-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexpressions.py
174 lines (126 loc) · 4.66 KB
/
expressions.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
173
174
from abc import ABC, abstractmethod
from typing import Any, Dict, List, FrozenSet, Union
from dataclasses import dataclass
from cvc5 import Kind
class Expr(ABC):
@abstractmethod
def to_cvc5(self, slv, variables):
pass
@abstractmethod
def variables(self):
pass
@abstractmethod
def substitute_evaluate(self, subs: Dict[str, "Expr"]) -> "Expr":
pass
@dataclass
class VariableExpr(Expr):
name: str
def to_cvc5(self, slv, variables):
return variables[self.name]
def variables(self):
return {self.name}
def substitute_evaluate(self, subs: Dict[str, "Expr"]) -> "Expr":
return subs.get(self.name, self)
def __repr__(self):
return f"{self.name}"
@dataclass
class ConstantExpr(Expr):
value: Union[int, bool]
def to_cvc5(self, slv, variables):
if type(self.value) is int:
return slv.mkInteger(self.value)
else:
return slv.mkBoolean(self.value)
def variables(self):
return set()
def substitute_evaluate(self, subs: Dict[str, "Expr"]) -> "Expr":
return self
def __repr__(self):
return f"{self.value}"
@dataclass
class Op:
name: str
def cvc5_kind(self):
return getattr(Kind, self.name.upper())
def __repr__(self):
return f"{self.name.upper()}"
@dataclass
class UnOpExpr(Expr):
op: Op
operand: Expr
def to_cvc5(self, slv, variables):
return slv.mkTerm(self.op.cvc5_kind(),
self.operand.to_cvc5(slv, variables))
def variables(self):
return self.operand.variables()
def substitute_evaluate(self, subs: Dict[str, "Expr"]) -> "Expr":
return UnOpExpr(self.op, self.operand.substitute_evaluate(subs))
def __repr__(self):
return f"({self.op} {self.operand})"
@dataclass
class BinOpExpr(Expr):
op: Op
left: Expr
right: Expr
def to_cvc5(self, slv, variables):
return slv.mkTerm(self.op.cvc5_kind(),
self.left.to_cvc5(slv, variables),
self.right.to_cvc5(slv, variables))
def variables(self):
return self.left.variables() | self.right.variables()
def substitute_evaluate(self, subs: Dict[str, "Expr"]) -> "Expr":
return BinOpExpr(self.op,
self.left.substitute_evaluate(subs),
self.right.substitute_evaluate(subs))
def __repr__(self):
if self.op.cvc5_kind() == Kind.ADD:
return f"({self.left}+{self.right})"
if self.op.cvc5_kind() == Kind.SUB:
return f"({self.left}-{self.right})"
if self.op.cvc5_kind() == Kind.MULT:
return f"({self.left}*{self.right})"
if self.op.cvc5_kind() == Kind.INTS_MODULUS:
return f"({self.left}%{self.right})"
if self.op.cvc5_kind() == Kind.LEQ:
return f"({self.left}<={self.right})"
if self.op.cvc5_kind() == Kind.LT:
return f"({self.left}<{self.right})"
if self.op.cvc5_kind() == Kind.GEQ:
return f"({self.left}>={self.right})"
if self.op.cvc5_kind() == Kind.GT:
return f"({self.left}>{self.right})"
if self.op.cvc5_kind() == Kind.EQUAL:
return f"({self.left}=={self.right})"
return f"({self.op} {self.left} {self.right})"
@dataclass
class IfExpr(Expr):
condition: Expr
true: Expr
false: Expr
def to_cvc5(self, slv, variables):
return slv.mkTerm(Kind.ITE,
self.condition.to_cvc5(slv, variables),
self.true.to_cvc5(slv, variables),
self.false.to_cvc5(slv, variables))
def variables(self):
return self.condition.variables() | self.true.variables() | self.false.variables()
def substitute_evaluate(self, subs: Dict[str, "Expr"]) -> "Expr":
return IfExpr(self.condition.substitute_evaluate(subs),
self.true.substitute_evaluate(subs),
self.false.substitute_evaluate(subs))
def __repr__(self):
return f"(if {self.condition} then {self.true} else {self.false})"
def add(a, b):
return BinOpExpr(Op("add"), a, b)
def mul(a, b):
return BinOpExpr(Op("mult"), a, b)
def sub(a, b):
return BinOpExpr(Op("sub"), a, b)
def leq(a, b):
return BinOpExpr(Op("leq"), a, b)
def forall_cvc5(slv, variables, quant_var_names, expression: Expr):
quant_var_list = slv.mkTerm(Kind.VARIABLE_LIST,
*[variables[name] for name in quant_var_names])
return slv.mkTerm(Kind.FORALL,
quant_var_list,
expression.to_cvc5(slv, variables))