-
Notifications
You must be signed in to change notification settings - Fork 0
/
first_order.py
172 lines (116 loc) · 4.65 KB
/
first_order.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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
from dataclasses import dataclass
from primitives import Literal, Clause, Term, FreeClause
@dataclass
class Relation:
name: str
def __call__(self, *args, **kwargs):
return RelationInstance(self.name, *args)
class RelationInstance(Term):
relation_name: str
vars: list
def __init__(self, relation_name: str, *vars, negate: bool = False):
super().__init__(negate)
object.__setattr__(self, "relation_name", relation_name)
object.__setattr__(self, "vars", vars)
def __contains__(self, item):
present = False
for var in self.vars:
present |= item in var
return present
def __repr__(self):
return f"RelationInstance{{name={self.relation_name}, vars={repr(self.vars)}, negate={self.negate}}}"
def __str__(self):
string = ""
if self.negate:
string += "¬"
var_names = [str(var) for var in self.vars]
string += f'{self.relation_name}({", ".join(var_names)})'
return string
def __invert__(self):
return RelationInstance(self.relation_name, *self.vars, negate=not self.negate)
def __eq__(self, other):
return type(other) is RelationInstance and \
self.relation_name == other.relation_name and \
self.vars == other.vars and \
self.negate == other.negate
def __hash__(self):
return hash(self.relation_name) ^ hash(self.negate) ^ hash("RelationName") ^ hash(self.vars)
@dataclass
class Function:
name: str
def __call__(self, *args, **kwargs):
if len(args) != 1:
raise RuntimeError("wrong number of arguments in function (one argument required)")
return FunctionInstance(self.name, args[0])
class Var(Term):
name: str
def __init__(self, name: str, negate: bool = False):
super().__init__(negate)
object.__setattr__(self, "name", name)
def __repr__(self):
return f"Var{{name={self.name}, negate={self.negate}}}"
def __str__(self):
return f"{self.name}"
def __eq__(self, other):
return type(other) is Var and self.name == other.name
def __hash__(self):
return hash(self.name) ^ hash(self.negate) ^ hash("Var")
def __contains__(self, item):
return type(item) is Var and self.name == item.name
def __invert__(self):
return Var(self.name, not self.negate)
class FunctionInstance(Term):
function_name: str
arg: Term
def __init__(self, function_name, arg, negate=False):
super().__init__(negate)
object.__setattr__(self, "function_name", function_name)
object.__setattr__(self, "arg", arg)
def __str__(self):
string = ""
if self.negate:
string += "¬"
return string + f"{self.function_name}({self.arg})"
def __repr__(self):
return f"FunctionInstance{{name={self.function_name}, var1={repr(self.arg)}, negate={self.negate}}}"
def __contains__(self, item):
return item in self.arg
def __invert__(self):
return FunctionInstance(self.function_name, self.arg, not self.negate)
def __eq__(self, other):
return type(other) is FunctionInstance and \
self.function_name == other.function_name and \
self.arg == other.arg and \
self.negate == other.negate
def __hash__(self):
return hash(self.function_name) ^ hash(self.negate) ^ hash("FunctionInstance") ^ hash(self.arg)
@dataclass(init=False, frozen=True)
class Quantifier(Term):
variable: Var
predicate: FreeClause
def __init__(self, variable: Var, predicate, negate: bool = False):
super().__init__(negate)
object.__setattr__(self, "variable", variable)
object.__setattr__(self, "predicate", predicate)
if type(variable) is not Var:
raise TypeError(f"You must use `Var`s for variables. Actual type: {type(variable)}")
if variable not in predicate:
raise TypeError("Quantifier variable not present in predicate")
def __contains__(self, item):
return item in self.predicate
class Exists(Quantifier):
def __str__(self):
string = "("
if self.negate:
string += "¬"
return string + f"∃ {self.variable.name} {self.predicate})"
def __invert__(self):
return Exists(self.variable, self.predicate, not self.negate)
class ForAll(Quantifier):
def __str__(self):
string = "("
if self.negate:
string += "¬"
return string + f"∀ {self.variable.name} {self.predicate})"
def __invert__(self):
return ForAll(self.variable, self.predicate, not self.negate)