示例#1
0
def action_negate(proof_step,
                  selected_objects: [MathObject],
                  target_selected: bool = True) -> CodeForLean:
    """
    Translate into string of lean code corresponding to the action
    
    If no hypothesis has been previously selected:
        transform the target in an equivalent one with its negations 'pushed'.
    If a hypothesis has been previously selected:
        do the same to the hypothesis.
    """

    test_selection(selected_objects, target_selected)
    goal = proof_step.goal

    if len(selected_objects) == 0:
        if not goal.target.is_not():
            raise WrongUserInput(error=_("Target is not a negation 'NOT P'"))
        code = CodeForLean.from_string('push_neg')
        code.add_success_msg(_("Negation pushed on target"))
    elif len(selected_objects) == 1:
        if not selected_objects[0].is_not():
            error = _("Selected property is not a negation 'NOT P'")
            raise WrongUserInput(error)
        selected_hypo = selected_objects[0].info["name"]
        code = CodeForLean.from_string(f'push_neg at {selected_hypo}')
        code.add_success_msg(
            _(f"Negation pushed on property "
              f"{selected_hypo}"))
    else:
        raise WrongUserInput(error=_('Only one property at a time'))
    return code
示例#2
0
def action_or(proof_step,
              selected_objects: [MathObject],
              user_input=None,
              target_selected: bool = True) -> CodeForLean:
    """
    If the target is of the form P OR Q:
        transform the target in P (or Q) according to the user's choice.
    If a hypothesis of the form P OR Q has been previously selected:
        transform the current goal into two subgoals,
            one with P as a hypothesis,
            and another with Q as a hypothesis.
    """

    test_selection(selected_objects, target_selected)
    goal = proof_step.goal

    if len(selected_objects) == 0:
        if not goal.target.is_or():
            raise WrongUserInput(
                error=_("Target is not a disjunction 'P OR Q'"))
        else:
            return construct_or(proof_step, user_input)
    elif len(selected_objects) == 1:
        if selected_objects[0].is_or():
            return apply_or(proof_step, selected_objects, user_input)
        else:
            return construct_or_on_hyp(proof_step, selected_objects,
                                       user_input)
    elif len(selected_objects) == 2:
        return construct_or_on_hyp(proof_step, selected_objects, user_input)
    else:  # More than 2 selected objects
        raise WrongUserInput(error=_("Does not apply to more than two "
                                     "properties"))
示例#3
0
def action_and(proof_step,
               selected_objects: [MathObject],
               user_input: [str] = None,
               target_selected: bool = True) -> CodeForLean:
    """
    Translate into string of lean code corresponding to the action

If the target is of the form P AND Q:
    transform the current goal into two subgoals, P, then Q.
If a hypothesis of the form P AND Q has been previously selected:
    creates two new hypothesis P, and Q.
If two hypothesis P, then Q, have been previously selected:
    add the new hypothesis P AND Q to the properties.
    """

    test_selection(selected_objects, target_selected)
    goal = proof_step.goal

    if len(selected_objects) == 0:
        return construct_and(proof_step, user_input)
    if len(selected_objects) == 1:
        if not selected_objects[0].is_and():
            raise WrongUserInput(error=_("Selected property is not "
                                         "a conjunction 'P AND Q'"))
        else:
            return apply_and(proof_step, selected_objects)
    if len(selected_objects) == 2:
        if not (selected_objects[0].math_type.is_prop
                and selected_objects[1].math_type.is_prop):
            raise WrongUserInput(error=_("Selected items are not properties"))
        else:
            return construct_and_hyp(proof_step, selected_objects)
    raise WrongUserInput(error=_("Does not apply to more than two properties"))
示例#4
0
def action_forall(proof_step,
                  selected_objects: [MathObject],
                  user_input: [str] = [],
                  target_selected: bool = True) -> CodeForLean:
    """
    (1) If no selection and target is of the form ∀ x, P(x):
        introduce x and transform the target into P(x)
    (2) If a single universal property is selected, ask user for an object
        to which the property will be applied
    (3) If 2 or more items are selected, one of which is a universal
        property, try to apply it to the other selected items

    """

    test_selection(selected_objects, target_selected)
    goal = proof_step.goal

    if len(selected_objects) == 0:
        if not goal.target.is_for_all():
            error = _("target is not a universal property '∀x, P(x)'")
            raise WrongUserInput(error)
        else:
            return construct_forall(proof_step)

    elif len(selected_objects) == 1:  # Ask user for item
        if not selected_objects[0].is_for_all():
            error = _("selected property is not a universal property '∀x, "
                      "P(x)'")
            raise WrongUserInput(error)
        elif not user_input:
            raise MissingParametersError(InputType.Text,
                                         title=_("Apply a universal property"),
                                         output=_("Enter element on which you "
                                                  "want to apply:"))
        else:
            item = user_input[0]
            item = add_type_indication(item)  # e.g. (0:ℝ)
            if item[0] != '(':
                item = '(' + item + ')'
            potential_var = MathObject(node="LOCAL_CONSTANT",
                                       info={'name': item},
                                       children=[],
                                       math_type=None)
            selected_objects.insert(0, potential_var)
            # Now len(l) == 2
    # From now on len(l) ≥ 2
    # Search for a universal property among l, beginning with last item
    selected_objects.reverse()
    for item in selected_objects:
        if item.is_for_all():
            # Put item on last position
            selected_objects.remove(item)
            selected_objects.reverse()
            selected_objects.append(item)
            return apply_forall(proof_step, selected_objects)
    raise WrongUserInput(error=_("no universal property among selected"))
