Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass truth values from GroundedPredicateNodes to rule engine from pattern matcher. #1868

Closed
noskill opened this issue Sep 21, 2018 · 70 comments

Comments

@noskill
Copy link
Contributor

noskill commented Sep 21, 2018

We need to use rule engine along with virtual evaluation links.
Current pattern matcher implementation does not store truth value returned by grounded predicate.
Instead matched evaluation link keeps its default value of stv(1 0). And here matched means having mean tv more than hardcoded threshold of 0.5.

Example:

(use-modules (opencog logger))

(load-from-path "conjunction-rule-base-config.scm")


(Inheritance (stv 0.99 0.99) (Concept "BB1") (Concept "BoundingBox"))
; default truth value 1.0 0.0 give 1.0 0 for any inference 
(Inheritance (stv 0.99 0.99) (Concept "BB2") (Concept "BoundingBox"))

(define Red (Predicate "Red"))


(define (redness box ) 
    (stv 0.55 (random 1.0)) 
)

(define RedBox1
    (EvaluationLink
         (GroundedPredicateNode  "scm: redness")
         (Variable "$X")
    )
)

(define RedBox2
   (EvaluationLink (stv 0.56 0.7)
         Red
         (ConceptNode "BB2")
   )
)


; need to restrict the search by inheritance link
(define AndRedBox1 (AndLink RedBox1 (InheritanceLink (VariableNode "$X") (ConceptNode "BoundingBox")) ) )
; don't need to restrict the search by inheritance link here
; do it anyway
(define AndRedBox2 (AndLink RedBox2 (InheritanceLink (ConceptNode "BB2") (ConceptNode "BoundingBox"))  ))
   

(define (run-bc and-box) 
    (define result (conj-bc and-box))
    (display "\n")
    (display result)
    (display "truth value for the first element in the set\n")
    (display (cog-tv (car (cog-outgoing-set result))))
    (display "\n")
    result
)

(ure-logger-set-level! "fine")
(cog-logger-set-level! "fine")
(ure-set-num-parameter conjunction-rule-base "URE:maximum-iterations" 20)
(display "query with virtual evaluation links\n")
(run-bc AndRedBox1)
(display "\n\nquery with real evaluation links\n")
(run-bc AndRedBox2)

====================================================================
Current implementation gives (stv 1.000000 0.000000) for all and links for the first conjunction (run-bc AndRedBox1):

query with virtual evaluation links

(SetLink
   (AndLink
      (EvaluationLink
         (GroundedPredicateNode "scm: redness")
         (ConceptNode "BB2")
      )
      (InheritanceLink (stv 0.99 0.99)
         (ConceptNode "BB2")
         (ConceptNode "BoundingBox")
      )
   )
   (AndLink
      (InheritanceLink (stv 0.99 0.99)
         (ConceptNode "BB1")
         (ConceptNode "BoundingBox")
      )
      (EvaluationLink
         (GroundedPredicateNode "scm: redness")
         (ConceptNode "BB1")
      )
   )
)
truth value for the first element in the set
(stv 1.000000 0.000000)


query with real evaluation links

(SetLink
   (AndLink (stv 0.56 0.7)
      (EvaluationLink (stv 0.56 0.7)
         (PredicateNode "Red")
         (ConceptNode "BB2")
      )
      (InheritanceLink (stv 0.99 0.99)
         (ConceptNode "BB2")
         (ConceptNode "BoundingBox")
      )
   )
)
truth value for the first element in the set
(stv 0.560000 0.700000)

One possible fix is to store truth value somewhere at the end of DefaultPatternMatchCB::eval_term

// XXX FIXME: we are making a crsip-logic go/no-go decision
// based on the TV strength. Perhaps something more subtle might be
// wanted, here.
bool relation_holds = tvp->get_mean() > 0.5;
return relation_holds;

Then I get the expected result (stv 0.55 0.77770132)

======================================================================

