def testSolve(self): if not z3wrapper.z3_loaded: return context.set_context('nat', vars={ "s": 'nat => nat', "A": 'nat', "B": 'nat' }) test_data = [ ("s 0 = 0 & s 1 = 0 --> s 1 = s 0 * B", True), ("s 1 = s 0 * B & ~~s 0 = A --> s 1 = A * B", True), ("s 1 = s 0 * B & ~s 0 = A --> s 1 + B = (s 0 + 1) * B", True), ("A * B + 1 = 1 + B * A", True), ("s 0 = s 1", False), ("s 0 + s 1 = A --> A + s 2 = B --> s 0 + s 2 + s 1 = B", True), ("s 0 + s 1 = A --> A + s 2 = B --> s 0 + s 2 = B", False), ("(!n. s n = 0) --> s 2 = 0", True), ("(!n. s n = 0) --> s 0 = 1", False), ] for s, res in test_data: t = parser.parse_term(s) self.assertEqual(z3wrapper.solve(t), res)
def testSymPySolve2(self): test_data = [ # Interval condition ("1 - x ^ (2::nat) >= 0", "x Mem real_closed_interval 0 1", True), ("1 - x ^ (2::nat) >= 0", "x Mem real_closed_interval 0 (sqrt 2)", False), ("1 - x ^ (2::nat) > 0", "x Mem real_open_interval 0 1", True), ("2 - x ^ (2::nat) >= 0", "x Mem real_closed_interval 0 (sqrt 2)", True), ("2 - x ^ (2::nat) >= 0", "x Mem real_closed_interval 0 2", False), ("sqrt 2 * cos x >= 0", "x Mem real_closed_interval 0 (pi / 2)", True), ("sqrt 2 * cos x >= 0", "x Mem real_closed_interval 0 pi", False), ("log x >= 0", "x Mem real_closed_interval 1 (exp 1)", True), ("log x <= 0", "x Mem real_closed_interval (exp (-1)) 1", True), ("log x >= 0", "x Mem real_closed_interval (exp (-1)) (exp 1)", False), ("~(sin x = 0)", "x Mem real_closed_interval 1 2", True), ("~(sin x = 0)", "x Mem real_closed_interval (-1) 1", False), ("~(sin x = 0)", "x Mem real_closed_interval 0 1", False), ("~(x ^ (2::nat) = 0)", "x Mem real_closed_interval (-1) 1", False), ("~(x ^ (2::nat) + 1 = 0)", "x Mem real_closed_interval (-1) 1", True), ] context.set_context('transcendentals', vars={'x': 'real'}) for goal, cond, res in test_data: goal = parser.parse_term(goal) cond = parser.parse_term(cond) self.assertEqual(sympywrapper.solve_with_interval(goal, cond), res)
def create_cache(self, data): self.username = data['username'] self.theory_name = data['theory_name'] self.thm_name = data['thm_name'] self.vars = data['vars'] self.prop = data['prop'] self.steps = data['steps'] if self.thm_name != '': limit = ('thm', self.thm_name) else: limit = None context.set_context(self.theory_name, limit=limit, username=self.username, vars=self.vars) state = server.parse_init_state(self.prop) self.history = [] self.states = [copy.copy(state)] self.error = None for step in self.steps: self.history.extend(state.parse_steps([step])) self.states.append(copy.copy(state)) try: state.check_proof() except Exception as e: self.error = { 'err_type': e.__class__.__name__, 'err_str': str(e), 'trace': traceback2.format_exc() }
def run_test(self, thy_name, s, expected_res, **kwargs): context.set_context(thy_name) t = parser.parse_term(s) with global_setting(**kwargs): ast = pprint.get_ast_term(t) res = pprint.print_ast(ast) self.assertEqual(res, expected_res)
def testGetBoundsProof(self): test_data = [ ("x + 3", "[0, 1]", "[3, 4]"), ("x + 3", "(0, 1)", "(3, 4)"), ("3 + x", "(0, 1)", "(3, 4)"), ("x + x", "(0, 1)", "(0, 2)"), ("-x", "[0, 2]", "[-2, 0]"), ("-x", "(1, 3)", "(-3, -1)"), ("-x", "(-1, 1)", "(-1, 1)"), ("x - 3", "[0, 1]", "[-3, -2]"), ("3 - x", "(0, 1)", "(2, 3)"), ("2 * x", "[0, 1]", "[0, 2]"), ("1 / x", "[1, 2]", "[1/2, 1]"), ("x ^ 2", "[1, 2]", "[1, 4]"), ("x ^ 2", "(-1, 0)", "(0, 1)"), ("x ^ 3", "(-1, 0)", "(-1, 0)"), ("sin(x)", "(0, pi/2)", "(0, 1)"), ("sin(x)", "(-pi/2, 0)", "(-1, 0)"), ("cos(x)", "(0, pi/2)", "(0, 1)"), ("cos(x)", "(-pi/2, pi/2)", "(0, 1]"), ("x ^ (1/2)", "(0, 4)", "(0, 2)"), ("log(x)", "(1, exp(2))", "(0, 2)"), ] context.set_context('interval_arith') for s, i1, i2 in test_data: t = expr_to_holpy(parse_expr(s)) cond = hol_set.mk_mem(term.Var('x', RealType), interval_to_holpy(parse_interval(i1))) var_range = {'x': ProofTerm.assume(cond)} res = hol_set.mk_mem(t, interval_to_holpy(parse_interval(i2))) pt = get_bounds_proof(t, var_range) self.assertEqual(pt.prop, res)
def testParseUnicode(self): test_data = [ ("A ∧ B", "A & B"), ("A ∨ B", "A | B"), ("A ⟶ B ⟶ C", "A --> B --> C"), ("A ∧ B | C", "A & B | C"), ("¬A", "~A"), ("λx::'a. x", "%x::'a. x"), ("∀x::'a. P x", "!x. P x"), ("∃x::'a. P x", "?x. P x"), ("∀x::'a. P x ∧ Q x", "!x. P x & Q x"), ("(∀x::'a. P x) & Q y", "(!x. P x) & Q y"), ] context.set_context('logic_base', vars={ 'A': 'bool', 'B': 'bool', 'C': 'bool', 'P': "'a => bool", 'Q': "'a => bool" }) for s, ascii_s in test_data: t = parser.parse_term(s) self.assertIsInstance(t, Term) with global_setting(unicode=False): self.assertEqual(print_term(t), ascii_s)
def testJsonData(self): context.set_context('logic_base', vars={'A': 'bool', 'B': 'bool'}) state = server.parse_init_state("A & B --> B & A") json_data = state.json_data() self.assertEqual(len(json_data['vars']), 2) self.assertEqual(len(json_data['proof']), 3) self.assertEqual(json_data['num_gaps'], 1)
def testRecSolveSet(self): test_data = [ ('x Mem S --> S Sub T --> x Mem T', 'S x, ~(T x), !x1. S x1 --> T x1 |- false'), ('m Mem univ', '~true |- false'), ('x Mem (diff S T) --> x Mem S', '~(S x), S x & ~(T x) |- false'), ('(?x1. x = x1 & x1 Mem S) --> x Mem S', '~(S x), ?x1. x = x1 & S x1 |- false'), ('(?a1. a = a1 & a1 Mem A) --> a Mem A', '~(A a), ?a1. a = a1 & A a1 |- false'), ] for t, p in test_data: context.set_context('smt', vars={ 'm': 'nat', 'S': 'nat set', 'T': 'nat set', 'x': 'nat', 'a': "'a", 'A': "'a set" }) t = parse_term(t) proof, assertions = z3wrapper.solve_and_proof(t) r = proofrec.proofrec(proof, assertions=assertions, trace=True) self.assertNotEqual(r.rule, 'sorry')
def testNormAbsoluteValue(self): test_data = [ ("abs x", ["x >= 0"], "x"), ("abs x", ["x Mem real_closed_interval 0 1"], "x"), ("abs x", ["x Mem real_closed_interval (-1) 0"], "-1 * x"), ("abs (sin x)", ["x Mem real_closed_interval 0 (pi / 2)"], "sin x"), ("abs (sin x)", ["x Mem real_closed_interval (-pi / 2) 0"], "-1 * sin x"), ("abs (log x)", ["x Mem real_open_interval (exp (-1)) 1"], "-1 * log x"), ] vars = {'x': 'real'} context.set_context('interval_arith', vars=vars) for t, conds, res in test_data: conds_pt = [ ProofTerm.assume(parser.parse_term(cond)) for cond in conds ] cv = auto.auto_conv(conds_pt) test_conv(self, 'interval_arith', cv, vars=vars, t=t, t_res=res, assms=conds)
def testRec1(self): test_data = [ # ('s 0 = 0 & s 1 = 0 --> s 1 = s 0 * B', # '~(s 1 = s 0 * B), s 0 = 0 & s 1 = 0 |- false'), ('s 1 = s 0 * B & ~~s 0 = A --> s 1 = A * B', '~(s 1 = A * B), s 1 = s 0 * B & s 0 = A |- false'), ('s 1 = s 0 * B & ~s 0 = A --> s 1 + B = (s 0 + 1) * B', '~(s 1 + B = (s 0 + 1) * B), s 1 = s 0 * B & ~(s 0 = A) |- false' ), ('A * B + 1 = 1 + B * A', '~(A * B + 1 = 1 + B * A) |- false'), ('s 0 + s 1 = A --> A + s 2 = B --> s 0 + s 2 + s 1 = B', 's 0 + s 1 = A, A + s 2 = B, ~(s 0 + s 2 + s 1 = B) |- false'), ('(!n. s n = 0) --> s 2 = 0', '!n. s n = 0, ~(s 2 = 0) |- false') ] for t, p in test_data: context.set_context('smt', vars={ "s": 'nat => nat', "A": 'nat', "B": 'nat' }) t = parse_term(t) proof, assertions = z3wrapper.solve_and_proof(t) r = proofrec.proofrec(proof, assertions=assertions, trace=True) self.assertNotEqual(r.rule, 'sorry')
def testRewriteIntWithAsserstion(self): test_data = [( "¬(¬(¬(¬P8 ∨ ¬(F20 + -1 * F18 ≤ 0)) ∨ ¬(P8 ∨ ¬(F4 + -1 * F2 ≤ 0))) ∨ ¬(¬(P8 ∨ ¬(F6 + -1 * F4 ≤ 0)) ∨ \ ¬(¬P8 ∨ ¬(F22 + -1 * F20 ≤ 0))) ∨ ¬(¬(P8 ∨ ¬(F2 + -1 * F0 ≤ 0)) ∨ ¬(¬P8 ∨ ¬(F18 + -1 * F16 ≤ 0))))\ ⟷ ¬(¬(F2 + -1 * F0 ≤ 0) ∨ ¬(F6 + -1 * F4 ≤ 0) ∨ ¬(F4 + -1 * F2 ≤ 0))", ("P8", "P8 ⟷ false"))] context.set_context('smt', vars={ "P8": "bool", "F20": "int", "F18": "int", "P8": "bool", "F4": "int", "F2": "int", "F6": "int", "F22": "int", "F20": "int", "F2": "int", "F16": "int", "F0": "int" }) for tm, ast in test_data: tm = parse_term(tm) var, prop = [parse_term(i) for i in ast] proofrec.atoms.clear() proofrec.atoms[var] = ProofTerm.assume(prop) proofrec._rewrite(tm)
def testCombineFractionConv(self): test_data = [ ('1 / (x + 1) + 1 / (x - 1)', 'x Mem real_open_interval (-1/2) (1/2)', '2 * x / ((x + 1) * (x - 1))'), ("2 + 1 / (x + 1)", 'x Mem real_open_interval 0 1', '(3 + 2 * x) / (x + 1)'), ("(x + 1) ^ -(1::real)", 'x Mem real_open_interval 0 1', '1 / (x + 1)'), ("2 * (x * (x + 1) ^ -(1::real))", 'x Mem real_open_interval 0 1', '2 * x / (x + 1)'), ("2 - 1 / (x + 1)", 'x Mem real_open_interval 0 1', '(1 + 2 * x) / (x + 1)'), ("x ^ (1/2)", "x Mem real_open_interval 0 1", "x ^ (1/2) / 1"), ("x ^ -(1/2)", "x Mem real_open_interval 0 1", "1 / (x ^ (1/2))"), ("x ^ -(2::real)", "x Mem real_open_interval 0 1", "1 / (x ^ (2::nat))"), ] vars = {'x': 'real'} context.set_context('interval_arith', vars=vars) for s, cond, res in test_data: s = parser.parse_term(s) res = parser.parse_term(res) cond_t = parser.parse_term(cond) cv = proof.combine_fraction([ProofTerm.assume(cond_t)]) test_conv(self, 'interval_arith', cv, vars=vars, t=s, t_res=res, assms=[cond])
def testThLemmaIntSingle(self): test_data = [ # ¬(y ≤ 3), y ≤ 4 ⊢ 0 = -4 + y, # y ≥ 0, y ≤ 0 ⊢ 1 = 1 + y, # y ≥ 0, ¬(y ≥ 1) ⊢ 1 = 1 + y, "x ≥ 1 ∨ x ≤ 0", "¬(x ≥ 2) ∨ ¬(x ≤ 0)", "¬(x ≥ 1) ∨ ¬(x ≤ 0)", "¬(x ≤ 2) ∨ x ≤ 3", "¬(x ≤ 3) ∨ ¬(x ≥ 4)", "¬(x = 4) ∨ x ≤ 4", "¬(1 = x) ∨ x ≥ 1", "¬(x ≤ 0) ∨ 4 + x = (if x ≤ 0 then 4 + x else -1 + x)", "1 = x ∨ ¬(x ≤ 1) ∨ ¬(x ≥ 1)", "3 = -1 + x ∨ ¬(-1 + x ≤ 3) ∨ ¬(-1 + x ≥ 3)", "x = 3 ∨ ¬(x ≤ 3) ∨ ¬(x ≥ 3)", # "x ≥ 4 ∨ 1 + x = (if x ≥ 4 then -4 + x else 1 + x)", # "¬(4 + x = (if x ≤ 0 then 4 + x else -1 + x)) ∨ 4 + x + -1 * (if x ≤ 0 then 4 + x else -1 + x) ≥ 0)", # "¬(-1 + x = (if x ≤ 0 then 4 + x else -1 + x)) ∨ -1 + x + -1 * (if x ≤ 0 then 4 + x else -1 + x) ≥ 0)", "¬(Succ x = 3) ∨ Succ x ≤ 3", "¬(Sum (Pred x) (Succ y) ≥ 2) ∨ ¬(Sum (Pred x) (Succ y) ≤ 1)", "¬(Sum (Pred x) (Succ y) = 2) ∨ Sum (Pred x) (Succ y) ≥ 2", ] context.set_context('smt', vars={ "x": "int", "Succ": "int => int", "Pred": "int => int", "Sum": "int => int => int" }) for tm in test_data: tm = parse_term(tm) self.assertNotEqual(proofrec.th_lemma([tm]).rule, 'sorry')
def testVCGIf(self): context.set_context(None, vars={'A': 'nat'}) c = parser.parse_term("Cond (%s. s (0::nat) = A) Skip (Assign 0 (%s. A))") P = parser.parse_term("%s::nat=>nat. true") Q = parser.parse_term("%s. s (0::nat) = A") goal = Valid(P, c, Q) prf = imp.vcg_solve(goal).export() self.assertEqual(theory.check_proof(prf), Thm([], goal))
def testParseNamedThm(self): A = Var('A', BoolType) B = Var('B', BoolType) test_data = [("conjI: A = B", ('conjI', Eq(A, B))), ("A = B", (None, Eq(A, B)))] context.set_context('logic_base', vars={'A': 'bool', 'B': 'bool'}) for s, res in test_data: self.assertEqual(parser.parse_named_thm(s), res)
def testVCGWhile(self): context.set_context(None, vars={"A": 'nat', "B": 'nat'}) c = parser.parse_term( "While (%s. ~s (0::nat) = A) (%s. s 1 = s 0 * B) (Seq (Assign 1 (%s. s 1 + B)) (Assign 0 (%s. s 0 + 1)))") P = parser.parse_term("%s. s (0::nat) = (0::nat) & s 1 = 0") Q = parser.parse_term("%s. s (1::nat) = A * B") goal = Valid(P, c, Q) prf = imp.vcg_solve(goal).export() self.assertEqual(theory.check_proof(prf), Thm([], goal))
def run_test(self, thy_name, *, vars=None, svars=None, s, Ts): context.set_context(thy_name, vars=vars, svars=svars) t = parser.parse_term(s) T = parser.parse_type(Ts) self.assertIsInstance(t, Term) self.assertEqual(t.checked_get_type(), T) # with global_setting(unicode=False): self.assertEqual(print_term(t), s)
def testSetLine(self): context.set_context('logic_base', vars={'A': 'bool', 'B': 'bool'}) state = server.parse_init_state("A & B --> B & A") state.add_line_before(2, 1) state.set_line(2, "theorem", args="conjD1") self.assertEqual(len(state.prf.items), 4) self.assertEqual(state.check_proof(), parser.parse_thm("|- A & B --> B & A"))
def testRemoveLine(self): context.set_context('logic_base', vars={'A': 'bool', 'B': 'bool'}) state = server.parse_init_state("A & B --> B & A") state.add_line_before(2, 1) state.remove_line(2) self.assertEqual(len(state.prf.items), 3) self.assertEqual(state.check_proof(), parser.parse_thm("|- A & B --> B & A"))
def testNormRealDerivative(self): test_data = [ # Differentiable everywhere ("real_derivative (%x. x) x", [], "(1::real)"), ("real_derivative (%x. 3) x", [], "(0::real)"), ("real_derivative (%x. 3 * x) x", [], "(3::real)"), ("real_derivative (%x. x ^ (2::nat)) x", [], "2 * x"), ("real_derivative (%x. x ^ (3::nat)) x", [], "3 * x ^ (2::nat)"), ("real_derivative (%x. (x + 1) ^ (3::nat)) x", [], "3 + 6 * x + 3 * x ^ (2::nat)"), ("real_derivative (%x. exp x) x", [], "exp x"), ("real_derivative (%x. exp (x ^ (2::nat))) x", [], "2 * (exp (x ^ (2::nat)) * x)"), # ("real_derivative (%x. exp (exp x)) x", [], "exp (x + exp x)"), ("real_derivative (%x. sin x) x", [], "cos x"), ("real_derivative (%x. cos x) x", [], "-1 * sin x"), ("real_derivative (%x. sin x * cos x) x", [], "(cos x) ^ (2::nat) + -1 * (sin x) ^ (2::nat)"), # Differentiable with conditions ("real_derivative (%x. 1 / x) x", ["x Mem real_open_interval 0 1"], "-1 * x ^ -(2::real)"), ("real_derivative (%x. 1 / (x ^ (2::nat) + 1)) x", ["x Mem real_open_interval (-1) 1"], "-2 * (x * (1 + 2 * x ^ (2::nat) + x ^ (4::nat)) ^ -(1::real))"), ("real_derivative (%x. log x) x", ["x Mem real_open_interval 0 1"], "x ^ -(1::real)"), ("real_derivative (%x. log (sin x)) x", ["x Mem real_open_interval 0 1"], "cos x * (sin x) ^ -(1::real)"), ("real_derivative (%x. sqrt x) x", ["x Mem real_open_interval 0 1"], "1 / 2 * x ^ -(1 / 2)"), ("real_derivative (%x. sqrt (x ^ (2::nat) + 1)) x", ["x Mem real_open_interval (-1) 1" ], "x * (1 + x ^ (2::nat)) ^ -(1 / 2)"), # Real power ("real_derivative (%x. x ^ (1 / 3)) x", ["x Mem real_open_interval 0 1"], "1 / 3 * x ^ -(2 / 3)"), ("real_derivative (%x. 2 ^ x) x", ["x Mem real_open_interval (-1) 1"], "log 2 * 2 ^ x"), ] vars = {'x': 'real'} context.set_context('interval_arith', vars=vars) for t, conds, res in test_data: conds_pt = [ ProofTerm.assume(parser.parse_term(cond)) for cond in conds ] cv = auto.auto_conv(conds_pt) test_conv(self, 'interval_arith', cv, vars=vars, t=t, t_res=res, assms=conds)
def testSolveNat(self): if not z3wrapper.z3_loaded: return context.set_context('set', vars={'x': 'nat', 'y': 'nat', 'z': 'nat'}) test_data = [('x - y + z = x + z - y', False), ('x >= y --> x - y + z = x + z - y', True)] for s, res in test_data: t = parser.parse_term(s) self.assertEqual(z3wrapper.solve(t), res)
def testPelletier(self): with open('prover/tests/pelletier.json', 'r', encoding='utf-8') as f: f_data = json.load(f) for problem in f_data: context.set_context('sat', vars=problem['vars']) prop = parser.parse_term(problem['prop']) cnf = tseitin.convert_cnf(tseitin.encode(Not(prop)).prop) res, cert = sat.solve_cnf(cnf) self.assertEqual(res, 'unsatisfiable')
def testHasBound0(self): test_data = [ ("%y::'a. !x::'a. y = y", True), ("%x::'a. y = y", False) ] context.set_context('logic', vars={'y': "'a"}) for fm, res in test_data: fm = parser.parse_term(fm) self.assertEqual(fologic.has_bound0(fm.body), res)
def testThLemmaIntMulti(self): test_data = [(('¬(x ≤ 3)', 'x ≤ 4'), '0 = -4 + x'), (('x ≥ 0', 'x ≤ 0'), '1 = 1 + x'), (('x ≥ 0', '¬(x ≥ 1)'), '1 = 1 + x')] context.set_context('smt', vars={'x': 'int'}) for assms, res in test_data: assms = [ProofTerm.assume(parse_term(assm)) for assm in assms] res = parse_term(res) self.assertEqual(proofrec.th_lemma([*assms, res]).prop, res)
def testNormDisjDisjunction(self): test_data = [ ('(A | B) | (C | D)', 'A | B | C | D'), ('(C | D) | (A | B)', 'A | B | C | D') ] vars = {'A': 'bool', 'B': 'bool', 'C': 'bool'} context.set_context('logic', vars=vars) for t, res in test_data: t, res = parser.parse_term(t), parser.parse_term(res) test_conv(self, 'logic', proplogic.norm_disj_disjunction(), vars=vars, t=t, t_res=res)
def testParseProof2(self): data = [{ 'id': 0, 'rule': 'variable', 'args': "a, 'a", 'prevs': [], 'th': '' }] context.set_context('logic_base') state = server.parse_proof(data) self.assertEqual(len(state.prf.items), 1)
def testNormConjConjunction(self): test_data = [ ('(A & B) & (C & D)', 'A & B & C & D'), ('(C & D) & (A & B)', 'A & B & C & D') ] vars = {'A': 'bool', 'B': 'bool', 'C': 'bool'} context.set_context('logic', vars=vars) for t, res in test_data: t, res = parser.parse_term(t), parser.parse_term(res) test_conv(self, 'logic', proplogic.norm_conj_conjunction(), vars=vars, t=t, t_res=res)
def testSwapDisjRConv(self): test_data = [ ('A | B', 'B | A'), ('A | B | C', 'B | A | C'), ] vars = {'A': 'bool', 'B': 'bool', 'C': 'bool'} context.set_context('logic', vars=vars) for t, res in test_data: t, res = parser.parse_term(t), parser.parse_term(res) test_conv(self, 'logic', proplogic.swap_disj_r(), vars=vars, t=t, t_res=res)
def testConvert(self): test_data = [ ("1 - x ^ (2::nat)", 1 - x**2), ("sqrt(2) * sin(x)", sqrt(2) * sin(x)), ("real_closed_interval 0 1", sympy.Interval(0, 1)), ("real_open_interval 0 1", sympy.Interval.open(0, 1)), ] context.set_context('realintegral', vars={'x': 'real'}) for s, res in test_data: s = parser.parse_term(s) self.assertEqual(sympywrapper.convert(s), res)
def testExprToHolpy(self): test_data = [ ("INT x:[2,3]. 2 * x + x ^ 2", "real_integral (real_closed_interval 2 3) (%x. 2 * x + x ^ (2::nat))" ), ] context.set_context('interval_arith', vars={'x': 'real'}) for s, res in test_data: s = integral.parser.parse_expr(s) res = parser.parse_term(res) self.assertEqual(proof.expr_to_holpy(s), res)