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

Storing PLN formulas in the AtomSpace #2015

Merged
merged 28 commits into from
Jan 29, 2019
Merged

Storing PLN formulas in the AtomSpace #2015

merged 28 commits into from
Jan 29, 2019

Conversation

linas
Copy link
Member

@linas linas commented Jan 26, 2019

The current PLN implementation encodes all formulas in scheme, and uses GPN's to apply those formulas. This is an experimental system to hold those formulas in the AtomSpace, instead. This has two benefits:

  • The formulas can be obtained from some learning system, e.g. MOSES, or pattern-mining, or neural nets, or whatever, without any need to convert them to scheme.

  • It's faster; this avoids the 50-microsecond overhead of getting into and out of the guile interpreter.

Take a look at the example "formulas.scm". It works.

This is a demo of one of the two ideas described in #2004

@linas linas mentioned this pull request Jan 26, 2019
linas added 3 commits January 26, 2019 20:13
Fixes to the Reduct code needd to continue with the examples
@ngeiswei
Copy link
Member

ngeiswei commented Jan 27, 2019

That's cool! Though I'm not sure about the PredicateFormulaLink name, and I would use a slightly different construction.

  1. Have a SimpleTruthValueLink that takes 2 number nodes and create a simple TruthValue.
  2. Wrap the whole thing in a regular LambdaLink (or PredicateLambdaLink if we want to be more specific, can be easier for type checking, etc).

Then your Compute TV = (1-sA*sB, cA*cB) example would look like

(cog-evaluate!
	(Evaluation
		; Compute TV = (1-sA*sB, cA*cB)
		(PredicateLambda
			(VariableList              ; optional
				(Variable "$X")
				(Variable "$Y"))
			(SimpleTruthValue
				(Minus
					(Number 1)
					(Times
						(StrengthOf (Variable "$X"))
						(StrengthOf (Variable "$Y"))))
				(Times
					(ConfidenceOf (Variable "$X"))
					(ConfidenceOf (Variable "$Y")))))
		(List
			(Concept "A")
			(Concept "B"))))

@ngeiswei
Copy link
Member