(SetLink
   (AndLink (stv 0.55 0.77770132)
      (EvaluationLink (stv 0.55 0.77770132)
         (GroundedPredicateNode "scm: redness")
         (ConceptNode "BB2")
      )
      (InheritanceLink (stv 0.99 0.99)
         (ConceptNode "BB2")
         (ConceptNode "BoundingBox")
      )
   )
   (AndLink (stv 0.55 0.94014286)
      (InheritanceLink (stv 0.99 0.99)
         (ConceptNode "BB1")
         (ConceptNode "BoundingBox")
      )
      (EvaluationLink (stv 0.55 0.94014286)
         (GroundedPredicateNode "scm: redness")
         (ConceptNode "BB1")
      )
   )
)
truth value for the first element in the set
(stv 0.550000 0.777701)


query with real evaluation links

(SetLink
   (AndLink (stv 0.56 0.7)
      (EvaluationLink (stv 0.56 0.7)
         (PredicateNode "Red")
         (ConceptNode "BB2")
      )
      (InheritanceLink (stv 0.99 0.99)
         (ConceptNode "BB2")
         (ConceptNode "BoundingBox")
      )
   )
)
truth value for the first element in the set
(stv 0.560000 0.700000)
@noskill
Copy link
Contributor Author

noskill commented Sep 21, 2018

I would keep current behavior as default and pass threshold and flag to enable storing tv to pattern matcher when necessary. @linas @ngeiswei what do you think?

@linas
Copy link
Member

linas commented Sep 21, 2018

Several short remarks:

  1. You don't have to declare-before use. The below accomplishes nothing at all:
(Concept "BB1")
(Concept "BB2")
(Concept "BoundingBox")
  1. I don't quite understand what you are trying to do, and I am not convinced that you are using the URE correctly. Normally, one defines a set of rules, and then runs the URE. I don't see any rule-set being declared above. I don't see why you even need chaining.

  2. The pattern matcher does not store truth values, because it does not compute truth values, because it does not know how. The formulas used to compute truth values have to be specified. The above does not seem to contain any formulas that show how truth values should be computed.

  3. ... which is why your example is confusing. You say that the truth value should be this and such, but how can it even be possible to know what it should be? A formula that computes the correct truth value needs to be provided. Without such a formula, its impossible to know what it should be.

@linas
Copy link
Member

linas commented Sep 21, 2018

FWIW, there is an open task to make sure that the URE can work with formulas for any kind of values, and not just truth values. The formulas are "arbitrary", and user-specified. For example, PLN has a certain set of formulas, but one could also use a different set to implement Bayesian nets, etc.

A different open task would be to have the pattern matcher not use truth values at all, but to instead look at a single-bit true/false boolean flag in the atom. That would fully decouple the mechanics of the pattern matcher from the flow of truth through the network.

@linas
Copy link
Member

linas commented Sep 24, 2018

There are no formulas whatsoever in the code that you just referenced. Those to files are config files, nothing more.

Here is an example of a formula: lines 16-17 of
https://github.com/opencog/opencog/blob/master/opencog/pln/rules/propositional/formulas.scm#L17

Here's more:
https://github.com/opencog/opencog/blob/master/opencog/pln/rules/propositional/consequent-disjunction-elimination.scm see lines 75-122

Those formulas are specific to PLN. Other rule collections can and do use different formulas.

@Necr0x0Der
Copy link
Contributor

In this example, PLN is used to compute TV of a compound logical expression. It's absolutely valid usage of PLN/URE. And the problem is - if PredicateNodes are used then the output is exactly what should be expected from PLN, but if equivalent GroundedPredicates are used, then the result is incorrect meaning that the computed TVs are lost.

@linas
Copy link
Member

linas commented Sep 25, 2018

Hi @Necr0x0Der OK, so you are claiming that this is a PLN bug. I am not familiar with PLN, so I don't know. At any rate, PLN is not a part of the atomspace, its not a part of the pattern matcher, its not a part of the URE. So it seems like this is not even the correct github repo to report this bug.

