|
| 1 | +from cvc5_pythonic_api import * |
| 2 | + |
| 3 | + |
| 4 | +def reset_solver(s): |
| 5 | + s.reset() |
| 6 | + s.set('produce-unsat-assumptions','true') |
| 7 | + |
| 8 | +def validate_unsat_assumptions(assumptions, core): |
| 9 | + # checks that the produced unsat assumptions (core) match the assumptions (assumptions) sent to the check function |
| 10 | + return sum([c in assumptions for c in core]) == len(core) |
| 11 | + |
| 12 | + |
| 13 | +def check_unsat_assumptions(assertions, core): |
| 14 | + # This function checks wether, given assertions, the produced unsat assumptions (core) also lead to unsat result |
| 15 | + slvr = Solver() |
| 16 | + slvr.set('produce-unsat-assumptions','true') |
| 17 | + for a in assertions: |
| 18 | + slvr.add(a) |
| 19 | + return s.check(*core) == unsat |
| 20 | + |
| 21 | + |
| 22 | +# To make make sure the unsat_core function works there should be at least one nontrivial solution - a solution that doesn't contain all the assumptions sent in the check function. |
| 23 | +nontrivial_counter = 0 |
| 24 | + |
| 25 | +p1, p2, p3 = Bools('p1 p2 p3') |
| 26 | +x, y = Ints('x y') |
| 27 | +s = Solver() |
| 28 | +reset_solver(s) |
| 29 | +assertions = [Implies(p1, x > 0), Implies(p2, y > x), Implies(p2, y < 1), Implies(p3, y > -3)] |
| 30 | + |
| 31 | +for a in assertions: |
| 32 | + s.add(a) |
| 33 | + |
| 34 | +assumptions = [p1,p2,p3] |
| 35 | + |
| 36 | +s.check(*assumptions) |
| 37 | + |
| 38 | +core = s.unsat_core() |
| 39 | + |
| 40 | + |
| 41 | +assert validate_unsat_assumptions(assumptions,core) |
| 42 | +assert check_unsat_assumptions(assertions,core) |
| 43 | +if len(core) < len(assumptions): |
| 44 | + nontrivial_counter += 1 |
| 45 | + |
| 46 | +# example 2 - booleans |
| 47 | + |
| 48 | +reset_solver(s) |
| 49 | + |
| 50 | +a, b, c = Bools('a b c') |
| 51 | + |
| 52 | +# Add constraints |
| 53 | + |
| 54 | +assertions = [Or(a, b), Or(Not(a), c), Not(c) ] |
| 55 | +for c in assertions: |
| 56 | + s.add(c) |
| 57 | + |
| 58 | + |
| 59 | +# Check satisfiability |
| 60 | +assumptions = [a,b,c] |
| 61 | +result = s.check(*assumptions) |
| 62 | + |
| 63 | +unsat_core = s.unsat_core() |
| 64 | + |
| 65 | +assert validate_unsat_assumptions(assumptions,unsat_core) |
| 66 | +assert check_unsat_assumptions(assertions,assumptions) |
| 67 | +if len(unsat_core) < len(assumptions): |
| 68 | + nontrivial_counter += 1 |
| 69 | + |
| 70 | +# example 3 - booleans |
| 71 | + |
| 72 | + |
| 73 | +reset_solver(s) |
| 74 | + |
| 75 | +a, b, c = Bools('a b c') |
| 76 | +d = Bool('d') |
| 77 | +# Add constraints with boolean operators |
| 78 | +assertions = [And(a, b, Not(c)), Or(a, d), Not(And(a, d)) ] |
| 79 | +for a in assertions: |
| 80 | + s.add(a) |
| 81 | + |
| 82 | +# Check satisfiability |
| 83 | +assumptions = [a,b,c,d] |
| 84 | +result = s.check(*assumptions) |
| 85 | + |
| 86 | +unsat_core = s.unsat_core() |
| 87 | + |
| 88 | +assert validate_unsat_assumptions(assumptions,unsat_core) |
| 89 | +assert check_unsat_assumptions(assertions,assumptions) |
| 90 | +if len(unsat_core) < len(assumptions): |
| 91 | + nontrivial_counter += 1 |
| 92 | + |
| 93 | +# example 4 - reals |
| 94 | + |
| 95 | + |
| 96 | + |
| 97 | +reset_solver(s) |
| 98 | + |
| 99 | +x = Real('x') |
| 100 | +y = Real('y') |
| 101 | +z = Real('z') |
| 102 | + |
| 103 | +assertions = [x + y == 5, y - z > 2, z > 3 ] |
| 104 | +for a in assertions: |
| 105 | + s.add(a) |
| 106 | + |
| 107 | +# Check satisfiability |
| 108 | +assumptions = [x > 0, y > 0, z > 0] |
| 109 | +result = s.check(*assumptions) |
| 110 | + |
| 111 | +unsat_core = s.unsat_core() |
| 112 | + |
| 113 | +assert validate_unsat_assumptions(assumptions,unsat_core) |
| 114 | +assert check_unsat_assumptions(assertions,assumptions) |
| 115 | +if len(unsat_core) < len(assumptions): |
| 116 | + nontrivial_counter += 1 |
| 117 | + |
| 118 | + |
| 119 | +# example 5 - strings |
| 120 | + |
| 121 | + |
| 122 | +reset_solver(s) |
| 123 | + |
| 124 | + |
| 125 | +# Define string variables |
| 126 | +s1 = String('s1') |
| 127 | +s2 = String('s2') |
| 128 | + |
| 129 | +# Add string constraints |
| 130 | +assertions = [Or(s1 == "hello", s1 == "world"), s1 + s2 == "helloworld"] |
| 131 | +for a in assertions: |
| 132 | + s.add(a) |
| 133 | + |
| 134 | +# Check satisfiability |
| 135 | + |
| 136 | +result = s.check( Length(s2) < 2) |
| 137 | + |
| 138 | +unsat_core = s.unsat_core() |
| 139 | + |
| 140 | +assert validate_unsat_assumptions([Length(s2) < 2], unsat_core) |
| 141 | +assert check_unsat_assumptions(assertions,[ Length(s2) < 2 ]) |
| 142 | +if len(unsat_core) < len([ Length(s2) < 2 ]): |
| 143 | + nontrivial_counter += 1 |
| 144 | + |
| 145 | +# check that there is at least one nontrivial unsat core |
| 146 | +assert nontrivial_counter >= 1 |
| 147 | + |
| 148 | +print('success') |
| 149 | + |
| 150 | + |
0 commit comments