示例#1
0
def construct_or_on_hyp(proof_step,
                        selected_property: [MathObject],
                        user_input: [str] = None) -> CodeForLean:
    """
    Construct a property 'P or Q' from property 'P' or property 'Q'.
    Here we assume selected_object contains 1 or 2 items.
    """
    if not user_input:
        user_input = []
    possible_codes = []
    first_hypo_name = selected_property[0].info["name"]
    hypo = selected_property[0].math_type.to_display()

    if len(selected_property) == 2:
        if not (selected_property[0].math_type.is_prop()
                and selected_property[1].math_type.is_prop()):
            error = _("Selected items are not properties")
            raise WrongUserInput(error)
        else:
            second_selected_property = selected_property[1].info["name"]
    elif len(selected_property) == 1:
        if not selected_property[0].math_type.is_prop():
            error = _("Selected item is not a property")
            raise WrongUserInput(error)
        if not user_input:
            raise MissingParametersError(
                InputType.Text,
                title=_("Obtain 'P OR Q'"),
                output=_("Enter the proposition you want to use:"))
        else:
            second_selected_property = user_input[0]
            user_input = user_input[1:]

    if not user_input:
        raise MissingParametersError(
            InputType.Choice,
            [(_("Left"), f'({hypo}) OR ({second_selected_property})'),
             (_('Right'), f'({second_selected_property}) OR ({hypo})')],
            title=_("Choose side"),
            output=_(f'On which side do you want') + f' {hypo} ?')

    new_hypo_name = get_new_hyp(proof_step)
    if user_input[0] == 0:
        possible_codes.append(f'have {new_hypo_name} := '
                              f'@or.inl _ ({second_selected_property}) '
                              f'({first_hypo_name})')
    elif user_input[0] == 1:
        possible_codes.append(f'have {new_hypo_name} := '
                              f'@or.inr ({second_selected_property}) _ '
                              f'({first_hypo_name})')
    else:
        raise WrongUserInput("Unexpected error")
    code = CodeForLean.or_else_from_list(possible_codes)
    code.add_success_msg(
        _('Property {} added to the context').format(new_hypo_name))
    return code
示例#2
0
def action_theorem(proof_step,
                   selected_objects: [MathObject],
                   theorem,
                   target_selected: bool = True
                   ):
    """
    Apply theorem on selected objects or target.
    """

    # test_selection(selected_objects, target_selected)

    # TODO: For an iff statement, use rewriting
    #  test for iff or equality is removed since it works only with
    #  pkl files

    goal = proof_step.goal

    codes = rw_using_statement(goal, selected_objects, theorem)

    h = get_new_hyp(proof_step)
    th = theorem.lean_name
    if len(selected_objects) == 0:
        codes = codes.or_else(f'apply {th}',
                              success_msg=_('theorem applied to target'))
        codes = codes.or_else(f'have {h} := @{th}',
                              success_msg=_('theorem added to the context'))
    else:
        command = f'have {h} := {th}'
        command_implicit = f'have {h} := @{th}'
        names = [item.info['name'] for item in selected_objects]
        arguments = ' '.join(names)
        # up to 4 implicit arguments
        more_codes = [f'apply {th} {arguments}',
                      f'apply @{th} {arguments}']
        more_codes += [command + arguments,
                       command_implicit + arguments,
                       command + ' _ ' + arguments,
                       command_implicit + ' _ ' + arguments,
                       command + ' _ _ ' + arguments,
                       command_implicit + ' _ _ ' + arguments,
                       command + ' _ _ _ ' + arguments,
                       command_implicit + ' _ _ _ ' + arguments,
                       command + ' _ _ _ _ ' + arguments,
                       command_implicit + ' _ _ _ _ ' + arguments
                       ]
        more_codes = CodeForLean.or_else_from_list(more_codes)
        context_msg = _('theorem') + ' ' + _('applied to') + ' ' + arguments
        more_codes.add_success_msg(context_msg)
        codes = codes.or_else(more_codes)

        codes.add_error_msg(_("unable to apply theorem"))

    return codes
