chainer and cog-execute ignore grounded atoms and assume erroneous (default) truth values

92 views
Skip to first unread message

Alexander Gabriel

unread,
Feb 26, 2020, 6:23:15 AM2/26/20
to opencog
Hiya everyone!

Here is another problem that I ran into. When a query contains grounded atoms those are ignored (not evaluated) when considering the output.
To demonstrate that I created this small example.


(use-modules (opencog) (opencog logger) (opencog exec) (opencog ure))
(define rbs (Concept "foo"))
(ure-set-maximum-iterations rbs 30)




(load-from-path "/home/rasberry/git/pln/opencog/pln/rules/propositional/crisp-conjunction-introduction.scm")
(Member (DefinedSchema "true-conjunction-introduction-2ary-rule") rbs)




(cog-logger-set-level! (cog-ure-logger) "debug")
(cog-logger-set-stdout! (cog-ure-logger) #t)


(define true (Concept "true"))
(define false (Concept "false"))


(define hungry (Concept "hungry"))
(define thirsty (Concept "thirty"))


(define alice (Concept "alice"))




(State (stv 1.0 1.0) (List alice hungry) true)
(State (stv 1.0 1.0) (List alice thirsty) false)




(define variables (VariableList
   
(TypedVariable
       
(Variable "person")
       
(Type "ConceptNode"))))




; NOTE: These returns (SetLink ) as they should, alice isnt thirsty, the second StateLink is evaluated correctly.
; (define target (And (State (List (Variable "person") hungry) true)
;                     (State (List (Variable "person") thirsty) true)))
; (cog-bc rbs target #:vardecl variables)
; (cog-execute! (Get variables target))




; NOTE: This doesnt evaluate the grounded second state and that ends up with an erroneous (stv 1.0 0.0) instead of (stv 0.0 1.0) which follows from the existence of (State (stv 1.0 1.0) (List alice thirsty) false). As a result it returns a result with second StateLink and AndLink at erroneous (stv 1.0 0.0). Is there a way to force the chainer to evaluate already grounded atoms as well?
(define target (And (State (List (Variable "person") hungry) true)
                   
(State (List alice thirsty) true)))
(cog-bc rbs target #:vardecl variables)


; This returns  (SetLink (ConceptNode "alice")), also ignoring the already grounded StateLink
(cog-execute! (Get variables target))



Shouldn't those grounded atoms be evaluated and considered?

Best,
Alex
ignoring_grounded_atoms.scm

Linas Vepstas

unread,
Feb 26, 2020, 1:22:29 PM2/26/20
to opencog
Hi Alex,

The answer: yes, or rather no, and there's a bug in your example.

The URE is built on top of the pattern matcher, and as mentioned earlier, the pattern matcher never alters truth values, and rarely looks at them, as it is only concerned with the presence/absence of patterns in the atomspace.  As a URE user, you are welcome to write rules that examine truth values, and alter them in any way that you want.  (I assume that one can also write URE rules that manipulate Values in general, but this may be cutting-edge, missing functions and utilities...)  (see also /examples/atomspace/formulas.scm which presents the recommended way of handling these kinds of computations.)

The bug is here:
(define target (And (State (List (Variable "person") hungry) true)
                   
(State (List alice thirsty) true)))

When you entered that, you just changed Alice's state. You didn't mean to, but atoms are globally-unique, and a StateLink can only have one state, so when the evaluator first sees that, it changes Alice's state, irrespective of it being wrapped up in the AndLink.

To add insult to injury, the pattern matcher completely ignores the second StateLink, because it has no variables in it, and thus is trivially present in the atomspace. I guess that the URE can still examine it, and do something with it's truth value, depending on which rule got triggered.

-- Linas



--
You received this message because you are subscribed to the Google Groups "opencog" group.
To unsubscribe from this group and stop receiving emails from it, send an email to opencog+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/opencog/5f6d23a9-a847-4fcb-85a2-a822cb1251f2%40googlegroups.com.


--
cassette tapes - analog TV - film cameras - you

Alexander Gabriel

unread,
Feb 26, 2020, 1:47:15 PM2/26/20
to opencog


Am Mittwoch, 26. Februar 2020 18:22:29 UTC schrieb linas:
Hi Alex,

The answer: yes, or rather no, and there's a bug in your example.

The URE is built on top of the pattern matcher, and as mentioned earlier, the pattern matcher never alters truth values, and rarely looks at them, as it is only concerned with the presence/absence of patterns in the atomspace.  As a URE user, you are welcome to write rules that examine truth values, and alter them in any way that you want.  (I assume that one can also write URE rules that manipulate Values in general, but this may be cutting-edge, missing functions and utilities...)  (see also /examples/atomspace/formulas.scm which presents the recommended way of handling these kinds of computations.)

But my goal wasn't to alter the value, just to have it looked up. But you know that already ;)
If you ask me, we should remove the assumption of the default truth value upon atom creation. Truth value definition should mean truth value changing, and not defining it should just create a pattern that one can feed to the system to query the truth values of a complex pattern. Unless there is another way to make a grounded complex query that I'm not aware of. (In which case please point me in the right direction ;)

The bug is here:
(define target (And (State (List (Variable "person") hungry) true)
                   
(State (List alice thirsty) true)))

When you entered that, you just changed Alice's state. You didn't mean to, but atoms are globally-unique, and a StateLink can only have one state, so when the evaluator first sees that, it changes Alice's state, irrespective of it being wrapped up in the AndLink.

To add insult to injury, the pattern matcher completely ignores the second StateLink, because it has no variables in it, and thus is trivially present in the atomspace. I guess that the URE can still examine it, and do something with it's truth value, depending on which rule got triggered.

If I could get my wish of definable patterns to query complex truth states, I'd expect the matcher to go collect those truth values. As it is now, I'd expect it to throw an error and tell people that they're changing the KB state. Silently changing the KB state as well as silently assuming the truth value of the grounded atoms is default (regardless of what it's defined to be) seems like the worst choice.

I tried an updated query that now also sets the truthvalue of the second StateLink, this confirms the truth value is seen as default in the AndLink:

(SetLink
  (AndLink
    (StateLink (stv 1.000000 1.000000)
      (ListLink
        (ConceptNode "alice") ; [6edb97fb269f42cf][1]
        (ConceptNode "hungry") ; [242c0228b7502b75][1]
      ) ; [bcc08bf365c085ef][1]
      (ConceptNode "true") ; [5ef6364983aee0cf][1]
    ) ; [84868fb1d3520298][1]
    (StateLink (stv 1.000000 1.000000)
      (ListLink
        (ConceptNode "alice") ; [6edb97fb269f42cf][1]
        (ConceptNode "thirty") ; [16526f8a1adbc29][1]
      ) ; [db02447762e2d55b][1]
      (ConceptNode "true") ; [5ef6364983aee0cf][1]
    ) ; [d3f761667ca45d1d][1]
  ) ; [d9a46b0c6194b7b8][1]
) ; [e6b35cc2f9480d13][1]

Best,
Alex

Linas Vepstas

unread,
Feb 26, 2020, 3:00:07 PM2/26/20
to opencog
On Wed, Feb 26, 2020 at 12:47 PM Alexander Gabriel <goo...@4d6.de> wrote:


Am Mittwoch, 26. Februar 2020 18:22:29 UTC schrieb linas:
Hi Alex,

The answer: yes, or rather no, and there's a bug in your example.

The URE is built on top of the pattern matcher, and as mentioned earlier, the pattern matcher never alters truth values, and rarely looks at them, as it is only concerned with the presence/absence of patterns in the atomspace.  As a URE user, you are welcome to write rules that examine truth values, and alter them in any way that you want.  (I assume that one can also write URE rules that manipulate Values in general, but this may be cutting-edge, missing functions and utilities...)  (see also /examples/atomspace/formulas.scm which presents the recommended way of handling these kinds of computations.)

But my goal wasn't to alter the value, just to have it looked up. But you know that already ;)

Well, but I didn't...

If you ask me, we should remove the assumption of the default truth value upon atom creation.

This is archaic; there's an idea that, if you ask for a truth value, you should get at least something, instead of throwing an error.  Anyway, if I recall, the default is not actually stored; its merely returned if there isn't already some other truth value.  So basically, if you get the default TV, that means there is no TV...

Truth value definition should mean truth value changing, and not defining it should just create a pattern that one can feed to the system to query the truth values of a complex pattern. Unless there is another way to make a grounded complex query that I'm not aware of. (In which case please point me in the right direction ;)

Well, but of course there is!  Just use the pattern matcher directly! (which you are already doing, in half of your examples). You are using the pattern matcher directly, whenever you say (cog-execute! (BindLink ...)) or (cog-execute! (GetLink ...))  That code path never goes through the URE, never looks at any rules.  

The URE is for chaining rules together in sequence -- think of it as a kind-of A-star search through the space of rules. By  contrast, the pattern-matcher (GetLink, BindLink) is a single-step, in a user-specified step direction.

You can even trigger truth-value rewrites with the pattern-matcher, several different ways, with the recommended best-practice being in /examples/atomspace/formulas.scm 

The bug is here:
(define target (And (State (List (Variable "person") hungry) true)
                   
(State (List alice thirsty) true)))

When you entered that, you just changed Alice's state. You didn't mean to, but atoms are globally-unique, and a StateLink can only have one state, so when the evaluator first sees that, it changes Alice's state, irrespective of it being wrapped up in the AndLink.

To add insult to injury, the pattern matcher completely ignores the second StateLink, because it has no variables in it, and thus is trivially present in the atomspace. I guess that the URE can still examine it, and do something with it's truth value, depending on which rule got triggered.

If I could get my wish of definable patterns to query complex truth states, I'd expect the matcher to go collect those truth values. As it is now, I'd expect it to throw an error and tell people that they're changing the KB state. Silently changing the KB state as well as silently assuming the truth value of the grounded atoms is default (regardless of what it's defined to be) seems like the worst choice.

OK, it sounds like you are frustrated, and for that I am sorry.

StateLink is by definition both stateful and "silent" and I don't really see any other way: some pop-up "Are you sure? Abort, retry, ignore."

The pattern matcher ignores truth values because that's just modular design. If you want to do something with truth values, that is an additional layer built on top of the core function. There are several reasons for this, besides modularity. One is the the lack of historical agreement about what the correct formulas are. Specifically, there was a battle: Pei Wang's NARS vs. Ben Goertzel's PLN. Which one has the correct rules? Maybe a third way? Maybe truth values should be truth-intervals? Maybe they should be histogrammed approximations to probability distributions learned from large datasets? Who knows?  Untangling basic search from valuations is one way to allow freedom for exploring different theories of valuation.

FWIW, this distinction is made in textbook classical logic, too.  One distinguishes P^Q from the possible assignments of T or F to P, Q.  The different possible assignments are called "valuations". This distinction leads to the difference between "syntactic" and "semantic" truth (single-turnstile vs double-turnstile). So, for example, for "syntactic truth", you assign T,F values to symbols, then evaluate the and-or-not expressions, turning the crank until evaluation terminates. For "semantic truth", you do NOT assign T,F values; you perform all manipulations abstractly, using rules of introduction and rules of retirement (and/or Hilbert-system style deductions).  Sometimes syntactic and semantic truth are the same, and sometimes they are not, these are the various satisfiability/unsatisfiability theorems of Skolem and Godel and etc. e.g. the upward and downward theorems of Lowenheim-Skolem. Untangling truth from the symbols that might carry some truth value is what makes logic so rich.

This email is too long, but also be aware of probability: thanks to Kolmogorov, we know that "and", "or", "not" corresponds to set-intersection, set-union and set-complement, in a very precise way.  So, the truth formulas for AndLink, OrLink: should they be ... ? boolean? set-intersection? maybe with Bayesian priors?  Which? it's a mess.
 
-- Linas

Alexander Gabriel

unread,
Feb 26, 2020, 3:39:35 PM2/26/20
to opencog


Am Mittwoch, 26. Februar 2020 20:00:07 UTC schrieb linas:


On Wed, Feb 26, 2020 at 12:47 PM Alexander Gabriel <goo...@4d6.de> wrote:


Am Mittwoch, 26. Februar 2020 18:22:29 UTC schrieb linas:
Hi Alex,

The answer: yes, or rather no, and there's a bug in your example.

The URE is built on top of the pattern matcher, and as mentioned earlier, the pattern matcher never alters truth values, and rarely looks at them, as it is only concerned with the presence/absence of patterns in the atomspace.  As a URE user, you are welcome to write rules that examine truth values, and alter them in any way that you want.  (I assume that one can also write URE rules that manipulate Values in general, but this may be cutting-edge, missing functions and utilities...)  (see also /examples/atomspace/formulas.scm which presents the recommended way of handling these kinds of computations.)

But my goal wasn't to alter the value, just to have it looked up. But you know that already ;)

Well, but I didn't...

If you ask me, we should remove the assumption of the default truth value upon atom creation.

This is archaic; there's an idea that, if you ask for a truth value, you should get at least something, instead of throwing an error.  Anyway, if I recall, the default is not actually stored; its merely returned if there isn't already some other truth value.  So basically, if you get the default TV, that means there is no TV...

Hrm, my problem isn't so much truth values (if you're referencing existing atoms, your references will hold the existing truth values anyway) but rather my inability to create structure without influencing the atomspace (the statelink issue, creating one to query messes with the one already present). I tried using a second atomspace for this, but ran into error messages on the way. (I haven't tried related atomspaces yet.)
 

Truth value definition should mean truth value changing, and not defining it should just create a pattern that one can feed to the system to query the truth values of a complex pattern. Unless there is another way to make a grounded complex query that I'm not aware of. (In which case please point me in the right direction ;)

Well, but of course there is!  Just use the pattern matcher directly! (which you are already doing, in half of your examples). You are using the pattern matcher directly, whenever you say (cog-execute! (BindLink ...)) or (cog-execute! (GetLink ...))  That code path never goes through the URE, never looks at any rules.  
Hrm, I don't understand..if I wanted to query a StateLink, I'd have to build one which would mess with already existing ones, wouldn't it? Could using a child atomspace avoid that issue but still give me results according to the state of the parent?


If I could get my wish of definable patterns to query complex truth states, I'd expect the matcher to go collect those truth values. As it is now, I'd expect it to throw an error and tell people that they're changing the KB state. Silently changing the KB state as well as silently assuming the truth value of the grounded atoms is default (regardless of what it's defined to be) seems like the worst choice.

