|
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