Dan Braddock
2008-02-20
I tried replacing the contents of the family_relations/family.py with names from my own family tree including three generations.
I found that when I ran the test.py program as specified in the README file I did not get the results I expected.
What I got was the name of the member I selected followed by each of the members in the family tree (except the one I selected).
The output looked something like this:
>>> test.test()
doing proof
Tyler Richard
Tyler Gail
Tyler Daniel
...
done
>>>
How would I obtain just Tyler's first cousins?
Since the following statement in the test.py file actually produces the printed output, an explanation of how it works would be helpful.
for (ans,), plan in engine.prove_n('example', 'how_related', ('Tyler',), 1):
# print "prove:", ans
print memberName, ans
Wow would I produce a list including the actual relationship between the two names on each line?
Any help would be appreciated.
Bruce Frederiksen
2008-02-22
Two things to note here.
1. It looks like you've omitted the last line of the "for" statement (line 88 in the original test.py). This example uses plans to print the type of relationship. This is a poor use of plans, but with this example, I had little other choice...
2. Given that the executed plan produces the relationship, there is no way to directly ask pyke for just first cousins. Had the examples been written to return the relationship in an additional pattern variable for the "how_related" goal, this would have been possible. Of course, you can do your own filtering of relationships by executing the various plans returned and only printing the first cousins; but this would run more slowly than being able to ask pyke just for first cousins directly.
An explanation of the "for" statement:
engine.prove_n('example', 'how_related', ('Tyler',), 1) means:
1. Try to prove 'example.how_related' using the arguments ('Tyler',) and 1 additional pattern variable. Thus, the goal to be proved is:
1.1. example.how_related(Tyler, $ans1).
2. Using "prove_n" rather than "prove_1" means that you're interested in all proofs, not just the first one.
3. For each proof, a two tuple is returned:
3.1. The first element of the returned tuple is a tuple of the values of the added pattern variables for which the goal is true. Since you specified 1 pattern variable, this will be a singleton tuple.
3.2. The second element is the "plan". This is just a python function that you can execute as many times as you like. In this example, the plan doesn't take any parameters and returns a string describing the relationship.
Other examples of the prove_n function for this example are:
1. engine.prove_n('example', 'how_related', ('Tyler', 'Gail'), 0). This expands to:
1.1. example.how_related(Tyler, Gail)
and probably only has one proof. Since the number of pattern variables is 0, the first element of the two tuple returned from prove_n will be an empty tuple. The plan will tell how Tyler and Gail are related.
2. engine.prove_n('example', 'how_related', (), 2). This expands to:
2.1. example.how_related($ans1, $ans2)
And will return two tuples of all combinations of people with plans indicating how they are related.
Note that all forms expand to passing two arguments to "example.how_related".
Also note that 'example' is the name of the root rule base for the .krb file activated on line 67. Since the 'example' rule base does not inherit any other rule bases, it is the root rule base itself; so 'example' is the name used here.
I hope this helps!