OK, it sounds like you are frustrated, and for that I am sorry.

No, no. No worries. I'm not frustrated, just formulating my naive first idea of how this could maybe behave in a way that is less prone to make the non-expert scratch their head over their reasoning results.
 

StateLink is by definition both stateful and "silent" and I don't really see any other way: some pop-up "Are you sure? Abort, retry, ignore."

I might just have to give up my idea of being able to check the state of a specific Concept-State pair without using VariableNodes.
 

The pattern matcher ignores truth values because that's just modular design. If you want to do something with truth values, that is an additional layer built on top of the core function. There are several reasons for this, besides modularity. One is the the lack of historical agreement about what the correct formulas are. Specifically, there was a battle: Pei Wang's NARS vs. Ben Goertzel's PLN. Which one has the correct rules? Maybe a third way? Maybe truth values should be truth-intervals? Maybe they should be histogrammed approximations to probability distributions learned from large datasets? Who knows?  Untangling basic search from valuations is one way to allow freedom for exploring different theories of valuation.

I think we're talking past each other here. Probably due to a lack of awareness on my part of how all the different parts (matcher, URE, ...) interact in detail. I'm not overly concerned with what the pattern matcher does or doesn't do. I'm just imagining an interface to my KB which should allow me to do certain things. Like querying a specific statelink.
I somehow can't believe that's not possible. But I also can't think how it could be possible.