示例#5
0
def action_definition(proof_step,
                      selected_objects: [MathObject],
                      definition,
                      target_selected: bool = True
                      ):
    """
    Apply definition to rewrite selected object or target.
    """

    test_selection(selected_objects, target_selected)

    codes = rw_using_statement(proof_step.goal, selected_objects, definition)
    codes.add_error_msg(_("unable to apply definition"))
    return codes
示例#6
0
def action_exists(proof_step,
                  selected_objects: [MathObject],
                  user_input: [str] = None,
                  target_selected: bool = True) -> CodeForLean:
    """
    Three cases:
    (1) If target is of form ∃ x, P(x):
        - if no selection, ask the user to enter a witness x and transform
        the target into P(x).
        - if some selection, use it as a witness for existence.
    (2) If a hypothesis of form ∃ x, P(x) has been previously selected:
        introduce a new x and add P(x) to the properties.
    (3) If some 'x' and a property P(x) have been selected:
        get property '∃ x, P(x)'
    """

    test_selection(selected_objects, target_selected)
    goal = proof_step.goal

    if len(selected_objects) == 0:
        if not goal.target.is_exists():
            error = _("target is not existential property '∃x, P(x)'")
            raise WrongUserInput(error)
        else:
            return construct_exists(proof_step, user_input)
    elif len(selected_objects) == 1 and not user_input:
        selected_hypo = selected_objects[0]
        if selected_hypo.math_type.is_prop():
            # Try to apply property "exists x, P(x)" to get a new MathObject x
            if not selected_hypo.is_exists():
                error = _("selection is not existential property '∃x, P(x)'")
                raise WrongUserInput(error)
            else:
                return apply_exists(proof_step, selected_objects)
        else:  # h_selected is not a property : get an existence property
            if not goal.target.is_exists():
                error = _("target is not existential property '∃x, P(x)'")
                raise WrongUserInput(error)
            else:
                object_name = selected_objects[0].info["name"]
                return construct_exists(proof_step, [object_name])
    elif len(selected_objects) == 2:
        return construct_exists_on_hyp(proof_step, selected_objects)
    raise WrongUserInput(error=_("does not apply to more than two properties"))
示例#7
0
def action_iff(proof_step,
               selected_objects: [MathObject],
               user_input: [str] = [],
               target_selected: bool = True) -> CodeForLean:
    """
    Three cases:
    (1) No selected property:
        If the target is of the form P ⇔ Q:
            introduce two subgoals, P⇒Q, and Q⇒P.
        If target is of the form (P → Q) ∧ (Q → P):
            replace by P ↔ Q
    (2) 1 selected property, which is an iff P ⇔ Q:
        split it into two implications P⇒Q, and Q⇒P.
    (3) 2 properties:
        try to obtain P ⇔ Q.
    """

    test_selection(selected_objects, target_selected)
    goal = proof_step.goal

    if len(selected_objects) == 0:
        if goal.target.math_type.node != "PROP_IFF":
            code = destruct_iff(proof_step)
            if code:
                return code
            else:
                raise WrongUserInput(
                    error=_("target is not an iff property 'P ⇔ Q'"))
        else:
            return construct_iff(proof_step, user_input)
    if len(selected_objects) == 1:
        if selected_objects[0].math_type.node != "PROP_IFF":
            error = _("selected property is not an iff property 'P ⇔ Q'")
            raise WrongUserInput(error)
        else:
            return destruct_iff_on_hyp(proof_step, selected_objects)
    if len(selected_objects) == 2:
        if not (selected_objects[0].math_type.is_prop()
                and selected_objects[1].math_type.is_prop()):
            error = _("selected items should both be implications")
            raise WrongUserInput(error)
        else:
            return construct_iff_on_hyp(proof_step, selected_objects)
    raise WrongUserInput(error=_("does not apply to more than two properties"))
示例#8
0
def action_implicate(proof_step,
                     selected_objects: [MathObject],
                     target_selected: bool = True) -> CodeForLean:
    """
    Three cases:
    (1) No property selected:
        If the target is of the form P ⇒ Q: introduce the hypothesis P in
        the properties and transform the target into Q.
    (2) A single selected property, of the form P ⇒ Q: If the target was Q,
    it is replaced by P
    (3) Exactly two selected property, on of which is an implication P ⇒ Q
    and the other is P: Add Q to the context
    """

    test_selection(selected_objects, target_selected)
    goal = proof_step.goal

    if len(selected_objects) == 0:
        if not goal.target.is_implication():
            raise WrongUserInput(
                error=_("Target is not an implication 'P ⇒ Q'"))
        else:
            return construct_implicate(proof_step)
    if len(selected_objects) == 1:
        if not selected_objects[0].can_be_used_for_implication():
            raise WrongUserInput(
                error=_("Selected property is not an implication 'P ⇒ Q'"))
        else:
            return apply_implicate(proof_step, selected_objects)
    elif len(selected_objects) == 2:
        if not selected_objects[-1].can_be_used_for_implication():
            if not selected_objects[0].can_be_used_for_implication():
                raise WrongUserInput(error=_(
                    "Selected properties are not implications 'P ⇒ Q'"))
            else:  # l[0] is an implication but not l[1]: permute
                selected_objects.reverse()
        return apply_implicate_to_hyp(proof_step, selected_objects)
    # TODO: treat the case of more properties, including the possibility of
    #  P, Q and 'P and Q ⇒ R'
    raise WrongUserInput(error=_("Does not apply to more than two properties"))