opencog / atomspace

The OpenCog (hyper-)graph database and graph rewriting system
https://wiki.opencog.org/w/AtomSpace
Other
823 stars 234 forks source link

BindLink bug when only constant clauses #1089

Closed ngeiswei closed 7 years ago

ngeiswei commented 7 years ago

The following

(cog-bind (BindLink (Concept "A") (Concept "B")))

should return

(Set (Concept "B"))

because (Concept "A") is trivially satisfied but instead it returns

(Set)

Add a virtual clause (who knows it might have worked)

(cog-bind (BindLink (And (Concept "A") (Identical (Concept "A") (Concept "A"))) (Concept "B")))

yields the same wrong answer.

Ah, this one works! But certainly for the wrong reason...

(cog-bind (BindLink (And (Concept "A") (Not (Identical (Concept "A") (Concept "A")))) (Concept "B")))
ngeiswei commented 7 years ago

@linas I need this because sometimes backward inference chains don't have variables (that may tend to happen when the target is a tv query, but not only). I could skip entirely using a BindLink you may say but I still need to define preconditions that determine whether the inference is valid or not, and so I'm using the BindLink as a kind of if-then or when.

@linas I know you're busy, I'm taking care of it (already partially fixed on my local branch) but I wanted to let you know about it in case you have something to say.

ngeiswei commented 7 years ago

Aha, the following

(cog-satisfying-set (Get (Inheritance (Concept "A") (Concept "S"))))

returns

$7 = (SetLink
   (ListLink
   )
)

Given that a BindLink is the composition of Put and Get the behavior of the BindLink is indeed inconsistent. A BindLink with a trivial constant clause should be seen as getting a empty ListLink, such should indeed trigger the rewrite term.

ngeiswei commented 7 years ago

Hmm, by the same logic

(cog-satisfying-set (Get (Concept "A")))

should return (Set (List)) as above but it returns the empty set instead.

Anyway, I'm reviewing the code, I'll soon understand...

ngeiswei commented 7 years ago

The reason (cog-bind (BindLink (Inheritance (Concept "A") (Concept "B")) (Concept "C")) returns (Set (Concept "C")) is because InitiateSearchCB::neighbor_search (wrongly) successfully processes it as if it were a normal clause. It fails on a clause like (Concept "A") because its neighbors obviously fall out of the candidate set.

I think the correct way to fix that is to

  1. Fix InitiateSearchCB::neighbor_search to discard constant clauses altogether
  2. Upgrade InitiateSearchCB::no_search to support multiple constant and evaluatable clauses

@linas let me know if you think otherwise.

ngeiswei commented 7 years ago

If I disable this conditional (i.e. remove constants no matter what)

https://github.com/opencog/atomspace/blob/master/opencog/atoms/pattern/PatternLink.cc#L443

and disable this check

https://github.com/opencog/atomspace/blob/master/opencog/atoms/pattern/PatternLink.cc#L476

all unit tests pass. So that's my starting point... Again @linas let me know if you foresee that I'm going in the wrong direction.

linas commented 7 years ago

yes, OK, about removing line 443ff (and remove thee comments above it) and removing lines 476ff

This alters how the "empty" bind-link behaves, and I guess that's OK.

The behavior that you see with GetLink, and also PutLink, are "convenience" behaviors, intended to make using them easier and more convenient. So: with GetLink: if there is only one variable, it returns

(Set
   (ValueA..)
   (ValueB..)
  ...
)

instead of


(Set
   (List (ValueA..))
   (List (ValueB..))
  ...
)

The goal is just to avoid verbose results, nothing else. Likewise for Put.

linas commented 7 years ago

tweaks to InitiateSearchCB are indeed probably the correct fixes.

I recall a conversation about the empty set, on wikipedia, long ago:

There's no point in arguing with the empty-product crowd, Jersey Devil. You can point out to them all day long that the sentence "1 can be written as the product of 0 prime numbers" means the same thing as "1 cannot be written as the product of any prime numbers". And they won't listen, or they'll tell you you're wrong. When you ask them to write down 0 numbers and they don't do it, and then claim that they've already done it, and there's "nothing" to it, you can begin to grasp the difference between that kind of formalistic logic and the kind of thinking you and I do. DavidCBryant 19:03, 2 March 2007 (UTC)