This email is too long, but also be aware of probability: thanks to Kolmogorov, we know that "and", "or", "not" corresponds to set-intersection, set-union and set-complement, in a very precise way.  So, the truth formulas for AndLink, OrLink: should they be ... ? boolean? set-intersection? maybe with Bayesian priors?  Which? it's a mess.

yeah, it is...it's a mix even in my little project.

Best,
Alex
 

Linas Vepstas

unread,
Feb 26, 2020, 5:24:45 PM2/26/20
to opencog
OK, so lets focus on StateLink, then.

Oh, but first a comment about the atomspace itself. If you were coding in C++ (and I don't recommend it, but just to clarify) ... if you were coding in C++, you would notice that Atoms correspond one-to-one with C++ objects. All the usual C++ behavior applies. You can, for example, create two Nodes with exactly the same name; as C++ objects, they would have different locations in RAM. You could, for example, place different TV's on each. which one you got depended on how you passed pointers around in your C++ code.

Now the atomspace: it exists for one reason: to force atoms into being globally unique. So if you put the first one into the atomspace, the atomspace says "thank you I will remember it". Put the second one in, it says "no thank you, I already got one, here's the one I have".

Neither the python nor the scheme (nor haskell) interfaces allow you to work with "bare" atoms; they are *always* in an atomspace, by the time you get to them. Even in C++, its dangerous to work with bare atoms: much of the C++ code assumes that they're in the atomspace, and will behave in undefined ways when not.

I'm only mentioning this because maybe it will help solidify your mental model of what the atomspace is: its just a trick to ensure global uniqueness. (global findability, global nameability...)

OK, so StateLink: by definition there can only be one "closed" StateLink at a time. By "closed", I mean "containing no variables". So, given (SomeAtom) there can only be one of these: (StateLink (SomeAtom) (OtherAtomWithNoFreeVariables))  but you can have as many of these as you want: (StateLink (SomeAtom) (AtomWithFreeVariables))

It's the atomspace that enforces the global uniqueness of the closed StateLink. Now, if you were coding in C++, you could violate this rule... but this would rapidly devolve into uncharted territory, posing all sorts of questions about how all sorts of arcane scenarios need to be handled.  If the correct answer was always obvious, maybe we could do it, but its .. not.

So ... how might you query a StateLink?  You have two, three mechanisms available.  One, in scheme, is this (I guess there's a python analog, not sure what it is). You would say

(cog-link 'StateLink (SomeAtom) (OtherAtom))

and this returns either the empty list, or the StateLink itself. The empty list, if that particular pairing is not currently in the atomspace.

The above cannot be used in patterns. The normal way of obtaining the current state would be to run  (cog-execute! (Get (State (SomeAtom) (Variable "x")))) and these can be composed in complex queries, for example:

(cog-evaluate!  (SequentialAnd
    (Equal (Concept "red light") (Get (State (Concept "stop-light") (Variable "x"))))
    (Not (Equal (Concept "car coming the other way") (Get (State (Concept "cross-street") (Variable "y"))))))
    ...
))

(The above does not use the URE!! Its just base atomspace functionality.)

Note that, conceptually, that (cog-link 'StateLink (SomeAtom) (OtherAtom)) is more-or-less equivalent to (Equal (OtherAtom) (Get (State (SomeAtom) (Variable "x"))))

Now, We could invent a brand new atom type, say, "IsInState" so that  you could write 

(cog-evalute! (IsInState (SomeAtom) (OtherAtom)))

and it evaluates to true/false.... but this offers very little advantage over just saying

(cog-evaluate! (Equal (OtherAtom) (Get (State (SomeAtom) (Variable "x")))))

which is a little more verbose, but works already.  Please keep in mind that explicit variable declarations are optional, when the query is unambiguous like this.  Finally, in scheme, you can always do this:

(define (is-in-state? A B) (Equal A (Get (State B) (Variable "x"))))

and use "is-in-state?" as if it were a real atom. It would work, in many/most cases. If you really need it to work in *all* cases, then something like this:

(DefineLink
    (DefinedPredicate "is in state")
    (Lambda
         (VariableList (Variable "a") (Variable "b"))
         (Equal (Variable "a") (Get (State (Variable "b") (Variable "x"))))))

which you would use like so:

(cog-evaluate!
    (EvaluationLink (DefinedPredicate "is in state")
         (List (Concept "red light") (Concept "stop light"))))

and that should work just fine. This might be overkill for what you are trying to do ... but it does work, and the intent is that, for complex situations, this is how you would do it.


-- Linas

--
You received this message because you are subscribed to the Google Groups "opencog" group.
To unsubscribe from this group and stop receiving emails from it, send an email to opencog+u...@googlegroups.com.

Alexander Gabriel

unread,
Feb 26, 2020, 5:39:41 PM2/26/20
to opencog
Oh! This is super helpful. Thank you so much! :)
I'm coding in python (and haven't seen a cog-link equivalent yet, but there might still be one.
But since I want to stick this into a complex pattern, I
will give (Get (State (Concept "stop-light") (Variable "x"))) a chance.
That'd be another problem solved :D 

Thanks again!

Nil Geisweiller

unread,
Feb 26, 2020, 11:07:03 PM2/26/20
to ope...@googlegroups.com
Hi Alex,

my recommendation is that you turn on the URE log and look at the
atomese code generated by the URE. This will help you to understand why
the URE has a hard time gluing together rules involving
executable/evaluatable atomese code.

Set the level to debug, and look for the strings

[DEBUG] [URE] Expanded forward chainer strategy:

as well as

[DEBUG] [URE] With inference tree:

to give you a graphical view of the inference.

(Sorry for the confusing terminology "forward chainer strategy" just
means "atomese inference tree").

Nil

On 2/26/20 1:23 PM, Alexander Gabriel wrote:
> Hiya everyone!
>
> Here is another problem that I ran into. When a query contains grounded
> atoms those are ignored (not evaluated) when considering the output.
> To demonstrate that I created this small example.
>
>
> |
> (use-modules (opencog)(opencog logger)(opencog exec)(opencog ure))
> (define rbs (Concept"foo"))
> (ure-set-maximum-iterations rbs 30)
>
>
>
>
> (load-from-path
> "/home/rasberry/git/pln/opencog/pln/rules/propositional/crisp-conjunction-introduction.scm")
> (Member(DefinedSchema"true-conjunction-introduction-2ary-rule")rbs)
>
>
>
>
> (cog-logger-set-level!(cog-ure-logger)"debug")
> (cog-logger-set-stdout!(cog-ure-logger)#t)
>
>
> (define true(Concept"true"))
> (define false(Concept"false"))
>
>
> (define hungry (Concept"hungry"))
> (define thirsty (Concept"thirty"))
>
>
> (define alice (Concept"alice"))
>
>
>
>
> (State(stv 1.01.0)(Listalice hungry)true)
> (State(stv 1.01.0)(Listalice thirsty)false)
>
>
>
>
> (define variables (VariableList
> (TypedVariable
> (Variable"person")
> (Type"ConceptNode"))))
>
>
>
>
> ;NOTE:Thesereturns (SetLink)asthey should,alice isnt thirsty,the second
> StateLinkisevaluated correctly.
> ;(define target (And(State(List(Variable"person")hungry)true)
> ;(State(List(Variable"person")thirsty)true)))
> ;(cog-bc rbs target #:vardecl variables)
> ;(cog-execute!(Getvariables target))
>
>
>
>
> ;NOTE:Thisdoesnt evaluate the grounded second state andthat ends up
> withan erroneous (stv 1.00.0)instead of (stv 0.01.0)which follows
> fromthe existence of (State(stv 1.01.0)(Listalice thirsty)false).Asa
> result it returns a result withsecond StateLinkandAndLinkat erroneous
> (stv 1.00.0).Isthere a way to force the chainer to evaluate already
> grounded atoms aswell?
> (define target (And(State(List(Variable"person")hungry)true)
> (State(Listalice thirsty)true)))
> (cog-bc rbs target #:vardecl variables)
>
>
> ;Thisreturns (SetLink(ConceptNode"alice")),also ignoring the already
> grounded StateLink
> (cog-execute!(Getvariables target))
> |
>
>
>
> Shouldn't those grounded atoms be evaluated and considered?
>
> Best,
> Alex
>
> --
> You received this message because you are subscribed to the Google
> Groups "opencog" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to opencog+u...@googlegroups.com
> <mailto:opencog+u...@googlegroups.com>.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/opencog/5f6d23a9-a847-4fcb-85a2-a822cb1251f2%40googlegroups.com
> <https://groups.google.com/d/msgid/opencog/5f6d23a9-a847-4fcb-85a2-a822cb1251f2%40googlegroups.com?utm_medium=email&utm_source=footer>.

Nil Geisweiller

unread,
Feb 26, 2020, 11:20:43 PM2/26/20
to ope...@googlegroups.com
On 2/26/20 9:59 PM, Linas Vepstas wrote:> Well, but of course there is! 
Just use the pattern matcher directly!
> (which you are already doing, in half of your examples). You are using
> the pattern matcher directly, whenever you say (cog-execute! (BindLink
> ...)) or (cog-execute! (GetLink ...))  That code path never goes through
> the URE, never looks at any rules.

BTW, the URE, really is just a way to form complex pattern matcher
queries, at least the backward chainer is exactly that. The forward
chainer on the other hand is more like an iterative chainer. I have
intended to update the code and the terminology to reflect that but I
didn't get a chance yet.

> The pattern matcher ignores truth values because that's just modular
> design. If you want to do something with truth values, that is an
> additional layer built on top of the core function. There are several
> reasons for this, besides modularity. One is the the lack of historical
> agreement about what the correct formulas are. Specifically, there was a
> battle: Pei Wang's NARS vs. Ben Goertzel's PLN. Which one has the
> correct rules? Maybe a third way? Maybe truth values should be
> truth-intervals? Maybe they should be histogrammed approximations to
> probability distributions learned from large datasets? Who knows?
> Untangling basic search from valuations is one way to allow freedom for
> exploring different theories of valuation.

I think this is another case for introducing Boolean Value, separated
from Simple Truth Value, to clearly show the distinction between
uncertain reasoning with PLN (or such) and crisp evaluation (from
evaluatable links) with the pattern matcher.

Nil

Linas Vepstas

unread,
Feb 27, 2020, 1:02:44 AM2/27/20
to opencog
On Wed, Feb 26, 2020 at 10:20 PM 'Nil Geisweiller' via opencog <ope...@googlegroups.com> wrote:


BTW, the URE, really is just a way to form complex pattern matcher
queries, at least the backward chainer is exactly that.

Ohh! So that is what the unifier is doing?  Gluing together a bunch of different rules, and then, I guess, running one giant pattern in the pattern matcher?  Oh, that's interesting!

I never quite understood what is going on, under the covers, and never quite recall reading any clear explanation.


I think this is another case for introducing Boolean Value, separated
from Simple Truth Value,

Yes. This was discussed in  https://github.com/opencog/atomspace/issues/2004 I don't think we got to the tipping point, where it's urgently needed. (that is, there were side issues that made it complicated). I'm also thinking about what I wrote for syntactic vs. semantic so I'm happy to keep that issue cooking in the oven a while longer.

--linas

Alexander Gabriel

unread,
Feb 29, 2020, 11:20:31 AM2/29/20
to opencog


Am Donnerstag, 27. Februar 2020 04:07:03 UTC schrieb Nil:
Hi Alex,

my recommendation is that you turn on the URE log and look at the
atomese code generated by the URE. 

Hi Nil,
I added the set_component method of the Logger class to the cython logger 
interface, but after setting that to URE and the level to DEBUG the logger 
still doesn't produce any output from the URE in python. My guess is that
the URE is using another instance of the logger and that adding a function
to the chainers to return that logger instance would be the easiest way 
to get access to it from python.
My python project is quite complex and is interacting with a simulation
environment in gazebo over ros, so debugging the reasoning in scheme 
doesn't really work as i can't reproduce the state of the atomspace reliably.

Do you know of a way to get access to the URE logger from python that 
already works?
Best, 
Alex 

Linas Vepstas

unread,
Feb 29, 2020, 4:02:40 PM2/29/20
to opencog
Alex,

FYI, There is "one weird little trick" that you might find useful.  Opencog comes with something called "the cogserver", which is a networked command-line shell. You can telnet into it, any number of times that you want, and from there, start either a scheme shell or a python shell (as many as you want) and then poke around, monitor status, whack things, etc. while the system is running.  All instances, both guile and python, share the same attached atomspace. Everything is fully multi-threaded and thread-safe, and, most importantly, crash-proof (a very handy property when running robots, or any jobs, for days/weeks on end.)  I've run this with ROS, pumping 50 messages/second into the atomspace, for hours/days on end.

In your case, you can start your system, connect to the cogserver, and turn logging on/off at any time, or do any other maintenance, stats collection, monitoring, etc.

There's two, maybe three ways to do this:
1) First, the "ugly" way. Start the cogserver executable first, and then get a python shell by saying  "rlwrap telnet localhost 17001".  The rlwrap thing enables arrow keys, command history.  This is ugly because the resulting python shell is not natural.

2) Start guile first, then say "(use-modules (opencopg cogserver)) (start-cogserver)" and then rlwrap-telnet. This way, you have a "natural" scheme shell, but still no natural python shell.

3) Start python first, then "import opencog.cogserver" then ??? and then rlwrap-telnet. This way you have a "natural" python shell, and the rest is accessible via telnet.  I'm not clear on ??? its under-documented.

-- Linas

--
You received this message because you are subscribed to the Google Groups "opencog" group.
To unsubscribe from this group and stop receiving emails from it, send an email to opencog+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/opencog/402a7064-035e-4cb6-85eb-484a058feac9%40googlegroups.com.

Nil Geisweiller

unread,
Mar 2, 2020, 2:07:09 AM3/2/20
to ope...@googlegroups.com, Alexander Gabriel
Hi Alex,

On 2/29/20 6:20 PM, Alexander Gabriel wrote:> Do you know of a way to
get access to the URE logger from python that
> already works?

Unfortunately I don't know a way, useless you call scheme from within
python of course. It looks like you'd need to create logger python
bindings and find a way to access the ure logger instance, as done in scheme

https://github.com/opencog/ure/blob/81fb2e8ecd330859d03fc1c20203f024b6ecf731/opencog/ure/URESCM.cc#L177-L180

Nil

>
> Best,
>
> Alex
>
> --
> You received this message because you are subscribed to the Google
> Groups "opencog" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to opencog+u...@googlegroups.com
> <mailto:opencog+u...@googlegroups.com>.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/opencog/402a7064-035e-4cb6-85eb-484a058feac9%40googlegroups.com
> <https://groups.google.com/d/msgid/opencog/402a7064-035e-4cb6-85eb-484a058feac9%40googlegroups.com?utm_medium=email&utm_source=footer>.

Alexander Gabriel

unread,
Mar 2, 2020, 8:09:46 AM3/2/20
to opencog


Am Montag, 2. März 2020 07:07:09 UTC schrieb Nil:
Hi Alex,

On 2/29/20 6:20 PM, Alexander Gabriel wrote:> Do you know of a way to
get access to the URE logger from python that
> already works?

Unfortunately I don't know a way, useless you call scheme from within
python of course. It looks like you'd need to create logger python
bindings and find a way to access the ure logger instance, as done in scheme

Hi Nil,
there is a python interface for the logger which I expanded to be able to set the component, but that interface creates its own logger singleton.
The URE code creates another logger singleton different from that. The two don't interact as far as I can tell.
I tried to set the URE logger to DEBUG through scheme code executed by python's scheme_eval() but that only produces output if the chainer is started in scheme, it doesn't when the chainer is started from python.

There are two ways out of this that I can see: make the URE logger singleton accessible from the chainer python interface, or change the chainer python bindings to use the python logger instead. The former is probably easier but messier.

Best,
Alex

 

>
> Best,
>
> Alex
>
> --
> You received this message because you are subscribed to the Google
> Groups "opencog" group.
> To unsubscribe from this group and stop receiving emails from it, send

Nil Geisweiller

unread,
Mar 4, 2020, 7:50:02 AM3/4/20
to ope...@googlegroups.com
On 3/2/20 3:09 PM, Alexander Gabriel wrote:
> Hi Nil,
> there is a python interface for the logger which I expanded to be able
> to set the component, but that interface creates its own logger singleton.

Oh, I see, so in order to use opencog's logger in Python ones needs to
first create one with

https://github.com/opencog/atomspace/blob/f7b99ec12d920f7a385cc477dd54abdc0a8768b1/opencog/cython/opencog/logger.pyx#L38-L47

Am I correct?

If so then it's badly done, it should allow the user to access OpenCog's
singleton, and ultimately other component's like the URE's.

Nil

> The URE code creates another logger singleton different from that. The
> two don't interact as far as I can tell.
> I tried to set the URE logger to DEBUG through scheme code executed by
> python's scheme_eval() but that only produces output if the chainer is
> started in scheme, it doesn't when the chainer is started from python.
>
> There are two ways out of this that I can see: make the URE logger
> singleton accessible from the chainer python interface, or change the
> chainer python bindings to use the python logger instead. The former is
> probably easier but messier.
>
> Best,
> Alex
>
>
>
> >
> > Best,
> >
> > Alex
> >
> > --
> > You received this message because you are subscribed to the Google
> > Groups "opencog" group.
> > To unsubscribe from this group and stop receiving emails from it,
> send
> > an email to ope...@googlegroups.com <javascript:>
> > <mailto:ope...@googlegroups.com <javascript:>>.
> <https://groups.google.com/d/msgid/opencog/402a7064-035e-4cb6-85eb-484a058feac9%40googlegroups.com?utm_medium=email&utm_source=footer
> <https://groups.google.com/d/msgid/opencog/402a7064-035e-4cb6-85eb-484a058feac9%40googlegroups.com?utm_medium=email&utm_source=footer>>.
>
>
> --
> You received this message because you are subscribed to the Google
> Groups "opencog" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to opencog+u...@googlegroups.com
> <mailto:opencog+u...@googlegroups.com>.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/opencog/2ecb9f33-8106-4113-8d5c-9dac39917151%40googlegroups.com
> <https://groups.google.com/d/msgid/opencog/2ecb9f33-8106-4113-8d5c-9dac39917151%40googlegroups.com?utm_medium=email&utm_source=footer>.

Alexander Gabriel

unread,
Mar 4, 2020, 11:55:07 AM3/4/20
to opencog

Oh, I see, so in order to use opencog's logger in Python ones needs to
first create one with

https://github.com/opencog/atomspace/blob/f7b99ec12d920f7a385cc477dd54abdc0a8768b1/opencog/cython/opencog/logger.pyx#L38-L47

Am I correct?

Hi Nil,

you can also use the singleton that file already creates for you on import

Best,
Alex

Alexander Gabriel

unread,
May 6, 2020, 8:30:57 AM5/6/20
to opencog

Hi Linas!

Am Mittwoch, 26. Februar 2020 22:24:45 UTC schrieb linas:
 If you really need it to work in *all* cases, then something like this:

(DefineLink
    (DefinedPredicate "is in state")
    (Lambda
         (VariableList (Variable "a") (Variable "b"))
         (Equal (Variable "a") (Get (State (Variable "b") (Variable "x"))))))

which you would use like so:

(cog-evaluate!
    (EvaluationLink (DefinedPredicate "is in state")
         (List (Concept "red light") (Concept "stop light"))))

and that should work just fine. This might be overkill for what you are trying to do ... but it does work, and the intent is that, for complex situations, this is how you would do it.

What actually did work, was this:

    someone = ConceptNode("bob")
    has_crate = ConceptNode("has crate")
    StateLink(someone, has_crate)

    DefineLink(
        DefinedPredicateNode("is in state"),
        LambdaLink(
             VariableList(VariableNode("target"), VariableNode("state")),
             EqualLink(SetLink(ListLink(VariableNode("target"), VariableNode("state"))), GetLink(StateLink(VariableNode("anything"), VariableNode("state"))))))

    query = EvaluationLink(DefinedPredicateNode("is in state"),
         ListLink(someone, ConceptNode("has crate")))

    results = evaluate_atom(atomspace, query)
    print(results)

Notice the addition of the SetLink which is necessary as the GetLink returns one.
Herein also lies the problem: This works fine if there is just one entity with a given state, but it fails when there are multiple entities with a given state because in this case the SetLink returned by the GetLink will contain multiple ListLinks and so the EqualLink evaluates to (0, 1).
I tried to get around this using a SubSetLink, but that runs into a NotImplemented error.

[2020-05-06 12:24:50:065] [ERROR] Either incorrect or not implemented yet. Cannot evaluate (SubsetLink
  (SetLink
    (ListLink
      (ConceptNode "bob" (stv 1.000000 1.000000)) ; [510da4194021b685][1]
      (ConceptNode "has crate") ; [7f11eb3c16f8beb0][1]
    ) ; [8983ace7aae6590b][-1]
  ) ; [e7b63e6f2f3e7452][-1]
  (GetLink
    (StateLink
      (VariableNode "anything") ; [7f082726ca4ddba3][1]
      (VariableNode "state") ; [38680c2d1603e9c8][1]
    ) ; [df8079f1c9baf09d][-1]
  ) ; [9e4a50ee0b3b95e2][-1]
) ; [cf2ff93ac449180b][-1] (/home/rasberry/git/atomspace/opencog/atoms/execution/EvaluationLink.cc:100)
Stack Trace:
2: basic_string.h:222   std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_is_local() const
3: Logger.cc:594   opencog::Logger::Error::operator()(char const*, ...)
4: exceptions.cc:54   opencog::StandardException::parse_error_message(char const*, __va_list_tag*, bool)
5: exceptions.cc:82   opencog::StandardException::parse_error_message(char const*, char const*, __va_list_tag*, bool)
6: exceptions.cc:169   opencog::SyntaxException::SyntaxException(char const*, char const*, __va_list_tag*)
7: EvaluationLink.cc:100 _Z20throwSyntaxExceptionbPKcz()
8: basic_string.h:222   std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_is_local() const
9: EvaluationLink.cc:299 bool_to_tv()
10: EvaluationLink.cc:999   opencog::EvaluationLink::do_evaluate(opencog::AtomSpace*, opencog::Handle const&, bool)
11: shared_ptr_base.h:729   std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count()
12: EvaluationLink.cc:868   opencog::EvaluationLink::do_eval_scratch(opencog::AtomSpace*, opencog::Handle const&, opencog::AtomSpace*, bool)
13: EvaluationLink.cc:999   opencog::EvaluationLink::do_evaluate(opencog::AtomSpace*, opencog::Handle const&, bool)
14: shared_ptr_base.h:758   std::__shared_count<(__gnu_cxx::_Lock_policy)2>::_M_swap(std::__shared_count<(__gnu_cxx::_Lock_policy)2>&)
15: [0x4bc9ba] ??() ??:0
16: [0x4ba036] ??() ??:0
17: [0x4eb32f] ??() ??:0
18: [0x4e5592] ??() ??:0
19: [0x4e3e46] ??() ??:0
20: [0x493ade] ??() ??:0
21: libc-start.c:325 __libc_start_main()
22: [0x4934a9] ??() ??:0

Traceback (most recent call last):
  File "./example3.py", line 99, in <module>
    results = evaluate_atom(atomspace, query)
  File "opencog/bindlink.pyx", line 21, in opencog.bindlink.evaluate_atom (/home/rasberry/git/atomspace/build/opencog/cython/opencog/bindlink.cpp:1268)
RuntimeError: Either incorrect or not implemented yet. Cannot evaluate (SubsetLink
  (SetLink
    (ListLink
      (ConceptNode "bob" (stv 1.000000 1.000000)) ; [510da4194021b685][1]
      (ConceptNode "has crate") ; [7f11eb3c16f8beb0][1]
    ) ; [8983ace7aae6590b][-1]
  ) ; [e7b63e6f2f3e7452][-1]
  (GetLink
    (StateLink
      (VariableNode "anything") ; [7f082726ca4ddba3][1]
      (VariableNode "state") ; [38680c2d1603e9c8][1]
    ) ; [df8079f1c9baf09d][-1]
  ) ; [9e4a50ee0b3b95e2][-1]
) ; [cf2ff93ac449180b][-1] (/home/rasberry/git/atomspace/opencog/atoms/execution/EvaluationLink.cc:100)



Do you have an idea on how to check for SetLink membership? Or am I doing something wrong?

Best regards,
Alex

Linas Vepstas

unread,
May 6, 2020, 1:42:33 PM5/6/20
to opencog
Let me reply by top-posting ,,,

> Do you have an idea on how to check for SetLink membership? Or am I doing something wrong?

Yes .. and yes...

I think you are mis-using the StateLink. The intent of the StateLink is to force an atomic one-and-only-one "membership", ever. Thus the example (State (Concept "traffic light") (Concept "red")) means that "traffic light"  can only have one color at a time, whereas lots of things can be red.  It's not symmetric -- only the first atom is the thing that has the state.  (Its also atomic, and can be accessed in multiple threads in a consistent, thread-safe manner)

You can count number of items in a link with ArityLink

scheme@(guile-user)> (use-modules (opencog) (opencog exec))
scheme@(guile-user)> (cog-execute! (Arity (Set (Concept "A") (Concept "B"))))
   (NumberNode "2")

(cog-evaluate! (GreaterThan (Arity (Set (Concept "A") (Concept "B"))) (Number 1)))
   (stv 1.000000 1.000000)

-- linas

--
You received this message because you are subscribed to the Google Groups "opencog" group.
To unsubscribe from this group and stop receiving emails from it, send an email to opencog+u...@googlegroups.com.

Alexander Gabriel

unread,
May 6, 2020, 1:51:37 PM5/6/20
to opencog

Am Mittwoch, 6. Mai 2020 18:42:33 UTC+1 schrieb linas:
I think you are mis-using the StateLink. The intent of the StateLink is to force an atomic one-and-only-one "membership", ever. Thus the example (State (Concept "traffic light") (Concept "red")) means that "traffic light"  can only have one color at a time, whereas lots of things can be red.  It's not symmetric -- only the first atom is the thing that has the state.  (Its also atomic, and can be accessed in multiple threads in a consistent, thread-safe manner) 

I'm aware. Let's say you have two traffic lights, each can only have one state/color at a time, but there are multiple traffic lights which can have the same color.
  (State (Concept "first traffic light") (Concept "red"))
  (State (Concept "second traffic light") (Concept "green"))
 

You can count number of items in a link with ArityLink

scheme@(guile-user)> (use-modules (opencog) (opencog exec))
scheme@(guile-user)> (cog-execute! (Arity (Set (Concept "A") (Concept "B"))))
   (NumberNode "2")

(cog-evaluate! (GreaterThan (Arity (Set (Concept "A") (Concept "B"))) (Number 1)))
   (stv 1.000000 1.000000)


Good to know, but that wasn't the goal. I want to check whether a specific traffic light is red.
I can get all the traffic lights that are red with a getlink,
but they'll be wrapped in a setlink, so I can't compare the set of many against my one traffic light node...unless I can check for something being an element of a setlink.

Best,
Alex

Linas Vepstas

unread,
May 6, 2020, 2:07:55 PM5/6/20
to opencog
OK, reply in-line below

On Wed, May 6, 2020 at 12:51 PM Alexander Gabriel <goo...@4d6.de> wrote:

Am Mittwoch, 6. Mai 2020 18:42:33 UTC+1 schrieb linas:
I think you are mis-using the StateLink. The intent of the StateLink is to force an atomic one-and-only-one "membership", ever. Thus the example (State (Concept "traffic light") (Concept "red")) means that "traffic light"  can only have one color at a time, whereas lots of things can be red.  It's not symmetric -- only the first atom is the thing that has the state.  (Its also atomic, and can be accessed in multiple threads in a consistent, thread-safe manner) 

I'm aware. Let's say you have two traffic lights, each can only have one state/color at a time, but there are multiple traffic lights which can have the same color.
  (State (Concept "first traffic light") (Concept "red"))
  (State (Concept "second traffic light") (Concept "green"))
 

You can count number of items in a link with ArityLink

scheme@(guile-user)> (use-modules (opencog) (opencog exec))
scheme@(guile-user)> (cog-execute! (Arity (Set (Concept "A") (Concept "B"))))
   (NumberNode "2")

(cog-evaluate! (GreaterThan (Arity (Set (Concept "A") (Concept "B"))) (Number 1)))
   (stv 1.000000 1.000000)


Good to know, but that wasn't the goal. I want to check whether a specific traffic light is red.
I can get all the traffic lights that are red with a getlink,
...
or you can get just one of them:
(Get (State (Concept "second traffic light")(Variable "x")))

but they'll be wrapped in a setlink,

It turns out that using SetLink for search results was a massive disaster. There is slow progress in fixing this. As of yesterday, MeetLink is the same as GetLink except it doesn't return a Set. Unfortunately, EqualLink doesn't yet know how to deal with this. I'll see if I can fix that today.   .. one at a time.
 
so I can't compare the set of many against my one traffic light node...unless I can check for something being an element of a setlink.

The Subset idea is a very interesting idea! Apparently, no one asked for this before :-/
but in retrospect, its obvious that it should have "just worked".  I will try to fix this maybe today. By "fix", I mean make the following work:

(cog-evaluate!  (Subset (Set (Concept "A")) (Set (Concept "A") (Concept "B"))))
and also
(cog-evaluate! (Member (Concept "A") (Set (Concept "A") (Concept "B"))))

getting this to run should be easy.

-- Linas
 

Best,
Alex

--
You received this message because you are subscribed to the Google Groups "opencog" group.
To unsubscribe from this group and stop receiving emails from it, send an email to opencog+u...@googlegroups.com.

Linas Vepstas

unread,
May 6, 2020, 3:55:40 PM5/6/20
to opencog
I just realized that the example below has a misleading, confusing bug in it.  (besides the missing SetLink) The fix is ...

On Wed, May 6, 2020 at 7:31 AM Alexander Gabriel <goo...@4d6.de> wrote:

Hi Linas!

Am Mittwoch, 26. Februar 2020 22:24:45 UTC schrieb linas:
 If you really need it to work in *all* cases, then something like this:

(DefineLink
    (DefinedPredicate "is in state")
    (Lambda
         (VariableList (Variable "a") (Variable "b"))
         (Equal (Variable "a") (Get (State (Variable "b") (Variable "x"))))))

Arghhh,  The get part of it should have been

(Get (Variable "x") (State (Variable "b") (Variable "x")))

so that the Lambda plugs in for the "b", and the Get does the search for the "x". Without this, the Get performs the searches for pairs "b" and "x" .. which was not the intent.  And I am guessing that this is what screwed up everything, and lead to thoughts of SubsetLink...

Sorry, this thinko on my part caused a lot of work on your part.  Oooops.

Anyway, I'm in the process of fixingin Subset and some other things so be sure to pull a new atomspace .. say in 12 hours...

--linas

 
--
You received this message because you are subscribed to the Google Groups "opencog" group.
To unsubscribe from this group and stop receiving emails from it, send an email to opencog+u...@googlegroups.com.

Alexander Gabriel

unread,
May 6, 2020, 3:59:56 PM5/6/20
to opencog


Am Mittwoch, 6. Mai 2020 20:55:40 UTC+1 schrieb linas:
I just realized that the example below has a misleading, confusing bug in it.  (besides the missing SetLink) The fix is ...

On Wed, May 6, 2020 at 7:31 AM Alexander Gabriel <goo...@4d6.de> wrote:

Hi Linas!

Am Mittwoch, 26. Februar 2020 22:24:45 UTC schrieb linas:
 If you really need it to work in *all* cases, then something like this:

(DefineLink
    (DefinedPredicate "is in state")
    (Lambda
         (VariableList (Variable "a") (Variable "b"))
         (Equal (Variable "a") (Get (State (Variable "b") (Variable "x"))))))

Arghhh,  The get part of it should have been

(Get (Variable "x") (State (Variable "b") (Variable "x")))

so that the Lambda plugs in for the "b", and the Get does the search for the "x". Without this, the Get performs the searches for pairs "b" and "x" .. which was not the intent.  And I am guessing that this is what screwed up everything, and lead to thoughts of SubsetLink...

yes that's it!
  

Anyway, I'm in the process of fixingin Subset and some other things so be sure to pull a new atomspace .. say in 12 hours...
Thank you! That will very convenient :)

Best,
Alex 
Reply all
Reply to author
Forward
0 new messages