|
52 | 52 | * Missing features:
|
53 | 53 | * Patterns
|
54 | 54 | * Models for uninterpreted sorts
|
| 55 | + * The `Model` function |
| 56 | + * In our API, this function returns an object whose only method is `evaluate`. |
55 | 57 | * Pseudo-boolean counting constraints
|
56 | 58 | * AtMost, AtLeast, PbLe, PbGe, PbEq
|
57 | 59 | * HTML integration
|
@@ -558,9 +560,6 @@ def _ctx_from_ast_arg_list(args, default_ctx=None):
|
558 | 560 | if is_ast(a):
|
559 | 561 | if ctx is None:
|
560 | 562 | ctx = a.ctx
|
561 |
| - else: |
562 |
| - if debugging(): |
563 |
| - _assert(ctx == a.ctx, "Context mismatch") |
564 | 563 | if ctx is None:
|
565 | 564 | ctx = default_ctx
|
566 | 565 | return ctx
|
@@ -1245,8 +1244,6 @@ def If(a, b, c, ctx=None):
|
1245 | 1244 | s = BoolSort(ctx)
|
1246 | 1245 | a = s.cast(a)
|
1247 | 1246 | b, c = _coerce_exprs(b, c, ctx)
|
1248 |
| - if debugging(): |
1249 |
| - _assert(a.ctx == b.ctx, "Context mismatch") |
1250 | 1247 | return _to_expr_ref(ctx.solver.mkTerm(Kind.ITE, a.ast, b.ast, c.ast), ctx)
|
1251 | 1248 |
|
1252 | 1249 |
|
@@ -1429,6 +1426,38 @@ def __mul__(self, other):
|
1429 | 1426 | return 0
|
1430 | 1427 | return If(self, other, 0)
|
1431 | 1428 |
|
| 1429 | + def __and__(self, other): |
| 1430 | + """Create the SMT and expression `self & other`. |
| 1431 | +
|
| 1432 | + >>> solve(Bool("x") & Bool("y")) |
| 1433 | + [x = True, y = True] |
| 1434 | + """ |
| 1435 | + return And(self, other) |
| 1436 | + |
| 1437 | + def __or__(self, other): |
| 1438 | + """Create the SMT or expression `self | other`. |
| 1439 | +
|
| 1440 | + >>> solve(Bool("x") | Bool("y"), Not(Bool("x"))) |
| 1441 | + [x = False, y = True] |
| 1442 | + """ |
| 1443 | + return Or(self, other) |
| 1444 | + |
| 1445 | + def __xor__(self, other): |
| 1446 | + """Create the SMT xor expression `self ^ other`. |
| 1447 | +
|
| 1448 | + >>> solve(Bool("x") ^ Bool("y"), Not(Bool("x"))) |
| 1449 | + [x = False, y = True] |
| 1450 | + """ |
| 1451 | + return Xor(self, other) |
| 1452 | + |
| 1453 | + def __invert__(self): |
| 1454 | + """Create the SMT not expression `~self`. |
| 1455 | +
|
| 1456 | + >>> solve(~Bool("x")) |
| 1457 | + [x = False] |
| 1458 | + """ |
| 1459 | + return Not(self) |
| 1460 | + |
1432 | 1461 |
|
1433 | 1462 | def is_bool(a):
|
1434 | 1463 | """Return `True` if `a` is an SMT Boolean expression.
|
@@ -1875,8 +1904,6 @@ def cast(self, val):
|
1875 | 1904 | String
|
1876 | 1905 | """
|
1877 | 1906 | if is_expr(val):
|
1878 |
| - if debugging(): |
1879 |
| - _assert(self.ctx == val.ctx, "Context mismatch") |
1880 | 1907 | val_s = val.sort()
|
1881 | 1908 | if self.eq(val_s):
|
1882 | 1909 | return val
|
@@ -2617,8 +2644,6 @@ def cast(self, val):
|
2617 | 2644 | failed
|
2618 | 2645 | """
|
2619 | 2646 | if is_expr(val):
|
2620 |
| - if debugging(): |
2621 |
| - _assert(self.ctx == val.ctx, "Context mismatch") |
2622 | 2647 | val_s = val.sort()
|
2623 | 2648 | if self.eq(val_s):
|
2624 | 2649 | return val
|
@@ -4067,8 +4092,6 @@ def cast(self, val):
|
4067 | 4092 | '#b00000000000000000000000000001010'
|
4068 | 4093 | """
|
4069 | 4094 | if is_expr(val):
|
4070 |
| - if debugging(): |
4071 |
| - _assert(self.ctx == val.ctx, "Context mismatch") |
4072 | 4095 | # Idea: use sign_extend if sort of val is a bitvector of smaller size
|
4073 | 4096 | return val
|
4074 | 4097 | else:
|
@@ -5494,7 +5517,6 @@ def ArraySort(*sig):
|
5494 | 5517 | if debugging():
|
5495 | 5518 | for s in sig:
|
5496 | 5519 | _assert(is_sort(s), "SMT sort expected")
|
5497 |
| - _assert(s.ctx == r.ctx, "Context mismatch") |
5498 | 5520 | ctx = d.ctx
|
5499 | 5521 | if len(sig) == 2:
|
5500 | 5522 | return ArraySortRef(ctx.solver.mkArraySort(d.ast, r.ast), ctx)
|
@@ -6238,12 +6260,22 @@ def proof(self):
|
6238 | 6260 | [a + 2 == 0, a == 0],
|
6239 | 6261 | (EQ_RESOLVE: False,
|
6240 | 6262 | (ASSUME: a == 0, [a == 0]),
|
6241 |
| - (MACRO_SR_EQ_INTRO: (a == 0) == False, |
6242 |
| - [a == 0, 7, 12], |
6243 |
| - (EQ_RESOLVE: a == -2, |
6244 |
| - (ASSUME: a + 2 == 0, [a + 2 == 0]), |
6245 |
| - (MACRO_SR_EQ_INTRO: (a + 2 == 0) == (a == -2), |
6246 |
| - [a + 2 == 0, 7, 12])))))) |
| 6263 | + (TRANS: (a == 0) == False, |
| 6264 | + (CONG: (a == 0) == (-2 == 0), |
| 6265 | + [5], |
| 6266 | + (EQ_RESOLVE: a == -2, |
| 6267 | + (ASSUME: a + 2 == 0, [a + 2 == 0]), |
| 6268 | + (TRANS: (a + 2 == 0) == (a == -2), |
| 6269 | + (CONG: (a + 2 == 0) == (2 + a == 0), |
| 6270 | + [5], |
| 6271 | + (TRUST_THEORY_REWRITE: a + 2 == 2 + a, |
| 6272 | + [a + 2 == 2 + a, 3, 7]), |
| 6273 | + (REFL: 0 == 0, [0])), |
| 6274 | + (TRUST_THEORY_REWRITE: (2 + a == 0) == (a == -2), |
| 6275 | + [(2 + a == 0) == (a == -2), 3, 7]))), |
| 6276 | + (REFL: 0 == 0, [0])), |
| 6277 | + (TRUST_THEORY_REWRITE: (-2 == 0) == False, |
| 6278 | + [(-2 == 0) == False, 3, 7]))))) |
6247 | 6279 | """
|
6248 | 6280 | p = self.solver.getProof()[0]
|
6249 | 6281 | return ProofRef(self, p)
|
@@ -6789,13 +6821,36 @@ def decls(self):
|
6789 | 6821 |
|
6790 | 6822 |
|
6791 | 6823 | def evaluate(t):
|
6792 |
| - """Evaluates the given term (assuming it is constant!)""" |
| 6824 | + """Evaluates the given term (assuming it is constant!) |
| 6825 | +
|
| 6826 | + >>> evaluate(evaluate(BitVecVal(1, 8) + BitVecVal(2, 8)) + BitVecVal(3, 8)) |
| 6827 | + 6 |
| 6828 | + """ |
| 6829 | + if not isinstance(t, ExprRef): |
| 6830 | + raise TypeError("Can only evaluate `ExprRef`s") |
6793 | 6831 | s = Solver()
|
6794 | 6832 | s.check()
|
6795 | 6833 | m = s.model()
|
6796 | 6834 | return m[t]
|
6797 | 6835 |
|
6798 | 6836 |
|
| 6837 | +class EmptyModel: |
| 6838 | + def evaluate(self, t): |
| 6839 | + return evaluate(t) |
| 6840 | + |
| 6841 | + |
| 6842 | +def Model(ctx=None): |
| 6843 | + """Return an object for evaluating terms. |
| 6844 | +
|
| 6845 | + We recommend using the standalone `evaluate` function for this instead, |
| 6846 | + but we also provide this function and its return object for z3 compatibility. |
| 6847 | +
|
| 6848 | + >>> Model().evaluate(BitVecVal(1, 8) + BitVecVal(2, 8)) |
| 6849 | + 3 |
| 6850 | + """ |
| 6851 | + return EmptyModel() |
| 6852 | + |
| 6853 | + |
6799 | 6854 | class ProofRef:
|
6800 | 6855 | """A proof tree where every proof reference corresponds to the
|
6801 | 6856 | root step of a proof. The branches of the root step are the
|
@@ -6857,12 +6912,22 @@ def getChildren(self):
|
6857 | 6912 | >>> p
|
6858 | 6913 | (EQ_RESOLVE: False,
|
6859 | 6914 | (ASSUME: a == 0, [a == 0]),
|
6860 |
| - (MACRO_SR_EQ_INTRO: (a == 0) == False, |
6861 |
| - [a == 0, 7, 12], |
6862 |
| - (EQ_RESOLVE: a == -2, |
6863 |
| - (ASSUME: a + 2 == 0, [a + 2 == 0]), |
6864 |
| - (MACRO_SR_EQ_INTRO: (a + 2 == 0) == (a == -2), |
6865 |
| - [a + 2 == 0, 7, 12])))) |
| 6915 | + (TRANS: (a == 0) == False, |
| 6916 | + (CONG: (a == 0) == (-2 == 0), |
| 6917 | + [5], |
| 6918 | + (EQ_RESOLVE: a == -2, |
| 6919 | + (ASSUME: a + 2 == 0, [a + 2 == 0]), |
| 6920 | + (TRANS: (a + 2 == 0) == (a == -2), |
| 6921 | + (CONG: (a + 2 == 0) == (2 + a == 0), |
| 6922 | + [5], |
| 6923 | + (TRUST_THEORY_REWRITE: a + 2 == 2 + a, |
| 6924 | + [a + 2 == 2 + a, 3, 7]), |
| 6925 | + (REFL: 0 == 0, [0])), |
| 6926 | + (TRUST_THEORY_REWRITE: (2 + a == 0) == (a == -2), |
| 6927 | + [(2 + a == 0) == (a == -2), 3, 7]))), |
| 6928 | + (REFL: 0 == 0, [0])), |
| 6929 | + (TRUST_THEORY_REWRITE: (-2 == 0) == False, |
| 6930 | + [(-2 == 0) == False, 3, 7]))) |
6866 | 6931 | """
|
6867 | 6932 | children = self.proof.getChildren()
|
6868 | 6933 | return [ProofRef(self.solver, cp) for cp in children]
|
@@ -6965,8 +7030,6 @@ def cast(self, val):
|
6965 | 7030 | '(fp #b0 #b01111111 #b00000000000000000000000)'
|
6966 | 7031 | """
|
6967 | 7032 | if is_expr(val):
|
6968 |
| - if debugging(): |
6969 |
| - _assert(self.ctx == val.ctx, "Context mismatch") |
6970 | 7033 | return val
|
6971 | 7034 | else:
|
6972 | 7035 | return FPVal(val, None, self, self.ctx)
|
@@ -8633,7 +8696,6 @@ def CreateDatatypes(*ds):
|
8633 | 8696 | _assert(
|
8634 | 8697 | all([isinstance(d, Datatype) for d in ds]), "Arguments must be Datatypes"
|
8635 | 8698 | )
|
8636 |
| - _assert(all([d.ctx == ds[0].ctx for d in ds]), "Context mismatch") |
8637 | 8699 | _assert(all([d.constructors != [] for d in ds]), "Non-empty Datatypes expected")
|
8638 | 8700 | ctx = ds[0].ctx
|
8639 | 8701 | s = ctx.solver
|
@@ -9240,9 +9302,6 @@ def cast(self, val):
|
9240 | 9302 | '#f10m31'
|
9241 | 9303 | """
|
9242 | 9304 | if is_expr(val):
|
9243 |
| - if debugging(): |
9244 |
| - _assert(self.ctx == val.ctx, "Context mismatch") |
9245 |
| - # Idea: use sign_extend if sort of val is a bitvector of smaller size |
9246 | 9305 | return val
|
9247 | 9306 | else:
|
9248 | 9307 | return FiniteFieldVal(val, self)
|
|
0 commit comments