def construct_and(proof_step, user_input: [str]) -> CodeForLean: """ Split the target 'P AND Q' into two sub-goals. """ target = proof_step.goal.target.math_type if not target.is_and(is_math_type=True): raise WrongUserInput(error=_("Target is not a conjunction 'P AND Q'")) left = target.children[0] right = target.children[1] if not user_input: # User choice choices = [(_("Left"), left.to_display()), (_("Right"), right.to_display())] raise MissingParametersError( InputType.Choice, choices, title=_("Choose sub-goal"), output=_("Which property to prove first?")) else: if user_input[0] == 1: # Prove second property first if target.node == "PROP_∃": # In this case, first rw target as a conjunction code = CodeForLean.and_then_from_list( ["rw exists_prop", "rw and.comm"]) else: code = CodeForLean.from_string("rw and.comm") left, right = right, left else: code = CodeForLean.empty_code() code = code.and_then("split") code.add_success_msg(_('Target split')) code.add_conjunction(target, left, right) return code
def apply_forall(proof_step, l: [MathObject]) -> CodeForLean: """ Try to apply last selected property on the other ones. The last property should be a universal property (or equivalent to such after unfolding definitions) :param l: list of MathObjects of length ≥ 2 :return: """ # FIXME: return error msg if user try to apply "forall x:X, P(x)" # to some object of wrong type (e.g. implication) # For the moment "forall x, P->Q" works with "P->Q" and button forall goal = proof_step.goal universal_property = l[-1] # The property to be applied unsolved_inequality_counter = 0 # Variable_names will contain the list of variables and proofs of # inequalities that will be passed to universal_property variable_names = [] code = CodeForLean.empty_code() for potential_var in l[:-1]: # TODO: replace by pattern matching # Check for "∀x>0" (and variations) inequality = inequality_from_pattern_matching(universal_property, potential_var) variable_names.append(potential_var.info['name']) if inequality: math_types = [p.math_type for p in goal.context] if inequality in math_types: index = math_types.index(inequality) inequality_name = goal.context[index].display_name variable_names.append(inequality_name) else: inequality_name = get_new_hyp(proof_step) variable_names.append(inequality_name) unsolved_inequality_counter += 1 # Add type indication to the variable in inequality math_type = inequality.children[1].math_type # Variable is not used explicitly, but this affects inequality: variable = inequality.children[0] variable = add_type_indication(variable, math_type) display_inequality = inequality.to_display(is_math_type=False, format_='lean') # Code I: state corresponding inequality # code = code.and_then(f"have {inequality_name}: " f"{display_inequality}") code = code.and_then("rotate") # Code II: Apply universal_property # new_hypo_name = get_new_hyp(proof_step) code = code.and_then( have_new_property(universal_property, variable_names, new_hypo_name)) # Code III: try to solve inequalities # e.g.: # iterate 2 { solve1 {try {norm_num at *}, try {compute_n 10}} <|> # rotate}, rotate, more_code = CodeForLean.empty_code() if unsolved_inequality_counter: code = code.and_then("rotate") # back to first inequality more_code1 = CodeForLean.from_string("norm_num at *") more_code1 = more_code1.try_() more_code2 = CodeForLean.from_string("compute_n 1") more_code2 = more_code2.try_() # Try to solve1 inequality by norm_num, maybe followed by compute: more_code = more_code1.and_then(more_code2) more_code = more_code.single_combinator("solve1") # If it fails, rotate to next inequality more_code = more_code.or_else("rotate") # Do this for all inequalities # more_code = more_code.single_combinator(f"iterate # {unsolved_inequality_counter}") --> replaced by explicit iteration code_list = [more_code] * unsolved_inequality_counter more_code = CodeForLean.and_then_from_list(code_list) # Finally come back to first inequality more_code = more_code.and_then("rotate") code.add_success_msg( _("Property {} added to the context").format(new_hypo_name)) return code.and_then(more_code)