The PredicateLambda construct would work for any clear box
predicate, regardless of its co-domain. But we may prefer to
explicitly specify its co-domain in its name (easier for type
checking, etc), which would then look very close (though not
identically, I'll explain) to your PredicateFormula. So for instance
for simple TV we'd have

(SimpleTruthValuePredicateScope
	(VariableList              ; optional
		(Variable "$X")
		(Variable "$Y"))
	(Minus
		(Number 1)
			(Times
				(StrengthOf (Variable "$X"))
				(StrengthOf (Variable "$Y"))))
	(Times
		(ConfidenceOf (Variable "$X"))
		(ConfidenceOf (Variable "$Y"))))

I use the name

SimpleTruthValuePredicateScope

instead of

SimpleTruthValuePredicateLambda

because LambdaLink has only one body while this construct has
two. So it's essentially PredicateFormula but there is only one
(optional) variable declaration because the argument list is gonna be
the same anyway. And should be clear that it is syntactic sugar of the
previous construct
#2015 (comment)

It's the same idea as

ImplicationScope
  <vardecl>
  <implicant>
  <implicand>

which is syntactic sugar for

Implication
  Lambda
    <vardecl>
    <implicant>
  Lambda
    <vardecl>
    <implicand>

@linas
Copy link
Member Author

linas commented Jan 27, 2019

Hi @ngeiswei It is very late here, and time for me to go to bed. I just now pushed one more fix, and extended the demo slightly. Please take a look at the last part of the example.

It works, but there is one kind-of annoying thing that I don't like very much: the formula "uses up all the space" that the PredicateNode would normally have. For example, you can either have this:

EvaluationLink
    PredicateNode "has the color red"
    ....

or you can have this

EvlautatiionLink
   PredicateFormula ... 

but you can't have both. I kind of want to have both. I am not sure how. Maybe this?

DefineLink
   DefinedPredicateNode "has a reddish color"
    PredicateFormula ...

That should work, but it feels ugly to me. Not sure. Maybe. I dunno. Not entirely happy with that. Please think about it while I sleep.

(Instead of DefineLink, maybe StateLink ??? Yuck, but also StateLink is mutable; DefineLink is not mutable.)

I will read your other comments tomorrow. But regrading Lambda and Scope -- you have this habit of obsessing about Lambda and Scope and I really do not understand why. They are handy for computing things, but actually putting them into everything, using them everywhere just seems to make everything complicated and verbose, and I don't see why they are needed. I don't understand why you want to use them so much. They seem like overkill for a simple problem.

@linas
Copy link
Member Author

linas commented Jan 27, 2019

Also, I don't want to discuss here, but rather elsewhere --- I still do not understand ImplicationScope. It seems to be the exact opposite of every book I have ever read about logic. It just smells like a non-well-formed expression. Can you point at a PDF or a book or a wikipedia which explains what it is?

@linas
Copy link
Member Author

linas commented Jan 28, 2019

OK, so SimpleTruthValueLink seems to have no particular defining characteristics, other than it wraps some expression that might evaluate to two doubles.That doesn't seem very special. The problem with PredicateLambda is we don't know how many arguments it might have -- Its varargs. When the number of arguments is variable and unknown, I've been using FunctionLink.

What PredicateFormula does is explicitly set the TV of the EvaluationLink its contained in. Otherwise it does not constrain the number and type of arguments (For example, a formula could contain an EqualLink that compares non-numeric things)

At this time, PredicateFormula only creates SimpleTV's, and so maybe could be called SimpleTVPredicateFormula. But maybe there are other ways of handling other TV types; I'd rather leave this as an open, undecided question, rather than prematurely engineering something that might be inadequate, later.

@linas
Copy link
Member Author

linas commented Jan 28, 2019

@ngeiswei the #1 most important question is: can PLN rules be written with these formulas? Is this actually usable? If not, what are the issues? I can't really tell if this is usable, in practice.

@bgoertzel
Copy link
Contributor

bgoertzel commented Jan 28, 2019 via email

@linas
Copy link
Member Author

linas commented Jan 28, 2019

Hi @bgoertzel There does exist a RandomNumberNode and also a RandomStreamValue and both of these can be used to generate samples. There's an example program, but that's it -- a flips a biased coin 0.7 vs 0.3 one thousand times, and actually gets 0.7 but no one has tried anything fancier.

@linas
Copy link
Member Author

linas commented Jan 28, 2019

@bgoertzel Here, this example:

https://github.com/opencog/atomspace/blob/master/examples/atomspace/random-choice.scm

It was written circa 2015 as a how-to-do probabilistic-programming demo for OpenCog. That was then .. now I would recommend using values instead of Atoms as the probability sources; this avoids the overhead of stuff random NumberNodes into the atomspace, where they basically pollute the atomspace and do nothing actually useful.

opencog/atoms/execution/EvaluationLink.cc Outdated Show resolved Hide resolved
examples/atomspace/formulas.scm Outdated Show resolved Hide resolved
@@ -505,6 +507,29 @@ TruthValuePtr EvaluationLink::do_eval_scratch(AtomSpace* as,
{
return evelnk->getTruthValue();
}
else if (PREDICATE_FORMULA_LINK == t)
{
std::vector<double> nums;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this block of code also be replaced by do_formula() call?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe. Let me look. I think it can be simpler, because it has no variables.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to keep as-is; to avoid passing in an empty list of arguments

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. It is not clear for me why list of arguments is empty here? Is it correct that do_eval_scratch is called only after variables substitution?
  2. What is wrong with passing empty list of arguments if this will reduce the code bloat?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Yes, do_eval_scratch is called after argument substitution and reduction has been made. (There is a mostly-finished "lazy execution" code path that is unused because GPN/GSN's don't know how to be lazy. Hmm. I should look at that again.

  2. Yes, you are right. The two code paths are similar, one is longer and more complicated. The decision to merge them seems very close to being a coin-flip; there are benefits and disadvantages, they seem to cancel each out out.

@linas linas merged commit 5db67ab into opencog:master Jan 29, 2019
@linas linas deleted the vc branch January 29, 2019 16:59
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

Successfully merging this pull request may close these issues.

4 participants