def testPrintBinary(self): m = Var("m", NatType) test_data = [ (nat.one, "(1::nat)"), (Nat(2), "(2::nat)"), (Nat(3), "(3::nat)"), (m + 1, "m + 1"), ] for t, s in test_data: self.assertEqual(printer.print_term(t), s)
def testComputeWP(self): Q = Var("Q", TFun(natFunT, BoolType)) test_data = [ (Assign(zero, Lambda(s, one)), Lambda(s, Q(mk_fun_upd(s, zero, one)))), (Seq(Assign(zero, Lambda(s, one)), Assign(one, Lambda(s, Nat(2)))), Lambda(s, Q(mk_fun_upd(s, zero, one, one, Nat(2))))), ] for c, P in test_data: prf = imp.compute_wp(natFunT, c, Q).export() self.assertEqual(theory.check_proof(prf), Thm([], Valid(P, c, Q)))
def testProveAvalIFail(self): s = fun_upd_of_seq(1, 7) s2 = Var("s2", TFun(NatType, NatType)) s3 = function.mk_fun_upd(s2, zero, one) macro = expr.prove_avalI_macro() # Value does not match self.assertFalse(macro.can_eval(expr.avalI(s, V(one), Nat(5)))) # State cannot be evaluated self.assertFalse(macro.can_eval(expr.avalI(s2, V(one), Nat(5)))) self.assertFalse(macro.can_eval(expr.avalI(s3, V(one), Nat(5)))) # Goal is not avalI self.assertFalse(macro.can_eval(Eq(V(one), N(zero))))
def testEvalSem(self): com = Seq(Assign(zero, Lambda(s, one)), Assign(one, Lambda(s, Nat(2)))) st = mk_const_fun(NatType, zero) st2 = fun_upd_of_seq(0, 1, 1, 2) goal = Sem(com, st, st2) prf = imp.eval_Sem_macro().get_proof_term(goal, []).export() self.assertEqual(theory.check_proof(prf), Thm([], goal))
def eval(self, goal, ths): assert isinstance(goal, Term), "prove_avalI_macro" assert len(ths) == 0, "prove_avalI_macro" s, t, n = goal.args res = self.get_avalI(s, t) assert n == Nat(res), "prove_avalI_macro: wrong result" return Thm([], goal)
def testEvalFunUpd(self): f = fun_upd_of_seq(1, 5) cv = function.fun_upd_eval_conv() prf = cv.get_proof_term(f(one)).export() self.assertEqual(theory.check_proof(prf), Thm([], Eq(f(one), Nat(5)))) prf = cv.get_proof_term(f(zero)).export() self.assertEqual(theory.check_proof(prf), Thm([], Eq(f(zero), zero)))
def var_expr(self, s): if ord(s) >= ord('a') and ord(s) <= ord('z'): return st(Nat(str_to_nat(s))) elif ord(s) >= ord('A') and ord(s) <= ord('Z'): return Var(s, NatType) else: raise NotImplementedError
def replace_states(self, t): """Replace states by their corresponding numbers.""" if t in self.states: return Nat(self.state_map[t]) elif t.is_comb(): return self.replace_states(t.fun)(self.replace_states(t.arg)) else: return t
def testEvalSem5(self): com = While(Lambda(s, Not(Eq(s(zero), Nat(3)))), assn_true, incr_one) st = mk_const_fun(NatType, zero) st2 = fun_upd_of_seq(0, 3) goal = Sem(com, st, st2) prf = imp.eval_Sem_macro().get_proof_term(goal, []).export() rpt = ProofReport() self.assertEqual(theory.check_proof(prf, rpt), Thm([], goal))
def testProveAvalI(self): s = fun_upd_of_seq(1, 7) test_data = [ (Plus(V(one), N(Nat(5))), Nat(12)), (Plus(V(zero), N(Nat(5))), Nat(5)), (Times(V(one), N(Nat(5))), Nat(35)), ] macro = expr.prove_avalI_macro() for t, n in test_data: goal = expr.avalI(s, t, n) # Test get_avalI self.assertEqual(Nat(macro.get_avalI(s, t)), n) # Test can_eval self.assertTrue(macro.can_eval(goal)) # Test eval self.assertEqual(macro.eval(goal, []), Thm([], goal)) # Test get_proof_term prf = macro.get_proof_term(goal, []).export() self.assertEqual(theory.check_proof(prf), Thm([], goal))
def process_file(input, output): 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[:5]: if run['ty'] == 'eval': com = parse_com(run['com']) st1 = mk_const_fun(NatType, nat.zero) for k, v in sorted(run['init'].items()): st1 = mk_fun_upd(st1, Nat(str_to_nat(k)), Nat(v)) st2 = mk_const_fun(NatType, nat.zero) for k, v in sorted(run['final'].items()): st2 = mk_fun_upd(st2, Nat(str_to_nat(k)), Nat(v)) Sem = imp.Sem(natFunT) goal = Sem(com, st1, st2) prf = ProofTerm("eval_Sem", goal, []).export() rpt = ProofReport() th = theory.check_proof(prf, rpt) output.add_theorem("eval" + str(eval_count), th, prf) eval_count += 1 elif run['ty'] == 'vcg': com = parse_com(run['com']) pre = Lambda(st, parse_cond(run['pre'])) post = Lambda(st, parse_cond(run['post'])) Valid = imp.Valid(natFunT) goal = Valid(pre, com, post) prf = imp.vcg_solve(goal).export() rpt = ProofReport() th = theory.check_proof(prf, rpt) output.add_theorem("vcg" + str(vcg_count), th, prf) vcg_count += 1 else: raise TypeError output.export_json()
def get_proof_term(self, goal, pts): assert len(pts) == 0 and self.can_eval(goal), "nat_const_less_eq_macro" m, n = goal.args assert m.dest_number() <= n.dest_number() p = Nat(n.dest_number() - m.dest_number()) eq = refl(m + p).on_rhs(norm_full()).symmetric() goal2 = rewr_conv('less_eq_exist').eval(goal).prop.rhs ex_eq = apply_theorem('exI', eq, concl=goal2) return ex_eq.on_prop(rewr_conv('less_eq_exist', sym=True))
def can_eval(self, goal): assert isinstance(goal, Term), "prove_avalI_macro" if goal.head != avalI or len(goal.args) != 3: return False s, t, n = goal.args try: res = self.get_avalI(s, t) except AssertionError: return False return n == Nat(res)
def testNatConv(self): test_data = [ ("(2::nat) + 3", 5), ("Suc (2 + 3)", 6), ("Suc (Suc (Suc 0))", 3), ("(5::nat) + 2 * 3", 11), ("((5::nat) + 2) * 3", 21), ("5 * Suc (2 + 5)", 40), ] for t, n in test_data: test_conv(self, 'nat', nat.nat_conv(), t=t, t_res=Nat(n))
def from_mono(m): """Convert a monomial to a term.""" assert isinstance(m, poly.Monomial), "from_mono: input is not a monomial" factors = [] for base, power in m.factors: assert isinstance(base, Term), "from_mono: base is not a Term" baseT = base.get_type() if baseT != RealType: base = Const('of_nat', TFun(baseT, RealType))(base) if power == 1: factors.append(base) else: factors.append(nat_power(base, Nat(power))) if m.coeff != 1: factors = [Real(m.coeff)] + factors return Prod(RealType, factors)
def testVCG(self): P = Var("P", TFun(natFunT, BoolType)) Q = Var("Q", TFun(natFunT, BoolType)) test_data = [ Assign(zero, Lambda(s, one)), Seq(Assign(zero, Lambda(s, one)), Assign(one, Lambda(s, Nat(2)))), ] for c in test_data: goal = Valid(P, c, Q) prf = imp.vcg(natFunT, goal).export() self.assertEqual(theory.check_proof(prf).concl, goal) prf = imp.vcg_tactic().get_proof_term(Thm([], goal), None, []).export() self.assertEqual(theory.check_proof(prf).prop, goal)
def load_system(filename): dn = os.path.dirname(os.path.realpath(__file__)) with open(os.path.join(dn, 'examples/' + filename + '.json'), encoding='utf-8') as a: data = json.load(a) basic.load_theory('gcl') name = data['name'] vars = [] for nm, str_T in data['vars'].items(): T = parser.parse_type(str_T) vars.append(Var(nm, T)) for i, nm in enumerate(data['states']): theory.thy.add_term_sig(nm, NatType) theory.thy.add_theorem(nm + "_def", Thm([], Eq(Const(nm, NatType), Nat(i)))) states = [Const(nm, NatType) for nm in data['states']] rules = [] for rule in data['rules']: if isinstance(rule['var'], str): rule_var = Var(rule['var'], NatType) cur_vars = {v.name: v.T for v in vars + [rule_var]} else: assert isinstance(rule['var'], list) rule_var = [Var(nm, NatType) for nm in rule['var']] cur_vars = {v.name: v.T for v in vars + rule_var} with context.fresh_context(vars=cur_vars): guard = parser.parse_term(rule['guard']) assign = dict() for k, v in rule['assign'].items(): assign[parser.parse_term(k)] = parser.parse_term(v) rules.append((rule_var, guard, assign)) invs = [] for inv in data['invs']: inv_vars = [Var(nm, NatType) for nm in inv['vars']] with context.fresh_context(vars={v.name: v.T for v in vars + inv_vars}): prop = parser.parse_term(inv['prop']) invs.append((inv_vars, prop)) return ParaSystem(name, vars, states, rules, invs)
def testReal(self): basic.load_theory('real') x = Var('x', RealType) y = Var('y', RealType) n = Var('n', NatType) test_data = [ (x + y, "x + y"), (x * y, "x * y"), (x - y, "x - y"), (-x, "-x"), (x - (-y), "x - -y"), (-(-x), "--x"), (-(x - y), "-(x - y)"), (-(x**n), "-(x ^ n)"), ((-x)**n, "-x ^ n"), (x + real.of_nat(Nat(2)), "x + of_nat 2"), (x + Real(1) / 0, "x + 1 / 0"), ] for t, s in test_data: self.assertEqual(printer.print_term(t), s)
def assign_cmd(self, v, e): Assign = imp.Assign(NatType, NatType) return Assign(Nat(str_to_nat(v)), Lambda(st, e))
def num_expr(self, n): return Nat(int(n))
def nat_as_even(n): """Obtain theorem of form even n.""" assert n % 2 == 0, "nat_as_even: n is not even" eq_pt = auto.auto_solve(Eq(Nat(2) * Nat(n // 2), Nat(n))) pt = apply_theorem('even_double', inst=Inst(n=Nat(n // 2))) return pt.on_prop(arg_conv(rewr_conv(eq_pt)))
def get_proof_term(self, t): simp_t = Nat(nat_eval(t)) if simp_t == t: return refl(t) return ProofTerm('nat_eval', Eq(t, simp_t))
def fun_upd_of_seq(*ns): return mk_fun_upd(function.mk_const_fun(NatType, zero), *[Nat(n) for n in ns])
def nat_as_odd(n): """Obtain theorem of form odd n.""" assert n % 2 == 1, "nat_as_odd: n is not odd" eq_pt = auto.auto_solve(Eq(nat.Suc(Nat(2) * Nat(n // 2)), Nat(n))) pt = apply_theorem('odd_double', inst=Inst(n=Nat(n // 2))) return pt.on_prop(arg_conv(rewr_conv(eq_pt)))
def eval(self, t): return Thm([], Eq(t, Nat(nat_eval(t))))