I'm going to close this for now. You have to ask Nil to take a look at it.

The point is that PLN is a layer on top of the URE, and the URE is a layer on top of the pattern matcher. Suggesting some bizarro hack to the pattern matcher to fix a bug in PLN just sounds wrong to me. There are other users of the pattern matcher besides the URE, and there are other users of the URE besides PLN. You'd have to make a much much stronger case that the pattern matcher should work in some new or different kind of way.

@linas linas closed this as completed Sep 25, 2018
@Necr0x0Der
Copy link
Contributor

Necr0x0Der commented Sep 25, 2018

No, you didn't understand. This is not specifically PLN bug. You could call it an URE bug, because whatever rules you will use in URE, (truth) values calculated by GroundedPredicates will be lost during chaining. However, the problem can be easily fixed if Pattern Matcher will store truth values of GroundedPredicates after evaluating them. URE relies on PM as on interpreter of Atomese, so either PM should be extended, or URE should re-evaluate grounded predicates...

@ngeiswei ngeiswei reopened this Sep 25, 2018
@linas
Copy link
Member

linas commented Sep 25, 2018

Look, can you actually explain this in a way that is understandable? To me, this comes of as a big giant ball of confusion about how the system actually works, and I don't feel I have the time to try to figure out who is confused by what. There is nothing that you said, nor is there anything in the initial bug report, that indicates that there is any bug in the atomspace.

@linas linas closed this as completed Sep 25, 2018
@ngeiswei
Copy link
Member

@linas I was writing to explain, but I'm thinking maybe it's better to move to singnet instead, and we'll only ping you if it really ends up concerning the pattern matcher.

@linas
Copy link
Member

linas commented Sep 25, 2018

Look, I just now found out about singnet. Cassio made me an explicit promise that there won't be any development happening on singnet, and, as is clearly visible in github, there seems to be significant development happening there, so WTF. I'm really quite rather very unhappy about that.

It's good that there are more developers joining the project, but that means that it is time to start acting in a professional manner. Yes, the chaos of children's playgrounds can be fun, but it is not an effective way to build good software. This is especially critical at this point: if we get over-run by chaos and crazy ad-hoc patches, you'll just get a pile of shitty code. You cannot build a skyscraper out of random pieces of wood.

Let me be clear: this bug report sounds like some random confusion, with some incoherent proposal to change something for no good reason. That's not engineering, that's hacking. Hacked systems never work, they always fail. Millions of developers have been writing software since before the 1970's, and we know what happens to software when one makes random, incoherent hacks. Doing this in the singnet repo is a high-way to failure.

@ngeiswei
Copy link
Member

ngeiswei commented Sep 25, 2018

The issue may look confusing but it's not a reason to dismiss it, if we can't sort it out here, then what? We can use emails but github offers a better platform for that so... I'm all for being super authoritative about merging, but not about discussing, otherwise we'll never make progress... OK, sure having that issue closed doesn't mean it cannot be discussed, maybe we can discuss it here while being closed...

Cassio made me an explicit promise that there won't be any development happening on singnet

Are you sure? Maybe there was a misunderstanding there... But yeah of course the plan is to have singnet repos, wholly or partly being merged back to opencog.

@ngeiswei
Copy link
Member

sure having that issue closed doesn't mean it cannot be discussed

though I wonder, can people without admin rights post messages on closed issues?

@noskill
Copy link
Contributor Author

noskill commented Sep 25, 2018

I can

@ngeiswei
Copy link
Member

