def get_proof(self): invC = Const("inv", TFun(gcl.stateT, BoolType)) transC = Const("trans", TFun(gcl.stateT, gcl.stateT, BoolType)) s1 = Var("s1", gcl.stateT) s2 = Var("s2", gcl.stateT) prop = Thm([], Implies(invC(s1), transC(s1, s2), invC(s2))) # print(printer.print_thm(prop)) trans_pt = ProofTerm.assume(transC(s1, s2)) # print(printer.print_thm(trans_pt.th)) P = Implies(invC(s1), invC(s2)) ind_pt = apply_theorem("trans_cases", inst=Inst(a1=s1, a2=s2, P=P)) # print(printer.print_thm(ind_pt.th)) ind_As, ind_C = ind_pt.prop.strip_implies() for ind_A in ind_As[1:-1]: # print("ind_A: ", ind_A) vars, As, C = logic.strip_all_implies(ind_A, ["s", "k"]) # for A in As: # print("A: ", A) # print("C: ", C) eq1 = ProofTerm.assume(As[0]) eq2 = ProofTerm.assume(As[1]) guard = ProofTerm.assume(As[2]) inv_pre = ProofTerm.assume(As[3]).on_arg(rewr_conv(eq1)).on_prop( rewr_conv("inv_def")) C_goal = ProofTerm.assume(C).on_arg(rewr_conv(eq2)).on_prop( rewr_conv("inv_def"))
def testInductList(self): Ta = TVar("a") Tlista = Type("list", Ta) list_ext = induct.add_induct_type( "list", ["a"], [("nil", Tlista, []), ("cons", TFun(Ta, Tlista, Tlista), ["x", "xs"])]) nil = Const("nil", Tlista) cons = Const("cons", TFun(Ta, Tlista, Tlista)) x = Var("x", Ta) xs = Var("xs", Tlista) x2 = Var("x'", Ta) xs2 = Var("xs'", Tlista) P = Var("P", TFun(Tlista, boolT)) xlist = Var("x", Tlista) res = [ AxType("list", 1), AxConstant("nil", Tlista), AxConstant("cons", TFun(Ta, Tlista, Tlista)), Theorem("list_nil_cons_neq", Thm([], logic.neg(eq(nil, cons(x, xs))))), Theorem("list_cons_inject", Thm([], imp(eq(cons(x, xs), cons(x2, xs2)), conj(eq(x, x2), eq(xs, xs2))))), Theorem("list_induct", Thm([], imp(P(nil), all(x, all(xs, imp(P(xs), P(cons(x, xs))))), P(xlist)))), Attribute("list_induct", "var_induct") ] self.assertEqual(list_ext.data, res)
def number(self, n): if int(n) == 0: return Const("zero", None) elif int(n) == 1: return Const("one", None) else: return Const("of_nat", None)(Binary(int(n)))
def get_proof(self): invC = Const("inv", TFun(gcl.stateT, boolT)) transC = Const("trans", TFun(gcl.stateT, gcl.stateT, boolT)) s1 = Var("s1", gcl.stateT) s2 = Var("s2", gcl.stateT) prop = Thm.mk_implies(invC(s1), transC(s1, s2), invC(s2)) # print(printer.print_thm(self.thy, prop)) trans_pt = ProofTerm.assume(transC(s1, s2)) # print(printer.print_thm(self.thy, trans_pt.th)) P = Term.mk_implies(invC(s1), invC(s2)) ind_pt = apply_theorem(self.thy, "trans_cases", inst={ "a1": s1, "a2": s2, "P": P }) # print(printer.print_thm(self.thy, ind_pt.th)) ind_As, ind_C = ind_pt.prop.strip_implies() for ind_A in ind_As[1:-1]: # print("ind_A: ", printer.print_term(self.thy, ind_A)) vars, As, C = logic.strip_all_implies(ind_A, ["s", "k"]) # for A in As: # print("A: ", printer.print_term(self.thy, A)) # print("C: ", printer.print_term(self.thy, C)) eq1 = ProofTerm.assume(As[0]) eq2 = ProofTerm.assume(As[1]) guard = ProofTerm.assume(As[2]) inv_pre = ProofTerm.assume(As[3]).on_arg(self.thy, rewr_conv(eq1)) \ .on_prop(self.thy, rewr_conv("inv_def")) C_goal = ProofTerm.assume(C).on_arg(self.thy, rewr_conv(eq2)) \ .on_prop(self.thy, rewr_conv("inv_def"))
def testInferPrintedType(self): t = Const("nil", listT(Ta)) infer_printed_type(thy, t) self.assertTrue(hasattr(t, "print_type")) t = list.cons(Ta)(Var("a", Ta)) infer_printed_type(thy, t) self.assertFalse(hasattr(t.fun, "print_type")) t = Term.mk_equals(Const("nil", listT(Ta)), Const("nil", listT(Ta))) infer_printed_type(thy, t) self.assertFalse(hasattr(t.fun.fun, "print_type")) self.assertTrue(hasattr(t.arg1, "print_type")) self.assertFalse(hasattr(t.arg, "print_type")) t = Term.mk_equals(list.mk_append(list.nil(Ta), list.nil(Ta)), list.nil(Ta)) infer_printed_type(thy, t) self.assertTrue(hasattr(t.arg1.arg1, "print_type")) self.assertFalse(hasattr(t.arg1.arg, "print_type")) self.assertFalse(hasattr(t.arg, "print_type")) t = Term.mk_abs(Var("x", Ta), Term.mk_equals(Var("x", Ta), Var("x", Ta))) infer_printed_type(thy, t)
def testInferTypeFail(self): test_data = [(Const("implies", None)(Var("A1", nat.natT), Var("A2", None))), (Const("equals", None)(Var("A", None), Var("a", None)))] for t in test_data: self.assertRaisesRegex(TypeInferenceException, "Unable to unify", type_infer, thy, ctxt, t)
def testInferTypeFail2(self): test_data = [ Abs("x", None, Abs("y", None, Const("equals", None)(Var("x", None), Var("y", None)))), Const("nil", None), ] for t in test_data: self.assertRaisesRegex(TypeInferenceException, "Unspecified type", type_infer, t)
def testInferType(self): test_data = [ # A1 --> A2 (Const("implies", None)(Var("A1", None), Var("A2", None)), Term.mk_implies(Var("A1", boolT), Var("A2", boolT))), # A1 = A2 (Const("equals", None)(Var("A1", boolT), Var("A2", None)), Term.mk_equals(Var("A1", boolT), Var("A2", boolT))), # a = b (Const("equals", None)(Var("a", None), Var("b", None)), Const("equals", TFun(Ta, Ta, boolT))(Var("a", Ta), Var("b", Ta))), # %x. P x (Abs("x", None, Var("P", None)(Bound(0))), Abs("x", Ta, Var("P", TFun(Ta, boolT))(Bound(0)))), # %x y. x = y (Abs("x", Ta, Abs("y", None, Const("equals", None)(Bound(1), Bound(0)))), Abs( "x", Ta, Abs("y", Ta, Const("equals", TFun(Ta, Ta, boolT))(Bound(1), Bound(0))))), # [a] (Const("cons", None)(Var("a", None), Const("nil", None)), list.cons(Ta)(Var("a", Ta), Const("nil", listT(Ta)))), ] for t, res in test_data: self.assertEqual(type_infer(thy, ctxt, t), res)
def testToInternalVars(self): test_data = [ (Var("x", TVar("a")), Var("_x", TVar("_a"))), (Var("x", natT), Var("_x", natT)), (Const("x", TVar("a")), Const("x", TVar("_a"))), (Const("x", natT), Const("x", natT)), (Abs("x", TVar("a"), Var("y", TVar("b"))), Abs("x", TVar("_a"), Var("_y", TVar("_b")))), ] for t, res in test_data: self.assertEqual(matcher.to_internal_vars(t), res)
def testRewrConvWithAssum(self): x = Const("x", natT) y = Const("y", natT) x_eq_y = Term.mk_equals(x, y) th = Thm([], Term.mk_implies(x_eq_y, x_eq_y)) cv = arg_conv(rewr_conv(ProofTerm.atom(0, th))) f = Const("f", TFun(natT, natT)) res = Thm([x_eq_y], Term.mk_equals(f(x), f(y))) self.assertEqual(cv.eval(thy, f(x)), res) prf = Proof() prf.add_item(0, "sorry", th=th) cv.get_proof_term(thy, f(x)).export(prf=prf) self.assertEqual(thy.check_proof(prf), res)
def testSubstType(self): test_data = [ (Var('a', STa), Var("a", Tb)), (Const("c", STa), Const("c", Tb)), (Var("f", TFun(STa, Tb))(Var("a", STa)), Var("f", TFun(Tb, Tb))(Var("a", Tb))), (Abs("x", STa, B0), Abs("x", Tb, B0)), (Abs("x", STa, Var('a', STa)), Abs("x", Tb, Var("a", Tb))), ] for t, res in test_data: self.assertEqual(t.subst_type(TyInst(a=Tb)), res)
def testAbsConv(self): nat0 = Const("zero", natT) nat1 = Const("one", natT) f = Const("f", TFun(natT, natT)) g = Const("g", TFun(natT, natT)) x = Var("x", natT) thy.add_theorem("f_eq_g", eq(f(x), g(x))) t = Term.mk_abs(x, f(x)) cv = abs_conv(rewr_conv("f_eq_g")) res_th = eq(t, Term.mk_abs(x, g(x))) self.assertEqual(cv.eval(thy, t), res_th) prf = cv.get_proof_term(thy, t).export() self.assertEqual(thy.check_proof(prf), res_th)
def testFirstOrderMatchFun(self): """First-order matching of variables in function position.""" P = Var("P", TFun(Ta, boolT)) Q = Var("Q", TFun(Ta, boolT)) C = Const("C", TFun(boolT, boolT, boolT)) test_data = [ (abs(x, P(x)), abs(x, C(P(x), Q(x))), { "P": abs(x, C(P(x), Q(x))) }), (abs(x, C(P(x), Q(x))), abs(x, C(Q(x), P(x))), { "P": Q, "Q": P }), (abs(x, C(P(x), P(x))), abs(x, C(C(P(x), Q(x)), C(P(x), Q(x)))), { "P": abs(x, C(P(x), Q(x))) }), (exists(x, P(x)), exists(x, conj(P(x), Q(x))), { "P": abs(x, conj(P(x), Q(x))) }), ] for pat, t, inst in test_data: if inst is not None: self.assertEqual(matcher.first_order_match(pat, t)[1], inst) else: self.assertRaises(matcher.MatchException, matcher.first_order_match, pat, t)
def get_proof_term(self, t): assert t.is_equals() or t.is_less_eq() or t.is_less()\ or t.is_greater_eq() or t.is_greater(), "%s is not an equality term" % t pt1 = refl(t) # a = b <==> a = b if t.is_equals(): pt2 = pt1.on_rhs(rewr_conv('int_sub_move_0_r', sym=True)) # a = b <==> a - b = 0 eq_refl = ProofTerm.reflexive(equals(IntType)) elif t.is_less_eq(): pt2 = pt1.on_rhs(rewr_conv('int_leq')) eq_refl = ProofTerm.reflexive(less_eq(IntType)) elif t.is_less(): pt2 = pt1.on_rhs(rewr_conv('int_less')) eq_refl = ProofTerm.reflexive(less(IntType)) elif t.is_greater_eq(): pt2 = pt1.on_rhs(rewr_conv('int_geq')) eq_refl = ProofTerm.reflexive(greater_eq(IntType)) elif t.is_greater(): pt2 = pt1.on_rhs(rewr_conv('int_gt')) eq_refl = ProofTerm.reflexive(greater(IntType)) pt3 = simp_full().get_proof_term( pt2.prop.arg.arg1) # a - b = a + (-1) * b pt4 = ProofTerm.combination(eq_refl, pt3) pt5 = ProofTerm.combination(pt4, refl(Const( 'zero', IntType))) # a - b = 0 <==> a + (-1)*b = 0 return pt2.transitive(pt5) # a = b <==> a + (-1) * b = 0
def get_extension(self): assert self.error is None, "get_extension" res = [] res.append( extension.Constant(self.name, self.type, ref_name=self.cname)) for rule in self.rules: res.append(extension.Theorem(rule['name'], Thm([], rule['prop']))) res.append(extension.Attribute(rule['name'], 'hint_backward')) # Case rule Targs, _ = self.type.strip_type() vars = [] for i, Targ in enumerate(Targs): vars.append(Var("_a" + str(i + 1), Targ)) P = Var("P", BoolType) pred = Const(self.name, self.type) assum0 = pred(*vars) assums = [] for rule in self.rules: prop = rule['prop'] As, C = prop.strip_implies() eq_assums = [Eq(var, arg) for var, arg in zip(vars, C.args)] assum = Implies(*(eq_assums + As), P) for var in reversed(prop.get_vars()): assum = Forall(var, assum) assums.append(assum) prop = Implies(*([assum0] + assums + [P])) res.append(extension.Theorem(self.cname + "_cases", Thm([], prop))) return res
def parse(self, data): self.name = data['name'] try: self.type = parser.parse_type(data['type']) self.cname = theory.thy.get_overload_const_name( self.name, self.type) for rule in data['rules']: with context.fresh_context(defs={self.name: self.type}): prop = parser.parse_term(rule['prop']) # Test conclusion of the prop _, concl = prop.strip_implies() f, _ = concl.strip_comb() if f != Const(self.name, self.type): raise ItemException( "Inductive %s: wrong head of conclusion" % self.name) self.rules.append({'name': rule['name'], 'prop': prop}) except Exception as error: self.type = data['type'] self.rules = data['rules'] self.error = error self.trace = traceback2.format_exc()
def parse(self, data): self.name = data['name'] try: self.type = parser.parse_type(data['type']) self.cname = theory.thy.get_overload_const_name( self.name, self.type) for rule in data['rules']: with context.fresh_context(defs={self.name: self.type}): prop = parser.parse_term(rule['prop']) # prop should be an equality if not prop.is_equals(): raise ItemException("Fun %s: rule is not an equality" % self.name) f, args = prop.lhs.strip_comb() if f != Const(self.name, self.type): raise ItemException("Fun %s: wrong head of lhs" % self.name) lhs_vars = set(v.name for v in prop.lhs.get_vars()) rhs_vars = set(v.name for v in prop.rhs.get_vars()) if not rhs_vars.issubset(lhs_vars): raise ItemException( "Fun %s: extra variables in rhs: %s" % (self.name, ", ".join(v for v in rhs_vars - lhs_vars))) self.rules.append({'prop': prop}) except Exception as error: self.type = data['type'] self.rules = data['rules'] self.error = error self.trace = traceback2.format_exc()
def mk_exists(x, body): """Given a variable x and a term t possibly depending on x, return the term ?x. t. """ exists_t = Const("exists", TFun(TFun(x.T, boolT), boolT)) return exists_t(Term.mk_abs(x, body))
class NatComparison(Macro): oprmap = { '<=': Ind('Coq.Init.Peano.le', 0), '<': Const('Coq.Init.Peano.lt'), '=': Apply(Ind('Coq.Init.Logic.eq', 0), NatType()) } @classmethod def name(cls): return "net_comparison" def __init__(self, opr, l, r): assert opr in ('<=', '<', '='), "unsupported comparison operator %s" % opr self.opr = opr self.l = l self.r = r def check(self, environment=None): _, sideff_l = self.l.check(environment) _, sideff_r = self.r.check(environment) return Sort.mkProp(), set.union(sideff_l, sideff_r) def render(self, environment=None, debug=False): return "(%s %s %s)" % ( self.l.render(environment, debug), self.opr, self.r.render(environment, debug), ) def unfold(self): return Apply(self.oprmap[self.opr], self.l, self.r)
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 mk_exists1(x, body): """Given a variable x and a term P possibly depending on x, return the term ?!x. P. """ assert x.is_var(), "mk_exists1" exists1_t = Const("exists1", TFun(TFun(x.T, BoolType), BoolType)) return exists1_t(Lambda(x, body))
def testCheckedExtend(self): """Checked extension: adding an axiom.""" id_simps = Eq(Comb(Const("id", TFun(Ta,Ta)), x), x) exts = [extension.Theorem("id.simps", Thm([], id_simps))] ext_report = theory.thy.checked_extend(exts) self.assertEqual(theory.get_theorem("id.simps", svar=False), Thm([], id_simps)) self.assertEqual(ext_report.get_axioms(), [("id.simps", Thm([], id_simps))])
def helper(*args): if len(args) == 3: f, a, b = args return Const("fun_upd", None)(f, a, b) elif len(args) > 3: return helper(helper(*args[:3]), *args[3:]) else: raise TypeError()
def mk_some(x, body): """Given a variable x and a term P possibly depending on x, return the term SOME x. P. """ assert x.is_var(), "mk_some" some_t = Const("Some", TFun(TFun(x.T, BoolType), x.T)) return some_t(Lambda(x, body))
def vname(self, s): s = str(s) if theory.thy.has_term_sig(s) or s in context.ctxt.defs: # s is the name of a constant in the theory return Const(s, None) else: # s not found, either bound or free variable return Var(s, None)
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) thy = basic.load_theory('gcl') name = data['name'] vars = [] for nm, str_T in data['vars'].items(): T = parser.parse_type(thy, str_T) vars.append(Var(nm, T)) for i, nm in enumerate(data['states']): thy.add_term_sig(nm, natT) thy.add_theorem(nm + "_def", Thm.mk_equals(Const(nm, natT), to_binary(i))) states = [Const(nm, natT) for nm in data['states']] rules = [] for rule in data['rules']: if isinstance(rule['var'], str): rule_var = Var(rule['var'], natT) ctxt = dict((v.name, v.T) for v in vars + [rule_var]) else: assert isinstance(rule['var'], list) rule_var = [Var(nm, natT) for nm in rule['var']] ctxt = dict((v.name, v.T) for v in vars + rule_var) guard = parser.parse_term(thy, ctxt, rule['guard']) assign = dict() for k, v in rule['assign'].items(): assign[parser.parse_term(thy, ctxt, k)] = parser.parse_term(thy, ctxt, v) rules.append((rule_var, guard, assign)) invs = [] for inv in data['invs']: inv_vars = [Var(nm, natT) for nm in inv['vars']] ctxt = dict((v.name, v.T) for v in vars + inv_vars) prop = parser.parse_term(thy, ctxt, inv['prop']) invs.append((inv_vars, prop)) return ParaSystem(thy, name, vars, states, rules, invs)
def vname(self, s): thy = parser_setting['thy'] s = str(s) if thy.has_term_sig(s): # s is the name of a constant in the theory return Const(s, None) else: # s not found, either bound or free variable return Var(s, None)
def testIsPattern(self): test_data = [ (Var('a', Ta), True), (Var('f', TFun(Ta, Tb))(Var('a', Ta)), False), (Const('f', TFun(Ta, Tb))(Var('a', Ta)), True), ] for t, res in test_data: self.assertEqual(matcher.is_pattern(t, []), res)
def within(net, S): """Form the term within net S. net -- a term of type 'a net. S -- a term of type 'a set. """ Ta = net.get_type().args[0] return Const('within', TFun(netT(Ta), set.setT(Ta), netT(Ta)))(net, S)
class BinaryNumberExpr(Macro): oprmap = { '+': None, '-': None, '*': None, '/': None, '%': None, '&': None, '|': None, '>>': None, '<<': None, '>': None, '>=': None, '<=': Const('Coq.ZArith.BinInt.Z.le'), '<': Const('Coq.ZArith.BinInt.Z.lt'), '=': Apply(Ind('Coq.Init.Logic.eq', 0), BinaryNumberType()), '==': None, '!=': None, } def __init__(self, opr, l, r=None): assert opr in self.oprmap, "unsupported operator %s" % opr self.opr = opr self.l = l self.r = r def type(self, environment=None): return Sort.mkProp() def check(self, environment=None): _, sideff_l = self.l.check(environment) _, sideff_r = self.r.check(environment) return Sort.mkProp(), set.union(sideff_l, sideff_r) def render(self, environment=None, debug=False): return "(%s %s %s)" % ( self.l.render(environment, debug), self.opr, self.r.render(environment, debug), ) def unfold(self): return Apply(self.oprmap[self.opr], self.l, self.r)