In PyDatalog I have defined the following assertions:
#stations
assert_fact('station', 'A' ,'yellow')
assert_fact('station', 'B' ,'yellow')
assert_fact('station', 'C' ,'yellow')
assert_fact('station', 'D' ,'yellow')
#sections
assert_fact('stretch', 'A' ,'B')
assert_fact('stretch', 'B' ,'C')
assert_fact('stretch', 'C', 'D')
And I would like to ask the database if there is a way to get to D from A. The following code should work, because it answers set([()]) if there is a way, and None if there isn't. But it doesn't give me the result of the different evaluations of Z. I would like to know also the route, for example: A B C D
load("""
route(X,Y) <= stretch(X,Y)
route(X,Y) <= stretch(X,Z) & route(Z,Y)
""")
I have tried with unbound values, but it only gives me the result of the first iteration:
load("""
route(X,Y,P) <= stretch(X,Y) & (P==Y)
route(X,Y,P) <= stretch(X,P) & route(P,Y,Z)
""")
I think that the problem is that it only takes P in the first iteration. Or should I use aggregation functions? I don't understand very well how I could use concat...
Thanks in advance.
You need a predicate with a variable that contains the nodes between the 2 end points. You could use the following definition of route():
load("""
route(X,P, Y) <= stretch(X,Y) & (P==[])
route(X,P, Y) <= stretch(X,Z) & route(Z,P1,Y) & ~(Z in P1) & (P==[Z]+P1)
""")
print(pyDatalog.ask("route('A', P, 'D')"))
# prints set([(('B', 'C'),)])
Lists are supported since pyDatalog 0.13.