Oh, yeah, of course, if you can create and close you should be able to post to it (it seems closed PRs however cannot receive further commits, but that's independent of rights I suppose).

@linas
Copy link
Member

linas commented Sep 25, 2018

OK, we can discuss, but if the proposed change is to the pattern matcher (which seems to be what the proposal suggests) then the example code should invoke the pattern matcher only, and compare it to the existing pattern matcher behavior.

Somewhat off-topic, but: it has been nagging me for many many years that the pattern matcher touches truth values. I never really liked that. The thought is now crystallizing that atoms could have a single-bit crisp-logic boolean value, and that this bit could be used for all of the basic pattern matching needs. This way, other formulas, other behaviors could be moved to modules, and it would open the possibility of using other value types, besides truth values, with which to perform formula evaluations.

@ngeiswei
Copy link
Member

@noskill, small comment (till I get to understand the whole thing)

  1. you can also use the logger to display debug messages, for instance
(define (redness box ) 
    (display "redness called with: ")
    (display box)
    (display "\n")
    (stv 0.55 (random 1.0)) 
)

can be replaced by

(define (redness box ) 
    (cog-logger-info "redness called with ~a" box)
    (stv 0.55 (random 1.0)) 
)

having previously loaded the logger with

(use-modules (opencog logger))

That message will by default be printed in a opencog.log file, which is good if you don't want it to clobber the stdout, if you'd rather have it printed on stdout you may add

(cog-logger-set-stdout! #t)

See https://wiki.opencog.org/wikihome/index.php/Scheme#Logger for more info about the logger.

@ngeiswei
Copy link
Member

"trace" is not a logger level, see https://wiki.opencog.org/wikihome/index.php/Scheme#Change_the_log_level for valid log levels.

@ngeiswei
Copy link
Member

@noskill Please, simplify the issue as much as possible, for instance the display messages are not used at all, I guess they were useful to you for debugging, but they do not appear further in the issue so they are useless to the reader (and we can easily add debugging messages back ourselves if we need to).

It also looks like the conjunction could have 2 instead of 3 arguments.

Don't hesitate to simplify names as well, like replacing "BoundingBox" by "A", or "Herring" and "Red" by "P" and "Q", I mean, I don't know, do whatever you think is gonna simplify the issue, make as flowing as possible to read and understand.

@ngeiswei
Copy link
Member

Don't hesitate to use markdown goodies, like specifying that the code is in scheme (as I've just done), etc.

@noskill
Copy link
Contributor Author

noskill commented Sep 25, 2018

Thanks Nil! I simplified the example a bit more, leaving only one predicate - redness. I doesn't like one-letter names though..

@pennachin
Copy link
Member

@linas this is not true:

Look, I just now found out about singnet. Cassio made me an explicit promise that there won't be any development happening on singnet, and, as is clearly visible in github, there seems to be significant development happening there, so WTF. I'm really quite rather very unhappy about that.

You saw the plans for the fork, commented on them, and agreed with them in a call we had a couple of months ago.

@noskill
Copy link
Contributor Author

noskill commented Sep 25, 2018

@ngeiswei I made a unit test for this issue https://github.com/noskill/atomspace/blob/virt-eval-test/tests/query/CogBindTVUTest.cxxtest

@ngeiswei
Copy link
Member

I'm still exploring but it seems the problem could be that executing an evaluation link doesn't return the evaluation instance with the TV on it although evaluating that same link does return the correct TV.

So for instance, given

(define (sp x) (stv 0.55 0.55))
(define GP (GroundedPredicate "scm:sp"))
(define A (Concept "A"))
(define E (Evaluation GP A))

The following returns the correct TV

(cog-evaluate! E)
$3 = (stv 0.550000 0.550000)

But the following

(cog-execute! E)

returns E unchanged.

Do we want (cog-execute! E) to modify its TV?
My answer: I don't know.

@ngeiswei
Copy link
Member

Although, it's true that if one modifies the TV of E at some point (like in DefaultPatternMatchCB::eval_term as suggested by @noskill ) then we don't need to worry about the effect of executing E.

@linas
Copy link
Member

linas commented Sep 28, 2018 via email

@linas
Copy link
Member

linas commented Sep 28, 2018 via email

@linas
Copy link
Member

linas commented Sep 28, 2018 via email

@noskill
Copy link
Contributor Author

noskill commented Sep 28, 2018

I want to remove truth values from the pattern matcher. More and more, it is starting to feel like a design mistake.

@linas What then would be difference between atomese and prolog's family of languages? I somehow got into thinking that atomese is an extension of logic programming with probabilistic reasoning..

@noskill
Copy link
Contributor Author

noskill commented Sep 28, 2018

  1. It bloats disk-usage. If you save the dataset to disk, all of those TV's will get saved, slowing down atom store performance, atom fetch performance.

Can't we just use truth value during computation in rule engine? That's our use case. Currently we create child atomspace before request to rule engine, and destroy it afterwards.. There should be easier way to do some requests without bloating of atomspace.

@linas
Copy link
Member

linas commented Sep 28, 2018

What then would be difference between atomese and prolog's family of languages? I somehow got into thinking that atomese is an extension of logic programming with probabilistic reasoning..

Atomese has zero logic programming in it, and zero probabilistic reasoning. Atomese is a knowledge-representation system, plus a collection of tools and layers that allow you to implement logic programming, if you wish. Currently, we do not implement any logic programming system. (That might change someday) We do implement a probabilistic reasoning system, called PLN, but that lives in a different github repo. There's all sorts of neat stuff we should get around to implementing, but it takes .. time and effort.

@linas
Copy link
Member

linas commented Sep 28, 2018

Can't we just use truth value during computation in rule engine? That's our use case. Currently we create child atomspace before request to rule engine, and destroy it afterwards.. There should be easier way to do some requests without bloating of atomspace.

I don't understand what this is saying, so I can't answer it.

I am trying to replace truth values by just-plain values, which are more general and more flexible. However, since the atomspace is legacy code, there's still a lot of truth values everywhere. Removing all of them will take time.

The rule engine ... well ideally, it would accept, as input, a set of rules, a set of formulas, an atomspace containing the rules and formulas, and maybe a different atomspace containing the data. When a rule fires, it should cause a formula to run. The inputs to a formula should be generic values, not truth values, and the outputs should be generic values as well.

PLN is a specific set of rules and formulas, described in the PLN book. Other rules and formulas are possible.

One of the design goals of the atomspace is to allow simple, easy representation of "generic knowledge", and then allow many different kinds of AI algorithms to manipulate that knowledge. Examples of AI algorithms include: rule-engines, parsers, constraint-solvers, logic solvers, search algos, data-mining algos, neural nets, etc.

So far, only a few of these have been implemented. So far, its been kind-of awkward and kind-of slow. Just about any special-case system, e.g. from apache foundation, is going to outperform the atomspace+layers on top of it. The atomspace is trying to be a generic, neutral platform, for any AI algo, which is something no one else attempts to do. Whether th atomspace is successful in doing this ... is open to debate.

I'm pushing back on this bug report because the proposed solution is not generic. For example, people who want to run neural nets on top of the atomspace really wouldn't need or want the solution you propose.

@ngeiswei
Copy link
Member

ngeiswei commented Oct 1, 2018

I think @linas is right (I'm actually glad he shed the light on this, cause frankly I was blind).

However I also think that caching (or rather storing) TV in evaluation calls can be a desired feature, I just agree with @linas that this should not be in EvaluationLink.

I think the best would be to create a new link, say called CachedEvaluationLink (for lack of better name), inheriting from EvaluationLink. Such link would have an associated C++ class that would implement its own evaluation method, which would call EvaluationLink::evaluation() + store its TV.

Such CachedEvaluationLink may or may not live inside the atomspace repo. Technically, it could live in another repo. I would think that it is enough of a desired feature to live inside the atomspace repo, but that's another debate.

@ngeiswei
Copy link
Member

ngeiswei commented Oct 1, 2018

Maybe better names would be StoreTVEvaluationLink, which itself could be inherited by CachedTVEvaluationLink which would not only store the TV but reuse it if its confidence is above 0.

Or if EvaluationLink turns out to be generalized to work with Value instead of TV, it could be StoreValueEvaluationLink, etc.

@ngeiswei
Copy link
Member

ngeiswei commented Oct 1, 2018

I also agree with @linas that the pattern matcher should not require its EvaluationLink virtual links to output TVs, instead they should output boolean (maybe FalseLink or TrueLink, or some to-be-implemented BooleanValue). One could still have grounded schemata or grounded predicates within its pattern matcher query, but before these are used as matching preconditions they should be explicitly be turned into boolean output.

For instance instead of

Bind
  And
    Inheritance X beautiful
    Evaluation
      GroundedPredicate "py:nerdiness"
      X
  Inheritance X beautiful-nerd

we would have

Bind
  And
    Inheritance X beautiful
    GreaterThan
      Number 0.5
      TruthValueOf
        Evaluation
          GroundedPredicate "py:nerdiness"
          X
  Inheritance X beautiful-nerd

@noskill
Copy link
Contributor Author

noskill commented Oct 1, 2018

I don't understand what this is saying, so I can't answer it.

You said that storing tv in EvaluationLink would bload atomspace, but, at least in our usecase, we need EvaluationLink with tv only during ure's query computation. Anyway Nil's solution with CachedTVEvaluationLink would allow user to choose the desired behavior.

For example, people who want to run neural nets on top of the atomspace really wouldn't need or want the solution you propose.

We wrap neural network in EvaluationLink with GroundedPredicate. We populate atomspace with ConceptNodes with some data for neural network to perform classification.

(cog-execute! (BindLink
  (VariableList
    (TypedVariableLink (VariableNode "$B") (TypeNode "ConceptNode"))
    (TypedVariableLink (VariableNode "$X") (TypeNode "ConceptNode"))
  )
  (AndLink
    (InheritanceLink (VariableNode "$B") (ConceptNode "BoundingBox"))
    (InheritanceLink (VariableNode "$X") (ConceptNode "color"))
    (EvaluationLink (GroundedPredicateNode "py:runNeuralNetwork") (ListLink (VariableNode "$B") (ConceptNode "surfboard")) )
    (EvaluationLink (GroundedPredicateNode "py:runNeuralNetwork") (ListLink (VariableNode "$B") (VariableNode "$X")) )
  )
  (ListLink (Variable "$B") (Variable "$X") (ConceptNode "surfboard"))
)
)

In order to use rule engine we need this evaluation link

    (EvaluationLink (GroundedPredicateNode "py:runNeuralNetwork") (ListLink (VariableNode "$B") (ConceptNode "surfboard")) )

to have a truth value. @linas Perhaps we took an unexpected path to integrate atomspace with neural networks. What is the expected one?

@ngeiswei
Copy link
Member

ngeiswei commented Oct 1, 2018

The other option (alternatively to having a CachedEvaluationLink) is to use the URE. Since you're using the URE to begin with it shouldn't be problematic. You could have a rule that assigns the TV on a given grounded predicate evaluation.

For instance, the rule

Evaluation
  <grounded-predicate>
  <args>
|-
Evaluation <TV>
  <grounded-predicate>
  <args>

such that TV is the result of grounded-predicate applied to args.

Let's call this rule set-grounded-predicate-evaluation-tv-rule. Then the job of the URE would be to build the following inference tree

ExecutionOutput
  GroundedSchema "fuzzy-conjunction-introduction-formula"
  List
    And
      ExecutionOutput
        GrouhndedSchema "set-grounded-predicate-evaluation-tv-formula"
        Evaluation
          GroundedPredicate "py:neural-network"
          Concept "BB1"
      Inheritance
        Concept "BB1"
        Concept "red"

See what I mean?

@ngeiswei
Copy link
Member

ngeiswei commented Oct 1, 2018

Also, if it wasn't clear, let me remind that cog-evaluate! doesn't create atoms or change TVs, unless this is implemented as a side effect by the user (as I suggested here). cog-execute! on the other hand does create atoms or change TVs. So if you wish to do that in a way that is consistent with the current pattern matcher, you should execute a grounded schema, which is what by proposal above suggests.

@noskill
Copy link
Contributor Author

noskill commented Oct 1, 2018

I am not that familiar with ure yet, is there a way to force ure to apply this set-grounded-predicate-evaluation-tv-rule to every evaluation link with grounded predicate node it encounters? I mean URE could produce some result without using this rule at all.

For now I am quite happy with setting tv from within grounded predicate. This would allow us, as Alexey noted, to return different value to pattern matcher. This way we can process in URE evaluation links with low associated truth values. But i still think that better solution would be to implement CachedEvaluationLink and to provide the threshold to pattern matcher call. Here "better" means providing more options to change the system's behavior.

@ngeiswei
Copy link
Member

ngeiswei commented Oct 1, 2018

@noskill said

This would allow us, as Alexey noted, to return different value to pattern matcher

Oh, you mean that it may return something above 0.5 while setting the TV to its really value, that way you have more control over when the PM would allow a match?

Regarding forcing the URE, I think yes, it's possible to force the URE using inference control rules. But otherwise, what can be done is simply giving the URE enough evaluations and adding preconditions in the PLN conjunction rule to dismiss conjunctions if not all arguments have non null confidence.

@ngeiswei
Copy link
Member

ngeiswei commented Oct 1, 2018

Regarding forcing the URE, I think yes, it's possible to force the URE using inference control rules

this would not skip the intermediary inference tree though... It would be nice we have something that allows that. One way actually would be to gather inference trees, wrap them as rules that you'd be able to re-use then to skip inference steps...

@noskill
Copy link
Contributor Author

noskill commented Oct 1, 2018

@ngeiswei Yes, we want to be able to compute truth value for such and links:

   (AndLink 
      (EvaluationLink (stv 0.35 0.45)
         (GroundedPredicateNode "scm: redness")
         (ConceptNode "B")
      )
      (InheritanceLink (stv 0.45 0.45)
         (ConceptNode "red")
         (ConceptNode "color")
      )
   )

Current pattern matcher implementation would throw out the EvaluationLink with (stv 0.35 0.45), but unexpectedly would not throw out the IheritanceLink. I thought that IheritanceLink wouldn't be stored as well, but since it works, setting tv from within the grounded predicate seems to give same result as would providing threshold for pattern matcher.. I am not sure about other link types..

@ngeiswei
Copy link
Member

ngeiswei commented Oct 1, 2018

Interesting, so what I thought was a bug is actually a feature here...

@Necr0x0Der @linas this is another reason to have the pattern matcher support boolean predicate, that what one can choose how what threshold to apply over strength or confidence, instead of having a fixed 0.5 threshold over strength.

@linas
Copy link
Member

linas commented Oct 1, 2018

I think that the BindLink is mal-formed. I believe that what you want is this:

(BindLink
  (VariableList
    (TypedVariableLink (VariableNode "$B") (TypeNode "ConceptNode"))
    (TypedVariableLink (VariableNode "$X") (TypeNode "ConceptNode"))
  )
  (AndLink    ;; This is the premise that must be satisfied for a "match" to occur.
    (InheritanceLink (VariableNode "$B") (ConceptNode "BoundingBox"))
    (InheritanceLink (VariableNode "$X") (ConceptNode "color"))
  )
  ;; Below is the conclusion. The pattern matcher explores all possible values for $B and $X 
  ;; then it plugs them into the below, and then causes "py:runNeuralNetwork" to run.  The 
  ;; "py:runNeuralNetwork" should set the TV, and possibly set other values, e.g. a time-stamp,
  ;; the number of layers in the net, the size of the hill-climbing delta, and your favorite
  ;; hockey team.
  (EvaluationLink (GroundedPredicateNode "py:runNeuralNetwork") 
       (ListLink (VariableNode "$B") (VariableNode "$X") (ConceptNode "surfboard")) )

The pattern matcher simply finds all possible variable groundings that satisfy the premise, and places those groundings into the conclusion.

@linas
Copy link
Member

linas commented Oct 1, 2018

Re this comment:

Current pattern matcher implementation would throw out the EvaluationLink with (stv 0.35 0.45), but unexpectedly would not throw out the InheritanceLink.

The pattern matcher does NOT look at truth values on atoms. Instead, it is simply looking to see if an atom exists, or not. If the atom exists, then its a match. If it does not exist, then .. well, it doesn't exist. Existence is just a crisp true/false thing.

There are complications. For example, the GreaterThanLink X Y exists "virtually" whenever X is greater than Y, else it doesn't. Since it is impossible to store the infinite number of all possible X,Y pairs, this link is instead evaluated at match-time, to determine if it "exists", or not.

A "relation", in the strict, mathematical sense, is a function of N arguments, that, when evaluated, returns 1 or 0. Relations never return fractions, floats, or any other kind of value. (off-topic, but important: a "relational algebra" implements a collection of relations. SQL is a practical kind of easy-to-use relational algebra system. Relations are important.)

So: GreaterThan is a relation between numbers that has to be virtual, because there are an infinite quantity of numbers. There are other relations that have to be "vritual", i.e. dynamically-evaluatable at run-time. Today, these are handled with GroundedPredicateNode.

In the future, Perhaps we should instead use a RelationPredicateNode instead of a GroundedPredicateNode. Perhaps it should be a BooleanPredicateNode. Perhaps, instead of writting

(EvaluationLink (GroundedPredicateNode "py:foo") (List ...))

we should instead write

(ExistsLink (BooleanPredicateNode "py:foo") (List ...))

which evaluates to a crisp true/false when it is used in the premise-side of a BindLink. It is an accident of history that we did not do this from the beginning. This accident of history is now causing confusion.

@noskill
Copy link
Contributor Author

noskill commented Oct 1, 2018

@linas Our intention here is to decrease computational complexity:

  (AndLink
    (InheritanceLink (VariableNode "$B") (ConceptNode "BoundingBox"))
    (InheritanceLink (VariableNode "$X") (ConceptNode "color"))
    (EvaluationLink (GroundedPredicateNode "py:runNeuralNetwork") (ListLink (VariableNode "$B") (ConceptNode "surfboard")) )
    (EvaluationLink (GroundedPredicateNode "py:runNeuralNetwork") (ListLink (VariableNode "$B") (VariableNode "$X")) )
  )

Here if pattern matcher finds that evaluation link (EvaluationLink (GroundedPredicateNode "py:runNeuralNetwork") (ListLink (ConceptNode "BB-11") (ConceptNode "surfboard")) ) doesn't match, it won't consider this (ConceptNode "BB-11") anymore.

If we pass all variables to one evaluation link this optimization won't happen.

@linas
Copy link
Member

linas commented Oct 1, 2018

decrease computational complexity:

Ahh. Well, the pattern matcher is pretty fast: its going to be thousands of times faster than any neural net. Its going to be ten times faster than calling a python function. Doing this will in fact slow things down: the pattern matcher is still forced to explore all possible groundings, because it cannot guess what your "py:runNeuralNetwork" actually does; its a black-box.

@noskill
Copy link
Contributor Author

noskill commented Oct 1, 2018

I checked and pattern matcher does not call one evaluation link if other doesn't match, it doesn't respect the order in the AndLink though.

@linas
Copy link
Member

linas commented Oct 1, 2018

it doesn't respect the order

The AndLink is an unordered link. SequentialAnd is ordered.

@linas
Copy link
Member

linas commented Oct 1, 2018

... except the pattern matcher doesn't respect SequntialAnd's either. What the AndLink is doing is specifying a set of clauses, which must be satisfied. The clauses form a graph; graphs do not have an "order".

@noskill
Copy link
Contributor Author

noskill commented Oct 1, 2018

Thanks Linas! SequentialAnd seems to be respected by pattern matcher, at least for Evaluation links. I guess pattern matcher first considers inheritance links, then evaluation links. This can be usefull.

@linas
Copy link
Member

linas commented Feb 2, 2019

Closing; I don't see any work items here, and I think all issues have been resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants