https://www.oreilly.co.jp/books/9784873118727/
上記url の 6章の写経の続き。
以下の家系図を定義し、「John」の父親(≠義父)を求めます
John─Megan │ ┌──────────┼─────────────┐ William─Emma David─Olivia Adam─Lily ┌─┤ ┌─┬─┴─┬──┬──┐ │ Cris Stephanie Wayne Tiffany Julie Neil Peter Sopia
#!/usr/local/python3/bin/python3 # -*- coding: utf-8 -*- import json import kanren from kanren import Relation, facts, run, conde, var, eq relation = \ {"father": [{"John": "William"}, {"John": "David"}, {"John": "Adam"}, {"William": "Chris"}, {"William": "Stephanie"}, {"David": "Wayne"}, {"David": "Tiffany"}, {"David": "Julie"}, {"David": "Neil"}, {"David": "Peter"}, {"Adam": "Sophia"} ], "mother": [{"Megan": "William"}, {"Megan": "David"}, {"Megan": "Adam"}, {"Emma": "Stephanie"}, {"Emma": "Chris"}, {"Olivia": "Tiffany"}, {"Olivia": "Julie"}, {"Olivia": "Neil"}, {"Olivia": "Peter"}, {"Lily": "Sophia"} ] } def parent(x, y): return kanren.conde((father(x, y),), (mother(x, y),)) def grandparent(x, y): temp = var() return kanren.conde((parent(x, temp), parent(temp, y))) def sibling(x, y): # 兄弟 temp = var() return kanren.conde((parent(temp, x), parent(temp, y))) def uncle(x, y): temp = kanren.var() return kanren.conde((father(temp, x), grandparent(temp, y))) # return conde((sibling(temp, x), parent(temp, y))) def main(): # with open('relationships.json') as f: # d = json.loads(f.read()) d = relation father = kanren.Relation() mother = kanren.Relation() for item in d['father']: kanren.facts(father, (list(item.keys())[0], list(item.values())[0])) for item in d['mother']: kanren.facts(mother, (list(item.keys())[0], list(item.values())[0])) x = var() output = run(0, x, (father, 'John', x)) for item in output: print(item) if __name__ == '__main__': main()
↑こう書くと、↓こう表示されます
$ ./foo.py Adam David William