def testPrintFunction(self): test_data = [ (function.mk_fun_upd(f, a, b), "(f)(a := b)"), (function.mk_fun_upd(f, a, b, b, a), "(f)(a := b, b := a)"), ] thy = basic.load_theory('function') for t, s in test_data: self.assertEqual(printer.print_term(thy, t), s)
def testComputeWP(self): Q = Var("Q", TFun(natFunT, boolT)) test_data = [ (Assign(zero, abs(s, one)), abs(s, Q(mk_fun_upd(s, zero, one)))), (Seq(Assign(zero, abs(s, one)), Assign(one, abs(s, nat.to_binary(2)))), abs(s, Q(mk_fun_upd(s, zero, one, one, nat.to_binary(2))))), ] for c, P in test_data: prf = hoare.compute_wp(thy, natFunT, c, Q).export() self.assertEqual(thy.check_proof(prf), Thm([], Valid(P, c, Q)))
def testMkAssign(self): a, b = Var("a", TFun(natT, natT)), Var("b", boolT) var_map = {a: 0, b: 1} s = Var("s", gcl.stateT) test_data = [ ({ a(one): zero }, function.mk_fun_upd(s, Para(Ident(zero), one), NatV(zero))), ({ b: one }, function.mk_fun_upd(s, Ident(one), NatV(one))), ] for assign, res in test_data: self.assertEqual(gcl.mk_assign(var_map, s, assign), res)
def compute_wp(thy, T, c, Q): """Compute the weakest precondition for the given command and postcondition. The computation is by case analysis on the form of c. Returns the validity theorem. """ if c.head.is_const_name("Assign"): # Assign a b a, b = c.args s = Var("s", T) P2 = Term.mk_abs(s, Q(function.mk_fun_upd(s, a, b(s).beta_conv()))) return apply_theorem(thy, "assign_rule", inst={"b": b}, concl=Valid(T)(P2, c, Q)) elif c.head.is_const_name("Seq"): # Seq c1 c2 c1, c2 = c.args wp1 = compute_wp(thy, T, c2, Q) # Valid Q' c2 Q wp2 = compute_wp(thy, T, c1, wp1.prop.args[0]) # Valid Q'' c1 Q' return apply_theorem(thy, "seq_rule", wp2, wp1) elif c.head.is_const_name("While"): # While b I c _, I, _ = c.args pt = apply_theorem(thy, "while_rule", concl=Valid(T)(I, c, Q)) pt0 = ProofTerm.assume(pt.assums[0]) pt1 = vcg(thy, T, pt.assums[1]) return ProofTerm.implies_elim(pt, pt0, pt1) else: raise NotImplementedError
def process_file(input, output): thy = basic.load_theory('hoare') dn = os.path.dirname(os.path.realpath(__file__)) with open(os.path.join(dn, 'examples/' + input + '.json'), encoding='utf-8') as a: data = json.load(a) output = json_output.JSONTheory(output, ["hoare"], "Generated from " + input) content = data['content'] eval_count = 0 vcg_count = 0 for run in content: if run['ty'] == 'eval': com = parse_hoare(run['com']) st1 = mk_const_fun(nat.natT, nat.zero) for k, v in sorted(run['init'].items()): st1 = mk_fun_upd(st1, nat.to_binary(str_to_nat(k)), nat.to_binary(v)) st2 = mk_const_fun(nat.natT, nat.zero) for k, v in sorted(run['final'].items()): st2 = mk_fun_upd(st2, nat.to_binary(str_to_nat(k)), nat.to_binary(v)) Sem = hoare.Sem(natFunT) goal = Sem(com, st1, st2) prf = ProofTermDeriv("eval_Sem", thy, goal, []).export() rpt = ProofReport() th = thy.check_proof(prf, rpt) output.add_theorem("eval" + str(eval_count), th, prf) eval_count += 1 elif run['ty'] == 'vcg': com = parse_hoare(run['com']) pre = Term.mk_abs(st, parse_cond(run['pre'])) post = Term.mk_abs(st, parse_cond(run['post'])) Valid = hoare.Valid(natFunT) goal = Valid(pre, com, post) prf = hoare.vcg_solve(thy, goal).export() rpt = ProofReport() th = thy.check_proof(prf, rpt) output.add_theorem("vcg" + str(vcg_count), th, prf) vcg_count += 1 else: raise TypeError() output.export_json()
def mk_assign(var_map, s, assigns): """Given a dictionary of assignments, form the corresponding term. Example: given var_map {a: 0, b: 1}, where a is a function and b is a scalar. mk_assign(var_map, s, {a(i): 2}) = (s)(Para (Ident 0) i := 2) mk_assign(var_map, s, {b: 1}) = (s)(Ident 1 := 1) """ assign_args = [] for k, v in assigns.items(): k2 = convert_term(var_map, s, k) assert k2.fun == s, "mk_assign: key is not an identifer." assign_args.append(k2.arg) assign_args.append(convert_term(var_map, s, v)) return function.mk_fun_upd(s, *assign_args)
def testProveEvalI(self): s = function.mk_fun_upd(function.mk_const_fun(natT, zero), one, nat.to_binary(7)) test_data = [ (expr.Plus(expr.V(one), expr.N(nat.to_binary(5))), nat.to_binary(12)), (expr.Plus(expr.V(zero), expr.N(nat.to_binary(5))), nat.to_binary(5)), (expr.Times(expr.V(one), expr.N(nat.to_binary(5))), nat.to_binary(35)), ] for t, n in test_data: goal = expr.avalI(s, t, n) prf = expr.prove_avalI_macro().get_proof_term(thy, goal, []).export() self.assertEqual(thy.check_proof(prf), Thm([], goal))
def testFunUpdTriv(self): thy = basic.load_theory('function') Ta = TVar("a") Tb = TVar("b") f = Var("f", TFun(Ta, Tb)) a = Var("a", Ta) x = Var("x", Ta) prop = Term.mk_equals(function.mk_fun_upd(f, a, f(a)), f) state = ProofState.init_state(thy, [f, a], [], prop) state.apply_backward_step(0, "extension") state.introduction(0, names=["x"]) state.rewrite_goal((0, 1), "fun_upd_eval") state.apply_cases((0, 1), Term.mk_equals(x, a)) state.introduction((0, 1)) state.rewrite_goal((0, 1, 1), "if_P") state.rewrite_goal_with_prev((0, 1, 1), (0, 1, 0)) state.introduction((0, 2)) state.rewrite_goal((0, 2, 1), "if_not_P") self.assertEqual(state.check_proof(no_gaps=True), Thm([], prop))
def fun_upd_of_seq(*ns): return mk_fun_upd(mk_const_fun(natT, zero), *[nat.to_binary(n) for n in ns])
def testStripFunUpd(self): self.assertEqual(strip_fun_upd(f), (f, [])) self.assertEqual(strip_fun_upd(mk_fun_upd(f, a1, b1)), (f, [(a1, b1)])) self.assertEqual(strip_fun_upd(mk_fun_upd(f, a1, b1, a2, b2)), (f, [(a1, b1), (a2, b2)]))
def testMkFunUpd(self): self.assertEqual(mk_fun_upd(f, a1, b1, a2, b2), mk_fun_upd(mk_fun_upd(f, a1, b1), a2, b2))