def testReprType(self): test_data = [ (Ta, "TVar(a)"), (Type("bool"), "Type(bool, [])"), (Type("list", Ta), "Type(list, [TVar(a)])"), (Type("tree", Ta, Tb), "Type(tree, [TVar(a), TVar(b)])"), (Type("fun", Ta, Tb), "Type(fun, [TVar(a), TVar(b)])"), ] for T, repr_T in test_data: self.assertEqual(repr(T), repr_T)
def testCheckTypeFail(self): test_data = [ Type("bool", Ta), Type("bool", Ta, Ta), Type("fun"), Type("fun", Ta), Type("fun", Ta, Ta, Ta), TFun(Type("bool", Ta), Type("bool")), TFun(Type("bool"), Type("bool", Ta)), Type("random") ] for T in test_data: self.assertRaises(TheoryException, thy.check_type, T)
def to_internal_tvars(pat_T): """Add underscore to each type variable in the pattern.""" if pat_T.ty == HOLType.TVAR: return TVar("_" + pat_T.name) elif pat_T.ty == HOLType.TYPE: return Type(pat_T.name, *[to_internal_tvars(arg) for arg in pat_T.args])
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 run_test(self, thy_name, pat, t, *, vars=None, svars=None, tyinst=None, inst=None, failed=None): context.set_context(thy_name, vars=vars, svars=svars) pat, t = Term(pat), Term(t) inst = Inst((nm, Term(s)) for nm, s in inst.items()) if inst is not None else Inst() if tyinst is not None: inst.tyinst = TyInst((nm, Type(s)) for nm, s in tyinst.items()) if failed is not None: self.assertRaises(failed, first_order_match, pat, t) return self.assertEqual(first_order_match(pat, t), inst)
def testSubst(self): test_data = [ (Ta, { "a": Tb }, Tb), (Ta, { "b": Tb }, Ta), (TFun(Ta, Tb), { "a": Tb }, TFun(Tb, Tb)), (TFun(Ta, Tb), { "a": Tb, "b": Ta }, TFun(Tb, Ta)), (Type("list", Ta), { "a": Tb }, Type("list", Tb)), ] for T, tyinst, res in test_data: self.assertEqual(T.subst(tyinst), res)
def check_modify(): """Check a modified item for validity.""" data = json.loads(request.get_data().decode("utf-8")) error = {} item = data['content'] thy = basic.load_theory('list') if item['ty'] == 'thm' or item['ty'] == 'thm.ax': vars = {} for v in item['vars'].split('\n'): (nm, T) = parser.parse_thm_vars(thy, v) if nm: vars[nm.strip()] = T.strip() item['vars'] = vars if item['ty'] == 'type.ind': constrs, temp_list = [], [] if len(item['data_name'].split(' ')) > 1: temp_list.append(item['data_name'].split(' ')[0][1:]) item['name'] = item['data_name'].split(' ')[1] else: item['name'] = item['data_name'] item['args'] = temp_list apd = Type(item['name'], *(TVar(nm) for nm in item['args'])) for c in item['data_content'].split('\n'): constr = parser.parse_type_ind(thy, c) type_list = constr['type'] + [apd] constr['type'] = str(TFun(type_list)) constrs.append(constr) item['constrs'] = constrs # if item['ty'] == 'def.ind' or item['ty'] == 'def' or item['ty'] == 'def.pred': # item['name'] = parser.parse_thm_vars(thy, item['data_name'])[0] # item['type'] = parser.parse_thm_vars(thy, item['data_name'])[1] with open_file(data['file_name'], 'r') as f: f_data = json.load(f) try: thy = basic.load_imported_theory(f_data['imports'], user_info['username']) for d in data['prev_list']: parser.parse_extension(thy, d) file_data_to_output(thy, item) except Exception as e: exc_detailed = traceback2.format_exc() return jsonify({ "failed": e.__class__.__name__, "message": str(e), "detail_content": exc_detailed }) return jsonify({'content': item, 'error': error})
def testInductAdd(self): nat = Type("nat") plus = Const("plus", TFun(nat, nat, nat)) zero = Const("zero", nat) S = Const("Suc", TFun(nat, nat)) m = Var("m", nat) n = Var("n", nat) ext = induct.add_induct_def( 'plus', TFun(nat, nat, nat), [ eq(plus(zero, n), n), eq(plus(S(m), n), S(plus(m, n)))]) res = [ AxConstant("plus", TFun(nat, nat, nat)), Theorem("plus_def_1", Thm([], eq(plus(zero, n), n))), Attribute("plus_def_1", "hint_rewrite"), Theorem("plus_def_2", Thm([], eq(plus(S(m), n), S(plus(m, n))))), Attribute("plus_def_2", "hint_rewrite"), ] self.assertEqual(ext.data, res)
def testInductPredicate(self): nat = Type("nat") even = Const("even", TFun(nat, boolT)) zero = Const("zero", nat) Suc = Const("Suc", TFun(nat, nat)) n = Var("n", nat) prop_zero = even(zero) prop_Suc = Term.mk_implies(even(n), even(Suc(Suc(n)))) data = [("even_zero", prop_zero), ("even_Suc", prop_Suc)] even_ext = induct.add_induct_predicate("even", TFun(nat, boolT), data) a1 = Var("_a1", nat) P = Var("P", boolT) res = [ AxConstant("even", TFun(nat, boolT)), Theorem("even_zero", Thm([], even(zero))), Attribute("even_zero", "hint_backward"), Theorem("even_Suc", Thm.mk_implies(even(n), even(Suc(Suc(n))))), Attribute("even_Suc", "hint_backward"), Theorem("even_cases", Thm.mk_implies(even(a1), imp(eq(a1,zero), P), all(n, imp(eq(a1,Suc(Suc(n))), even(n), P)), P)) ] self.assertEqual(even_ext.data, res)
def testInductProd(self): Ta = TVar("a") Tb = TVar("b") Tab = Type("prod", Ta, Tb) prod_ext = induct.add_induct_type( "prod", ["a", "b"], [("Pair", TFun(Ta, Tb, Tab), ["a", "b"])]) a = Var("a", Ta) b = Var("b", Tb) a2 = Var("a'", Ta) b2 = Var("b'", Tb) pair = Const("Pair", TFun(Ta, Tb, Tab)) P = Var("P", TFun(Tab, boolT)) x = Var("x", Tab) res = [ AxType("prod", 2), AxConstant("Pair", TFun(Ta, Tb, Tab)), Theorem("prod_Pair_inject", Thm([], imp(eq(pair(a, b), pair(a2, b2)), conj(eq(a, a2), eq(b, b2))))), Theorem("prod_induct", Thm([], imp(all(a, all(b, P(pair(a, b)))), P(x)))), Attribute("prod_induct", "var_induct") ] self.assertEqual(prod_ext.data, res)
def testInductNat(self): nat = Type("nat") nat_ext = induct.add_induct_type( "nat", [], [("zero", nat, []), ("Suc", TFun(nat, nat), ["n"])]) zero = Const("zero", nat) S = Const("Suc", TFun(nat, nat)) n = Var("n", nat) n2 = Var("n'", nat) x = Var("x", nat) P = Var("P", TFun(nat, boolT)) res = [ AxType("nat", 0), AxConstant("zero", nat), AxConstant("Suc", TFun(nat, nat)), Theorem("nat_zero_Suc_neq", Thm([], logic.neg(eq(zero, S(n))))), Theorem("nat_Suc_inject", Thm([], imp(eq(S(n), S(n2)), eq(n, n2)))), Theorem("nat_induct", Thm([], imp(P(zero), all(n, imp(P(n), P(S(n)))), P(x)))), Attribute("nat_induct", "var_induct") ] self.assertEqual(nat_ext.data, res)
# Author: Bohua Zhan from kernel.type import Type, TFun from kernel.term import Term, Const from kernel.thm import Thm from kernel import macro from logic.conv import Conv, ConvException, all_conv, rewr_conv, \ then_conv, arg_conv, arg1_conv, every_conv, binop_conv from logic.proofterm import ProofTerm, ProofTermMacro, ProofTermDeriv, refl from logic.logic_macro import apply_theorem from logic import logic from logic import term_ord """Utility functions for natural number arithmetic.""" natT = Type("nat") zero = Const("zero", natT) Suc = Const("Suc", TFun(natT, natT)) one = Suc(zero) plus = Const("plus", TFun(natT, natT, natT)) times = Const("times", TFun(natT, natT, natT)) def is_Suc(t): return t.is_comb() and t.fun == Suc def mk_plus(*args): if not args: return zero elif len(args) == 1: return args[0]
def add_induct_type(name, targs, constrs): """Add the given inductive type to the theory. The inductive type is specified by name, arity (as list of default names of type arguments), and a list of constructors (triple consisting of name of the constant, type of the constant, and a list of suggested names of the arguments). For example, the natural numbers is specified by: (nat, [], [(0, nat, []), (Suc, nat => nat, ["n"])]). List type is specified by: (list, ["a"], [(nil, 'a list, []), (cons, 'a => 'a list => 'a list, ["x", "xs"])]). """ exts = TheoryExtension() # Add to type and term signature. exts.add_extension(AxType(name, len(targs))) for cname, cT, _ in constrs: exts.add_extension(AxConstant(cname, cT)) # Add non-equality theorems. for (cname1, cT1, vars1), (cname2, cT2, vars2) in itertools.combinations(constrs, 2): # For each A x_1 ... x_m and B y_1 ... y_n, get the theorem # ~ A x_1 ... x_m = B y_1 ... y_n. argT1, _ = cT1.strip_type() argT2, _ = cT2.strip_type() lhs_vars = [Var(nm, T) for nm, T in zip(vars1, argT1)] rhs_vars = [Var(nm, T) for nm, T in zip(vars2, argT2)] A = Const(cname1, cT1) B = Const(cname2, cT2) lhs = A(*lhs_vars) rhs = B(*rhs_vars) neq = logic.neg(Term.mk_equals(lhs, rhs)) th_name = name + "_" + cname1 + "_" + cname2 + "_neq" exts.add_extension(Theorem(th_name, Thm([], neq))) # Add injectivity theorems. for cname, cT, vars in constrs: # For each A x_1 ... x_m with m > 0, get the theorem # A x_1 ... x_m = A x_1' ... x_m' --> x_1 = x_1' & ... & x_m = x_m' if vars: argT, _ = cT.strip_type() lhs_vars = [Var(nm, T) for nm, T in zip(vars, argT)] rhs_vars = [Var(nm + "'", T) for nm, T in zip(vars, argT)] A = Const(cname, cT) assum = Term.mk_equals(A(*lhs_vars), A(*rhs_vars)) concls = [ Term.mk_equals(var1, var2) for var1, var2 in zip(lhs_vars, rhs_vars) ] concl = logic.mk_conj(*concls) if len(concls) > 1 else concls[0] th_name = name + "_" + cname + "_inject" exts.add_extension(Theorem(th_name, Thm.mk_implies(assum, concl))) # Add the inductive theorem. tvars = [TVar(targ) for targ in targs] T = Type(name, *tvars) var_P = Var("P", TFun(T, boolT)) ind_assums = [] for cname, cT, vars in constrs: A = Const(cname, cT) argT, _ = cT.strip_type() args = [Var(nm, T2) for nm, T2 in zip(vars, argT)] C = var_P(A(*args)) As = [var_P(Var(nm, T2)) for nm, T2 in zip(vars, argT) if T2 == T] ind_assum = Term.mk_implies(*(As + [C])) for arg in reversed(args): ind_assum = Term.mk_all(arg, ind_assum) ind_assums.append(ind_assum) ind_concl = var_P(Var("x", T)) th_name = name + "_induct" exts.add_extension( Theorem(th_name, Thm.mk_implies(*(ind_assums + [ind_concl])))) exts.add_extension(Attribute(th_name, "var_induct")) return exts
def setT(T): return Type("set", T)
def type(self, *args): return Type(str(args[-1]), *args[:-1])
# Author: Bohua Zhan """Utility functions for GCL (Guarded Command Language).""" from kernel.type import TFun, Type, boolT from kernel.term import Term, Const from logic import basic from logic.nat import natT, to_binary from logic import logic from logic import function thy = basic.load_theory("gcl") varType = Type("varType") Ident = Const("Ident", TFun(natT, varType)) Para = Const("Para", TFun(varType, natT, varType)) scalarValue = Type("scalarValue") NatV = Const("NatV", TFun(natT, scalarValue)) BoolV = Const("BoolV", TFun(boolT, scalarValue)) stateT = TFun(varType, scalarValue) def convert_term(var_map, s, t): """Convert term t with given var_map and state s. Examples: given var_map {a: 0, b: 1}, where a is a function and b is a scalar. convert_term(var_map, s, b) = s (Ident 1) convert_term(var_map, s, a(i)) = s (Para (Ident 0) i)
ctxt = { "A": boolT, "B": boolT, "C": boolT, "P": TFun(Ta, boolT), "Q": TFun(Ta, boolT), "R": TFun(Ta, Ta, boolT), "a": Ta, "b": Ta, "c": Ta, "f": TFun(Ta, Ta), "nn": TFun(boolT, boolT), "m": nat.natT, "n": nat.natT, "p": nat.natT, "xs": Type("list", Ta), "ys": Type("list", Ta), "zs": Type("list", Ta), } A = Var("A", boolT) B = Var("B", boolT) C = Var("C", boolT) class ParserTest(unittest.TestCase): def testParseType(self): test_data = [ "'b", "nat", "'a list",
A = Var("A", boolT) B = Var("B", boolT) C = Var("C", boolT) Ta = TVar("a") a = Var("a", Ta) b = Var("b", Ta) P = Var("P", TFun(Ta, boolT)) Q = Var("Q", TFun(Ta, boolT)) R = Var("R", TFun(Ta, Ta, boolT)) f = Var("f", TFun(Ta, Ta)) nn = Var("n", TFun(boolT, boolT)) m = Var("m", nat.natT) n = Var("n", nat.natT) p = Var("p", nat.natT) xs = Var("xs", Type("list", Ta)) ys = Var("ys", Type("list", Ta)) zs = Var("zs", Type("list", Ta)) eq = Term.mk_equals imp = Term.mk_implies conj = logic.mk_conj disj = logic.mk_disj abs = Term.mk_abs all = Term.mk_all neg = logic.neg exists = logic.mk_exists mk_if = logic.mk_if class PrinterTest(unittest.TestCase): def testPrintLogical(self): test_data = [
# Author: Bohua Zhan from kernel.type import Type, TFun, boolT from kernel.term import Term, Const from kernel.thm import Thm from kernel.macro import global_macros from logic import logic from logic import nat from logic import function from logic.nat import natT from logic.conv import arg_conv from logic.proofterm import ProofTermMacro, ProofTerm from logic.logic_macro import apply_theorem """Automation for arithmetic expressions.""" aexpT = Type("aexp") N = Const("N", TFun(natT, aexpT)) V = Const("V", TFun(natT, aexpT)) Plus = Const("Plus", TFun(aexpT, aexpT, aexpT)) Times = Const("Times", TFun(aexpT, aexpT, aexpT)) avalI = Const("avalI", TFun(TFun(natT, natT), aexpT, natT, boolT)) class prove_avalI_macro(ProofTermMacro): """Prove a theorem of the form avalI s t n.""" def __init__(self): self.level = 10 self.sig = Term
def file_data_to_output(thy, data): """Convert items in the theory from json format for the file to json format for the web client. Modifies data in-place. Also modifies argument thy in parsing the item. """ parser.parse_extension(thy, data) if data['ty'] == 'def.ax': T = parser.parse_type(thy, data['type']) data['type_hl'] = printer.print_type(thy, T, unicode=True, highlight=True) elif data['ty'] == 'thm' or data['ty'] == 'thm.ax': temp_list = [] for k, v in data['vars'].items(): temp_list.append(k + ' :: ' + v) ctxt = parser.parse_vars(thy, data['vars']) prop = parser.parse_term(thy, ctxt, data['prop']) data['prop_hl'] = printer.print_term(thy, prop, unicode=True, highlight=True) data['vars_lines'] = temp_list elif data['ty'] == 'type.ind': constrs = [] data_content = '' for constr in data['constrs']: T = parser.parse_type(thy, constr['type']) constrs.append((constr['name'], T, constr['args'])) exts = induct.add_induct_type(data['name'], data['args'], constrs) # Obtain items added by the extension ext_output = [] for ext in exts.data: s = print_extension(thy, ext) if s: ext_output.append(s) data['ext'] = ext_output # Obtain type to be defined T = Type(data['name'], *(TVar(nm) for nm in data['args'])) data['type_hl'] = printer.print_type(thy, T, unicode=True, highlight=True) # Obtain types of arguments for each constructor data['argsT'] = dict() for i, constr in enumerate(data['constrs']): str_temp_var = '' T = parser.parse_type(thy, constr['type']) argsT, _ = HOLType.strip_type(T) argsT = [ printer.print_type(thy, argT, unicode=True, highlight=True) for argT in argsT ] data['argsT'][str(i)] = argsT for j, a in enumerate(constr['args']): str_temp_term = '' for m, t in enumerate(data['argsT'][str(i)][j]): str_temp_term += t[0] str_temp_var += ' (' + a + ' :: ' + str_temp_term + ')' data_content += '\n' + constr['name'] + str_temp_var data['type_content'] = data_content elif data['ty'] == 'def.ind' or data['ty'] == 'def.pred': container = [[], [], [], '', '', ''] data_content_list, data_rule_names, data_vars_list, data_new_content, data_rule_name, data_vars_str = container T = parser.parse_type(thy, data['type']) data['type_hl'] = printer.print_type(thy, T, unicode=True, highlight=True) rules = [] for rule in data['rules']: ctxt = parser.parse_vars(thy, rule['vars']) prop = parser.parse_term(thy, ctxt, rule['prop']) rule['prop_hl'] = printer.print_term(thy, prop, unicode=True, highlight=True) rules.append(prop) exts = induct.add_induct_def(data['name'], T, rules) # Obtain items added by the extension ext_output = [] for ext in exts.data: s = print_extension(thy, ext) if s: ext_output.append(s) data['ext'] = ext_output if data['ty'] == 'def.ind': type_name = 'fun' if data['ty'] == 'def.pred': type_name = 'inductive' data['ext_output'] = '\n'.join(ext_output) data['type_name'] = type_name for k, r in enumerate(data['rules']): vars_str = '' data_con = '' for m, v in enumerate(r['vars']): vars_str += str(m) + '::' + v + ' ' data_vars_list.append(vars_str) for p in r['prop_hl']: data_con += p[0] data_content_list.append(data_con) if 'name' in r: data_rule_names.append(r['name']) for n, dv in enumerate(data_vars_list): data_vars_str += str(n) + ': ' + dv + '\n' for j, dc in enumerate(data_content_list): data_new_content += str(j) + ': ' + dc + '\n' data_rule_name += str(j) + ': ' + dc + '\n' data['data_new_content'] = data_new_content data['data_rule_name'] = data_rule_name data['data_vars_str'] = data_vars_str elif data['ty'] == 'def': i = 0 vars = '' data_new_content = '' data_content_list = [] data_content_list.append(data['prop']) for j, dc in enumerate(data_content_list): data_new_content += str(j) + ': ' + dc + '\n' for j, v in enumerate(data['vars']): vars += str(i) + ': ' + str(j) + '::' + v + '\n' i += 1 data['item_vars'] = vars T = parser.parse_type(thy, data['type']) data['type_name'] = 'definition' data['data_new_content'] = data_new_content data['type_hl'] = printer.print_type(thy, T, unicode=True, highlight=True) ctxt = parser.parse_vars(thy, data['vars']) prop = parser.parse_term(thy, ctxt, data['prop']) data['prop_hl'] = printer.print_term(thy, prop, unicode=True, highlight=True) # Ignore other types of information. else: pass
def comT(T): return Type("com", T)
def testPrintType(self): test_data = [ (Ta, "'a"), (TVar("ab"), "'ab"), (Type("bool"), "bool"), (Type("list", Ta), "'a list"), (Type("list", Type("list", Ta)), "'a list list"), (Type("tree", Ta, Tb), "('a, 'b) tree"), (TFun(Ta, Tb), "'a => 'b"), (TFun(Ta, Tb, Tc), "'a => 'b => 'c"), (TFun(TFun(Ta, Tb), Tc), "('a => 'b) => 'c"), (TFun(Type("list", Ta), Tb), "'a list => 'b"), (TFun(Ta, Type("list", Tb)), "'a => 'b list"), (Type("list", TFun(Ta, Tb)), "('a => 'b) list"), (Type("list", Type("list", TFun(Ta, Tb))), "('a => 'b) list list"), (TFun(Type("list", Ta), Type("list", Tb)), "'a list => 'b list"), (Type("list", TFun(Type("list", Ta), Tb)), "('a list => 'b) list"), ] for T, str_T in test_data: self.assertEqual(str(T), str_T)
def testParseConstructor(self): T = Type("'a => 'b") self.assertEqual(T, TFun(TVar('a'), TVar('b'))) t = Term("(A::bool)") self.assertEqual(t, Var('A', BoolType))