|
| 1 | + |
| 2 | +======================================================================== |
| 3 | +Tactic: `circuit` |
| 4 | +======================================================================== |
| 5 | + |
| 6 | +The ``circuit`` tactic can be used to resolve a multitude of goals where |
| 7 | +the semantics in question are over finite types. |
| 8 | + |
| 9 | +There are currently two variants of this tactic: |
| 10 | + |
| 11 | +- `circuit`, which attempts to automatically solve/prove the goal |
| 12 | + |
| 13 | +- `circuit simplify`, which performs a simplification over the goal structure |
| 14 | + augmented by equivalence checks whenever an equality between two finite types |
| 15 | + with bindings is encountered. |
| 16 | + |
| 17 | +.. contents:: |
| 18 | + :local: |
| 19 | + |
| 20 | +.. |
| 21 | + ------------------------------------------------------------------------ |
| 22 | + Variant: ``circuit`` (FOL) |
| 23 | + ------------------------------------------------------------------------ |
| 24 | + .. ecproof:: |
| 25 | + :title: First-order logic example |
| 26 | +
|
| 27 | + require import AllCore List QFABV. |
| 28 | + |
| 29 | + type W8. |
| 30 | + |
| 31 | + op to_bits : W8 -> bool list. |
| 32 | + op from_bits : bool list -> W8. |
| 33 | + op of_int : int -> W8. |
| 34 | + op to_uint : W8 -> int. |
| 35 | + op to_sint : W8 -> int. |
| 36 | + |
| 37 | + bind bitstring |
| 38 | + to_bits |
| 39 | + from_bits |
| 40 | + to_uint |
| 41 | + to_sint |
| 42 | + of_int |
| 43 | + W8 |
| 44 | + 8. |
| 45 | + |
| 46 | + realize gt0_size by admit. |
| 47 | + realize tolistP by admit. |
| 48 | + realize oflistP by admit. |
| 49 | + realize touintP by admit. |
| 50 | + realize tosintP by admit. |
| 51 | + realize ofintP by admit. |
| 52 | + realize size_tolist by admit. |
| 53 | + |
| 54 | + op (+^) : W8 -> W8 -> W8. |
| 55 | + bind op W8 (+^) "xor". |
| 56 | + realize bvxorP by admit. |
| 57 | + |
| 58 | + lemma L (w1 w2 : W8) : w1 +^ w2 = w2 +^ w1. |
| 59 | + proof. |
| 60 | + proc. (*$*) circuit solve. |
| 61 | + abort. |
| 62 | + |
| 63 | + As we can see, the tactic can, through the generation of the appropriate |
| 64 | + circuit representing validity of the proposition for a given value and |
| 65 | + the equation of this function with the constant function equal to true, |
| 66 | + establish the truth of the lemma. |
| 67 | + This is, in a sense, a reverse use of function extensionality, to convert |
| 68 | + statements about functions to statements about universal quantification. |
| 69 | + |
| 70 | + |
| 71 | +------------------------------------------------------------------------ |
| 72 | +Variant: ``circuit`` (HL) |
| 73 | +------------------------------------------------------------------------ |
| 74 | + |
| 75 | +.. ecproof:: |
| 76 | + :title: Hoare logic example |
| 77 | + |
| 78 | + require import AllCore List QFABV. |
| 79 | + |
| 80 | + type W8. |
| 81 | + |
| 82 | + op to_bits : W8 -> bool list. |
| 83 | + op from_bits : bool list -> W8. |
| 84 | + op of_int : int -> W8. |
| 85 | + op to_uint : W8 -> int. |
| 86 | + op to_sint : W8 -> int. |
| 87 | + |
| 88 | + bind bitstring |
| 89 | + to_bits |
| 90 | + from_bits |
| 91 | + to_uint |
| 92 | + to_sint |
| 93 | + of_int |
| 94 | + W8 |
| 95 | + 8. |
| 96 | + |
| 97 | + realize gt0_size by admit. |
| 98 | + realize tolistP by admit. |
| 99 | + realize oflistP by admit. |
| 100 | + realize touintP by admit. |
| 101 | + realize tosintP by admit. |
| 102 | + realize ofintP by admit. |
| 103 | + realize size_tolist by admit. |
| 104 | + |
| 105 | + op (+^) : W8 -> W8 -> W8. |
| 106 | + bind op W8 (+^) "xor". |
| 107 | + realize bvxorP by admit. |
| 108 | + |
| 109 | + module M = { |
| 110 | + proc f(w : W8) = { |
| 111 | + return w +^ w; |
| 112 | + } |
| 113 | + }. |
| 114 | + |
| 115 | + lemma L (w_ : W8) : hoare[M.f : w_ = w ==> res = of_int 0]. |
| 116 | + proof. |
| 117 | + proc. (*$*) circuit. |
| 118 | + abort. |
| 119 | + |
| 120 | + |
| 121 | +As we can see from the output, the execution of the tactic has several components: |
| 122 | + |
| 123 | +- The translation of the precondition to a circuit, using any explicit equations |
| 124 | + that define values of program variables at the start of execution in the further |
| 125 | + construction of circuits henceforth. |
| 126 | + |
| 127 | +- The translation of the program to a (collection of) circuits. This is done instruction-wise |
| 128 | + by keeping and updating a mapping from program variables to circuits determining how their |
| 129 | + value is obtained from the value of some initial "input" variables. In the case of a program |
| 130 | + these are either logical variables constraining initial values of program variables or the |
| 131 | + program variables themselves, interpreted as symbols which are then universally quantified. |
| 132 | + |
| 133 | +- The translation of the postcondition into a circuit outputting a boolean, representing whether |
| 134 | + the postcondition holds for given values of the input variables. The knowledge of how the |
| 135 | + inputs relate to the outputs through the program and the knowledge of any initial relations |
| 136 | + or known facts about these variables coming from the precondition or proof context is also |
| 137 | + incorporated into this circuit. The goal of the tactic is then to prove that this circuit |
| 138 | + is identically true for all values of the input, which is equivalent to the given hoare triple |
| 139 | + being valid/true under the current proof context. |
| 140 | + |
| 141 | +In the case where the goal is an equality, some extra optimization are effected. |
| 142 | +This corresponds to a heuristic inferrence procedure which tries to find structurally identical |
| 143 | +conditions in order to avoid having to check the same condition more than once and also reduce |
| 144 | +the number of inputs which are considered for each condition check, in order to reduce checking time. |
| 145 | + |
| 146 | + |
| 147 | +------------------------------------------------------------------------ |
| 148 | +Variant: ``circuit`` (rHL) |
| 149 | +------------------------------------------------------------------------ |
| 150 | + |
| 151 | +.. ecproof:: |
| 152 | + :title: Program equivalence example |
| 153 | + |
| 154 | + require import AllCore List QFABV. |
| 155 | + |
| 156 | + type W8. |
| 157 | + |
| 158 | + op to_bits : W8 -> bool list. |
| 159 | + op from_bits : bool list -> W8. |
| 160 | + op of_int : int -> W8. |
| 161 | + op to_uint : W8 -> int. |
| 162 | + op to_sint : W8 -> int. |
| 163 | + |
| 164 | + bind bitstring |
| 165 | + to_bits |
| 166 | + from_bits |
| 167 | + to_uint |
| 168 | + to_sint |
| 169 | + of_int |
| 170 | + W8 |
| 171 | + 8. |
| 172 | + |
| 173 | + realize gt0_size by admit. |
| 174 | + realize tolistP by admit. |
| 175 | + realize oflistP by admit. |
| 176 | + realize touintP by admit. |
| 177 | + realize tosintP by admit. |
| 178 | + realize ofintP by admit. |
| 179 | + realize size_tolist by admit. |
| 180 | + |
| 181 | + op (+^) : W8 -> W8 -> W8. |
| 182 | + bind op W8 (+^) "xor". |
| 183 | + realize bvxorP by admit. |
| 184 | + |
| 185 | + module M = { |
| 186 | + proc f1(w1 w2 : W8) = { |
| 187 | + var a : W8; |
| 188 | + a <- w1 +^ w2; |
| 189 | + return a; |
| 190 | + } |
| 191 | + |
| 192 | + proc f2(w1 w2 : W8) = { |
| 193 | + var a : W8; |
| 194 | + a <- w2 +^ w1; |
| 195 | + return a; |
| 196 | + } |
| 197 | + }. |
| 198 | + |
| 199 | + lemma L : equiv[M.f1 ~ M.f2 : ={arg} ==> ={res}]. |
| 200 | + proof. |
| 201 | + proc. (*$*) circuit. |
| 202 | + abort. |
| 203 | + |
| 204 | + |
| 205 | +As we can see in this example, the tactic is also able to automatically prove |
| 206 | +equivalence of these two programs. The way this is done is similar to the way |
| 207 | +that single procedures are handled, but now we consider two sets of transformations |
| 208 | +from input to outputs variables, one for each program. We then use this knowledge |
| 209 | +to convert the postcondition into the appropriate circuit and use the same procedure |
| 210 | +to attempt to automatically discharge it. |
0 commit comments