-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgraph.py
93 lines (81 loc) · 2.92 KB
/
graph.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import node
import error
class Graph:
def __init__(self):
self.atoms = {}
self.closed = False
def atom(self, name, *args, **kwargs):
"""
if an atom with name already exists, return it
else create an Atom in this graph
"""
atom = self.atoms.get(name, None)
if atom is None:
atom = node.Atom(name, self, *args, **kwargs)
self.atoms[name] = atom
elif kwargs.get('tv', None):
raise ValueError('cannot specify atom.tv when the atom already exists')
return atom
def validate_atom(self, atom):
if atom.graph is not self:
raise error.AtomNotInGraph("{} belongs to another graph".format(atom))
return atom
def entails(self, antecedent, concequent):
"""
Connect antecedent and concequent
"""
if antecedent is concequent:
raise ValueError('concequent must be different than antecedent')
if isinstance(antecedent, node.Atom):
self.validate_atom(antecedent)
antecedent.outputs.append(concequent) #FIXME: check if concequent is a valid atom
else:
antecedent.output = concequent
if isinstance(concequent, node.Atom):
self.validate_atom(concequent)
concequent.inputs.append(antecedent)
else:
concequent.input = antecedent
return concequent
def close(self, facts=[]):
"""
Close the graph.
Set all leaf atoms to false if indeterminate, set all atoms in facts to true.
"""
if self.closed and facts:
raise Exception("Graph is closed")
self.closed = True
for fact in facts:
self.atoms[fact.name].tv = node.TRUE
for atom in set(self.atoms.values()).difference(set(facts)):
if len(atom.inputs) == 0 and atom.tv == node.INDETERMINATE:
atom.tv = node.FALSE
def eval(self, n, facts=[], verbose=False):
"""
Evaluate the truth value of node
add node to graph and evaluate
"""
self.close(facts)
return n.eval(None, verbose=verbose)
def reset(self):
"""
Reset facts to their orignial truth value or indeterminate
"""
for atom in self.atoms.values():# TODO: Atom.reset()
atom.tv = atom.original_tv if atom.original_tv is not None else node.INDETERMINATE
if atom.tv_reason:
atom.tv_reason = None
self.closed = False
def suppose(self, facts=[]):
return Session(self, facts)
def __str__(self):
strs = [str(atom) for atom in self.atoms.values()]
return "Graph({})".format(strs)
class Session:
def __init__(self, graph, facts):
self.graph = graph
self.facts = facts
def __enter__(self):
self.graph.close(self.facts)
def __exit__(self, *args):
self.graph.reset()