示例#3
0
def action_assumption(proof_step,
                      selected_objects: [MathObject],
                      target_selected: bool = True) -> CodeForLean:
    """
    Translate into string of lean code corresponding to the action.
    """

    goal = proof_step.goal

    # (1) First trials
    target = goal.target
    improved_assumption = solve_target(target)
    codes = [improved_assumption]

    # (2) Use user selection
    if len(selected_objects) == 1:
        apply_user = CodeForLean.from_string(
            f'apply {selected_objects[0].info["name"]}')
        codes.append(apply_user.solve1())

    # (3) Conjunctions: try to split hypotheses once
    # TODO: recursive splitting in hypo
    # And then retry many things (in improved_assumption_2).
    split_conj = split_conjunctions_in_context(proof_step)

    improved_assumption_2 = solve_target(target)
    # Split target
    if target.is_and():
        # TODO: recursive splitting in target, and_then for each subgoal
        #  apply improved_assumption
        split_code = CodeForLean.from_string('split, assumption, assumption')
        improved_assumption_2 = improved_assumption_2.or_else(split_code)

    # Try norm_num
    if (goal.target.is_equality() or goal.target.is_inequality()
            or goal.target.is_false()):
        # Do not remove above test, since norm_num may solve some
        # not-so-trivial goal, e.g. implications
        norm_num_code = CodeForLean.from_string('norm_num at *').solve1()
        improved_assumption_2 = improved_assumption_2.or_else(norm_num_code)

    # Try specific properties
    more_assumptions = search_specific_prop(proof_step)
    if not more_assumptions.is_empty():
        improved_assumption_2 = improved_assumption_2.or_else(more_assumptions)
    more_code = split_conj.and_then(improved_assumption_2)
    codes.append(more_code)
    code = CodeForLean.or_else_from_list(codes)
    code = code.solve1()
    code.add_error_msg(_("I don't know how to conclude"))
    return code
示例#4
0
def destruct_iff_on_hyp(proof_step,
                        selected_objects: [MathObject]) -> CodeForLean:
    """
    Split a property 'P iff Q' into two implications.
    len(selected_objects) should be 1.
    """
    possible_codes = []
    hypo_name = selected_objects[0].info["name"]
    h1 = get_new_hyp(proof_step)
    h2 = get_new_hyp(proof_step)
    possible_codes.append(f'cases (iff_def.mp {hypo_name}) with {h1} {h2}')
    code = CodeForLean.or_else_from_list(possible_codes)
    code.add_success_msg(
        _("property {} split into {} and {}").format(hypo_name, h1, h2))
    return code
示例#5
0
def have_new_property(arrow: MathObject, variable_names: [str],
                      new_hypo_name: str) -> CodeForLean:
    """

    :param arrow:           a MathObject which is either an implication or a
                            universal property
    :param variable_names:  a list of names of variables (or properties) to
                            which "arrow" will be applied
    :param new_hypo_name:   a fresh name for the new property

    return:                 Lean Code to produce the wanted new property,
                            taking into account implicit parameters
    """

    selected_hypo = arrow.info["name"]

    command = f'have {new_hypo_name} := {selected_hypo}'
    command_explicit = f'have {new_hypo_name} := @{selected_hypo}'

    arguments = ' '.join(variable_names)

    # try with up to 4 implicit parameters
    implicit_codes = [
        command + ' ' + arguments, command + ' _ ' + arguments,
        command + ' _ _ ' + arguments, command + ' _ _ _ ' + arguments,
        command + ' _ _ _ _ ' + arguments
    ]

    explicit_codes = [
        command_explicit + ' ' + arguments,
        command_explicit + ' _ ' + arguments,
        command_explicit + ' _ _ ' + arguments,
        command_explicit + ' _ _ _ ' + arguments,
        command_explicit + ' _ _ _ _ ' + arguments
    ]

    possible_codes = implicit_codes + explicit_codes

    code = CodeForLean.or_else_from_list(possible_codes)
    code.add_success_msg(
        _("Property {} added to the context").format(new_hypo_name))
    return code