Hi all,
In the "what language for a thinkbot" series, here is my idea from last night.
If you reverse AIML, you get a cheap logic engine.
Knowledge:
the sky is blue
the sky is big
Query:
the sky is *
Answer:
blue
big
It's like saying "the sky is what?"
With multiple constraints:
Knowledge:
the sky is blue
the sky is big
blue is a color
Query:
the sky is {1}
{1] is a color
Answer:
blue
If knowledge is stored in a tree (http://www.alicebot.org/documentation/matching.html), it can be pretty fast I guess.
It's easy to use and understand anyway, which is important if you believe in crowdsourcing.
Knowledge:
the sky is blue
the sky is big
blue is a color
Query:
the sky is {1}
{1] is a color
Answer:
blue
And, therefore:
Query:
the sky is {1}
{1] is a color
the sky is a color
Or, with {1}, {2}, {3}:
Query:
THE {1} IS {2}
{2] IS A {3}
THE {1} IS A {3}
Opinion: Reversing a finalized A.I. which has been tightly coupled for years, may not the best way to go for learning purposes, I think. It is more educational to start fresh.
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
8PLA.NET
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
No, {1} was supposed to be an lvar. I was asking "what can {1} be if the sky is {1} and {1} is a color?" My bad, I wasn't clear.
But it's not a logic engine yet, since we would need facts and rules to run a complete engine. So we could do it old style, like this...
[the Bing family]
John is the father of Miranda
Miranda is the father of Chandler
[generally speaking]
if you can say:
"man1" is the father of "man2"
"man2" is the father of "man3"
then you can say:
"man1" is the grandfather of "man3"
...and then query the engine (here lvars are between double quotes).
Or embed it in functions, like...
=> the Bing family
John is the father of Miranda
Miranda is the father of Chandler
{the grandfather of <name>}
considering: "man1" is the father of "man2"
considering: "man2" is the father of <name>
render: "man1"
[main]
about: the Bing family
print: Grandpa is (the grandfather of Chandler)
...or something.
Yes, or NodeJS!
So, I keep going. The following program...
=> way to school
right from home is town
up from town is school
up from home is woods
right from woods is school
{possible ways}
consider: "direction1" from home is "a place"
consider: "direction2" from "a place" is school
formulate: we can go "direction1" to "a place" and then "direction2" to school
render: <this>
[main]
print: (possible ways)
... should print:
we can go up to woods and then right to school
we can go right to town and then up to school
Right?
Yep, why not. It works too! :)
I used a new command "formulate" because I realized that answers to queries are actually arrays of arrays, say with lvars in columns and possibilities in rows. The "formulate" command makes a single sentence from one row. I never really digged (dug?) into logic programming before.
EDIT:
=> ways to school
east from home is town
north from town is school
north from home is woods
east from woods is school
{possible ways}
consider: "direction1" from home is "a place"
consider: "direction2" from "a place" is school
formulate: go "direction1" to "a place" and then "direction2" to school
render: <this>
[main]
consider: <ways to school>
for each item from: (possible ways)
print: We can <item>.
print: Done.
The "consider" command places things in a variable named <truth>. The "formulate" command works from what is in this <truth> variable. Then we would have a "putaside" command that removes stuff from <truth>, an "if" command that succeeds only if its argument can be found in <truth>, and a "while" command. And one last: the "store truth in" command that would store the current content of <truth> in another variable.
[ ] sections are commands
{ } sections are functions
=> sections are merely variables containing lists of strings
Code blocks end with a blank line. For now.
Yes, you're right. I feel we need recursion now. So, back to the family example, we could have:
=> the Bing family
Paul is the father of John
John is the father of Miranda
Miranda is the father of Chandler
{ancestors of <name>}
consider: "man1" is the father of <name> // put in "man1" the father of <name>
formulate: "man1" // produce man1's name in <this>
for each item from: <this> // if <this> is not empty
with: (ancestors of <item>) // append man1's ancestors to <this>
render: <this> // return <this>
[main]
consider: (the Bing family) // load the Bing family in <truth>
print: Ancestors of Chandler:
print: (ancestors of Chandler) // print the list of ancestors
put aside: (the Bing family)
Next step would be to find our way in a map. Let's make it a little bigger:
+----------+------------+----------+
| town | woods | SCHOOL |
+----------+------------+----------+
| HOME | mountain | beach |
+----------+------------+----------+
=> map
east from home is mountain
east from mountain is beach
north from home is town
north from mountain is woods
north from beach is school
=> map logic
east from "west place" is "east place"
north from "south place" is "north place"
[build entire map]
consider: <map logic>
formulate: west from "east place" is "west place"
consider: <this>
formulate: south from "north place" is "south place"
consider: <this>
put aside: <map logic>
[main]
consider: <map>
build entire map
Here with [build entire map] we deduce "west" and "south" links from existing "east" and "north" links. Now I'll try to build a way from home to school recursively.
EDIT: added a [main] section in the 2nd example
We split [consider] in [sufficient] and [necessary] because we need to express AND and OR.
[consider] is still here to accept new truths.
[make parents]
sufficient: "parent" is the father of "child"
sufficient: "parent" is the mother of "child"
formulate: "parent" is the parent of "child"
consider: <this>
If you're a father OR a mother, then you're a parent.
[make mom and dad]
necessary: "dad" is the parent of "child"
necessary: "dad" is a man
formulate: "dad" is the father of "child"
consider: <this>
necessary: "mom" is the parent of "child"
necessary: "mom" is a woman
formulate: "mom" is the mother of "child"
consider: <this>
If you're a parent AND you're a man, then you're a father.
If you're a parent AND you're a woman, then you're a mother.
[formulate] produces results, and then deletes every logic variable.
Pseudocode quoted from Zero:
Knowledge:
the sky is blue
the sky is big
Query:
the sky is *
Answer:
blue
big
Here is a version written in PHP:
<?php
/* Knowledge */
$knowledge=array(
"the sky is blue",
"the sky is big",
);
/* Query */
foreach($knowledge as $key=>$query)
{
preg_match("/the sky is (.*)/i",$query,$matches);
$matched[]=$matches;
}
/* Answer */
echo "Answer ".var_export($matched,TRUE)."\n";
?>
Answer array (
0 =>
array (
0 => 'the sky is blue',
1 => 'blue',
),
1 =>
array (
0 => 'the sky is big',
1 => 'big',
),
)