def search_method(self, id, prevs): """Perform search for each method.""" id = ItemID(id) prevs = [ItemID(prev) for prev in prevs] if prevs else [] results = [] all_methods = method.get_all_methods() for name in all_methods: cur_method = all_methods[name] if hasattr(cur_method, 'no_order'): test_prevs = [prevs] else: test_prevs = itertools.permutations(prevs) for perm_prevs in test_prevs: res = cur_method.search(self, id, perm_prevs) for r in res: r['method_name'] = name r['goal_id'] = str(id) if prevs: r['fact_ids'] = list(str(id) for id in perm_prevs) with global_setting(unicode=True, highlight=True): r['display'] = method.output_hint(self, r) results.extend(res) # If there is an element in results that solves the goal, # output only results that solves. if any('_goal' in r and len(r['_goal']) == 0 for r in results): results = list( filter(lambda r: '_goal' in r and len(r['_goal']) == 0, results)) return results
def apply_tactic(self, id, tactic, args=None, prevs=None): id = ItemID(id) prevs = [ItemID(prev) for prev in prevs] if prevs else [] prevs = [ ProofTerm.atom(prev, self.get_proof_item(prev).th) for prev in prevs ] cur_item = self.get_proof_item(id) assert cur_item.rule == "sorry", "apply_tactic: id is not a gap" pt = tactic.get_proof_term(cur_item.th, args=args, prevs=prevs) new_prf = pt.export(prefix=id, subproof=False) self.add_line_before(id, len(new_prf.items) - 1) for i, item in enumerate(new_prf.items): cur_id = item.id prf = self.prf.get_parent_proof(cur_id) prf.items[cur_id.last()] = item self.check_proof(compute_only=True) # Test if the goals are already proved: for item in new_prf.items: if item.rule == 'sorry': new_id = self.find_goal( self.get_proof_item(item.id).th, item.id) if new_id is not None: self.replace_id(item.id, new_id) # Resolve trivial subgoals for item in new_prf.items: if item.rule == 'sorry': if logic.trivial_macro().can_eval(item.th.prop): self.set_line(item.id, 'trivial', args=item.th.prop)
def testCanDependOn(self): test_data = [("0", "0", False), ("0", "1", False), ("1", "0", True), ("1.1", "1.0", True), ("1.1", "1", False), ("2", "1.1", False)] for id1, id2, res in test_data: self.assertEqual(ItemID(id1).can_depend_on(ItemID(id2)), res)
def set_line(self, id, rule, *, args=None, prevs=None, th=None): """Set the item with the given id to the following data.""" id = ItemID(id) prf = self.prf.get_parent_proof(id) prf.items[id.last()] = ProofItem(id, rule, args=args, prevs=prevs, th=th) self.check_proof(compute_only=True)
def remove_line(self, id): """Remove line with the given id.""" id = ItemID(id) prf = self.prf.get_parent_proof(id) split = id.last() prf.items = prf.items[:split] + prf.items[split + 1:] for item in prf.items[split:]: item.decr_proof_item(id) self.check_proof(compute_only=True)
def add_line_before(self, id, n): """Add n lines before the given id.""" id = ItemID(id) prf = self.prf.get_parent_proof(id) split = id.last() new_items = [ProofItem(id.incr_id(i), "") for i in range(n)] prf.items = prf.items[:split] + new_items + prf.items[split:] for item in prf.items[split + n:]: item.incr_proof_item(id, n) self.check_proof(compute_only=True)
def apply_method(state, step): """Apply a method to the state. Here data is a dictionary containing all necessary information. """ method = get_method(step['method_name']) goal_id = ItemID(step['goal_id']) fact_ids = [ItemID(fact_id) for fact_id in step['fact_ids']] \ if 'fact_ids' in step and step['fact_ids'] else [] assert all(goal_id.can_depend_on(fact_id) for fact_id in fact_ids), \ "apply_method: illegal dependence." return method.apply(state, goal_id, step, fact_ids)
def testIncrIdAfter(self): test_data = [ (("0", "0", 1), "1"), (("0.1", "0", 1), "1.1"), (("1", "2.2", 1), "1"), (("2.1", "2.2", 1), "2.1"), (("2.2", "2.2", 1), "2.3"), (("2.3.2", "2.2", 1), "2.4.2"), (("3", "2.2", 1), "3"), ] for (id, start, n), res in test_data: id = ItemID(id) start = ItemID(start) self.assertEqual(str(id.incr_id_after(start, n)), res)
def run_test(self, thy_name, tactic, *, vars=None, prevs=None, goal, args=None, new_goals=None, failed=None): """Test a single invocation of a tactic.""" context.set_context(thy_name, vars=vars) assms = [parser.parse_term(prev) for prev in prevs] if prevs is not None else [] prf = Proof(*assms) prevs = [ ProofTerm.atom(i, Thm.assume(assm)) for i, assm in enumerate(assms) ] goal = parser.parse_term(goal) goal_pt = ProofTerm.sorry(Thm(assms, goal)) # Invoke the tactic to get the proof term if failed is not None: self.assertRaises(failed, tactic.get_proof_term, goal_pt, prevs=prevs, args=args) return pt = tactic.get_proof_term(goal_pt, prevs=prevs, args=args) # Export and check proof prefix = ItemID(len(prevs) - 1) if len(prevs) > 0 else ItemID(len(prevs)) prf = pt.export(prefix=prefix, prf=prf, subproof=False) self.assertEqual(theory.check_proof(prf), Thm(assms, goal)) # Test agreement of new goals new_goals = [parser.parse_term(new_goal) for new_goal in new_goals ] if new_goals is not None else [] concls = [goal.prop for goal in prf.get_sorrys()] self.assertEqual(new_goals, concls)
def rec(pt): # Should not call _export when self is already in seq_to_id assert pt.th not in seq_to_id, "export: th already found." # Should be called only on derivations assert pt.rule != 'atom', "export: atom" ids = [] for prev in pt.prevs: if prev.rule == 'atom': ids.append(prev.args) elif prev.th in seq_to_id: ids.append(seq_to_id[prev.th]) else: rec(prev) ids.append(prf.items[-1].id) if subproof: id = ItemID(prefix.id + (len(prf.items),)) else: id = ItemID(prefix.id[:-1] + (prefix.id[-1] + len(prf.items),)) seq_to_id[pt.th] = id prf.add_item(id, pt.rule, args=pt.args, prevs=ids, th=pt.th)
def get_vars(self, id): """Obtain the context at the given id.""" id = ItemID(id) vars = dict() for v in self.vars: vars[v.name] = v.T prf = self.prf try: for n in id.id: for item in prf.items[:n + 1]: if item.rule == "variable": nm, T = item.args vars[nm] = T prf = prf.items[n].subproof return vars except (AttributeError, IndexError): raise ProofStateException
def export(self, prefix=None, prf=None, subproof=True): """Convert to proof object.""" def rec(pt): # Should not call _export when self is already in seq_to_id assert pt.th not in seq_to_id, "export: th already found." # Should be called only on derivations assert pt.rule != 'atom', "export: atom" ids = [] for prev in pt.prevs: if prev.rule == 'atom': ids.append(prev.args) elif prev.th in seq_to_id: ids.append(seq_to_id[prev.th]) else: rec(prev) ids.append(prf.items[-1].id) if subproof: id = ItemID(prefix.id + (len(prf.items),)) else: id = ItemID(prefix.id[:-1] + (prefix.id[-1] + len(prf.items),)) seq_to_id[pt.th] = id prf.add_item(id, pt.rule, args=pt.args, prevs=ids, th=pt.th) # Current id prefix. Used in generating ids. if prefix is None: prefix = ItemID() # The currently built proof. Updated by the function. if prf is None: prf = Proof() # Mapping from existing sequents to ids. seq_to_id = dict() rec(self) return prf
def apply_search(self, id, method, prevs=None): id = ItemID(id) prevs = [ItemID(prev) for prev in prevs] if prevs else [] return method.search(self, id, prevs)
def get_proof_item(self, id): """Obtain the proof item with the given id.""" return self.prf.find_item(ItemID(id))