Exemple #1
0
def print_goal(course):
    counter = 0
    to_prove = False
    for st in course.statements:
        print("-------------------------")
        if isinstance(st, Exercise):
            counter += 1
            print(_("Exercise") + f" n°{counter}: {st.pretty_name}")
            to_prove = True
        elif isinstance(st, Definition):
            print(_("Definition:") + f" {st.pretty_name}")
            to_prove = False
        elif isinstance(st, Theorem):
            print(_("Theorem:") + f" {st.pretty_name}")
            to_prove = False

        if 'open_question' in st.info:
            open_problem = True
        else:
            open_problem = False
        goal = st.initial_proof_state.goals[0]
        print(
            goal.goal_to_text(format_='utf8',
                              to_prove=to_prove,
                              text_depth=5,
                              open_problem=open_problem))
Exemple #2
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
Exemple #3
0
 def type(self):
     if self.is_definition():
         return _('definition')
     elif self.is_theorem():
         return _('theorem')
     elif self.is_exercise():
         return _('exercise')
Exemple #4
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"))
Exemple #5
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"))
    def __init__(self, mathobject: MathObject, tag: str = '='):
        """
        Init self with an instance of the class MathObject and a tag.
        See self.__doc__.

        :param mathobject: The MathObject one wants to display.
        :param tag: The tag of mathobject.
        """

        super().__init__()

        self.mathobject = mathobject
        self.tag = tag

        lean_name = mathobject.to_display()
        math_expr = mathobject.math_type.to_display(is_math_type=True)
        caption = f'{lean_name} : {math_expr}'
        self.setText(caption)
        self.setIcon(_TagIcon(tag))
        # set tool_tips (merge several tool_tips if needed)
        tool_tips = explain_how_to_apply(mathobject)
        # log.debug(f"Setting tooltips {tool_tips}")
        if len(tool_tips) == 1:
            tool_tip = _("Double click to") + " " + tool_tips[0]
            self.setToolTip(tool_tip)
        elif len(tool_tips) > 1:
            text = _("Double click to:")
            for tool_tip in tool_tips:
                text += "\n" + "• " + tool_tip
            self.setToolTip(text)
    def __init__(self, statements: [Statement], outline: Dict[str, str]):
        """
        Init self with a list of instances of the class Statement (or
        child of) and an outline (see self.__doc__). This method
        automatically calls self._init_tree, which itself instantiates
        all the nodes and items in self._init_tree_branch.

        :param statements: The ordered list of instances of the class
            (or child of) Statement one wants to display.
        :param outline: A Dict[str, str] in which keys are
            hierarchy levels (e.g.  'rings_and_ideals') and values are
            their pretty names (e.g. 'Rings and ideals'), see
            self.__doc__. 
        """

        # TODO: get rid of self._init_tree ?

        super().__init__()
        self._init_tree(statements, outline)

        # Cosmetics
        self.setWindowTitle('StatementsTreeWidget')
        if StatementsTreeWidget.show_lean_name_for_statements:
            self.setHeaderLabels([_('Statements'), _('L∃∀N name')])
            self.resizeColumnToContents(0)
            self.resizeColumnToContents(1)
        else:
            self.resizeColumnToContents(0)
            self.setHeaderLabels([_('Statements')])
Exemple #8
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"))
Exemple #9
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
Exemple #10
0
def method_absurdum(proof_step, selected_objects: [MathObject]) -> CodeForLean:
    """
    If no selection, engage in a proof by contradiction.
    """
    if len(selected_objects) == 0:
        new_hypo = get_new_hyp(proof_step)
        code = CodeForLean.from_string(f'by_contradiction {new_hypo}')
        code.add_success_msg(_("Negation of target added to the context"))
        return code
    else:
        error = _('Proof by contradiction only applies to target')
    raise WrongUserInput(error)
Exemple #11
0
def construct_implicate(proof_step) -> CodeForLean:
    """
    Here the target is assumed to be an implication P ⇒ Q, P is added to the
    context, and the target becomes Q.
    """
    if not proof_step.goal.target.is_implication():
        raise WrongUserInput(error=_("Target is not an implication 'P ⇒ Q'"))
    else:
        new_hypo_name = get_new_hyp(proof_step)
        code = CodeForLean.from_string(f'intro {new_hypo_name}')
        code.add_success_msg(
            _("Property {} added to the context").format(new_hypo_name))
        return code
Exemple #12
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
Exemple #13
0
def construct_exists(proof_step, user_input: [str]) -> CodeForLean:
    """
    Assuming the target is an existential property '∃ x, P(x)', prove it by
    providing a witness x and proving P(x).
    """

    if not user_input:
        raise MissingParametersError(
            InputType.Text,
            title=_("Exist"),
            output=_("Enter element you want to use:"))
    x = user_input[0]
    code = CodeForLean.from_string(f'use {x}, dsimp')
    code = code.or_else(f'use {x}')
    code.add_success_msg(_("now prove {} suits our needs").format(x))
    return code
Exemple #14
0
def action_compute(proof_step, selected_objects, target_selected: bool = True):
    """
    If the target is an equality, an inequality (or 'False'), then send
    tactics trying to prove the goal by (mainly linearly) computing.
    """

    goal = proof_step.goal

    target = goal.target
    if not (target.is_equality() or target.is_inequality()
            or target.is_false()):
        error = _("target is not an equality, an inequality, "
                  "nor a contradiction")
        raise WrongUserInput(error)
    # try_before = "try {apply div_pos}, " \
    #            + "try { all_goals {norm_num at *}}" \
    #             + ", "
    # simplify_1 = "simp only " \
    #             + "[*, ne.symm, ne.def, not_false_iff, lt_of_le_of_ne]"
    # possible_code = [try_before + "linarith",
    #                 try_before + simplify_1]
    # "finish" "norm_num *"
    # if user_config.getboolean('use_library_search_for_computations'):
    #     possible_code.append('library_search')
    code1 = CodeForLean.from_string("norm_num at *").solve1()
    code2 = CodeForLean.from_string("compute_n 10")
    code3 = CodeForLean.from_string("norm_num at *").try_().and_then(code2)
    possible_code = code1.or_else(code3)
    #possible_code = [solve1_wrap("norm_num at *"),
    #                 solve1_wrap("try {norm_num at *}, compute_n 10")]
    return possible_code
 async def __server_send_editor_lean(self):
     """
     Send the L∃∀N code written in the L∃∀N editor widget to the
     server interface.
     """
     await self.servint.code_set(_('Code from editor'),
                                 self.lean_editor.code_get())
Exemple #16
0
 def display(self):
     """
     Compute a txt version of the proof stored in journal.memory.
     :return:
     """
     display_txt = ""
     step_counter = 0
     time_deltas = [0]
     for counter in range(len(self.memory)):
         if counter < len(self.memory) - 1:
             t2 = self.memory[counter + 1].time
             t1 = self.memory[counter].time
             # Time diff in seconds
             delta = (t2.tm_min - t1.tm_min) * 60 + t2.tm_sec - t1.tm_sec
             time_deltas.append(delta)
     time_deltas.append(0)
     for step, time_delta in zip(self.memory, time_deltas):
         # Compute display of the proof step:
         step_txt = step.display()  # ProofStep.display()
         time_display = "#" * int(time_delta / 10)
         time_display2 = str(step.time.tm_min) + "'" + str(step.time.tm_sec)
         step_counter += 1
         more_txt = "------------------------------------\n"
         more_txt += time_display + "\n"
         more_txt += _("Step n°{} ").format(step_counter) \
             + "(" + time_display2 + ")" + "\n"
         more_txt += step_txt
         display_txt += more_txt
     return display_txt
Exemple #17
0
def test_selection(items_selected, selected_target):
    """
    Test that at least one of items_selected or selected_target is not empty.
    """
    if not (items_selected or selected_target):
        error = _("select at least one object, one property or the target")
        raise WrongUserInput(error)
Exemple #18
0
def display_belongs_to(math_type: Any, format_, text_depth, belonging=True) \
        -> str:
    """
    Compute the adequate shape for display of "x belongs to X", e.g.
    - generically, "x∈X"
    - specifically,
        - "f : X -> Y" (and not f ∈ X-> Y),
        or "f is a function from X to Y"
        - "P: a proposition" (and not P ∈ a proposition),

        :param math_type:   MathObject or "unknown"
        :param format_:     as usual
        :param text_depth:  int
        :param belonging:   fixme: unused
        :return:
    """

    # log.debug(f"display ∈ with {math_type}, {format_}, {text_depth}")
    # if 'unknown' == math_type:  # should not happen anymore
    #    if format_ in ('utf8', 'lean'):
    #        return "∈"
    # from now on math_type is an instance of MathObject
    if math_type is 'unknown':
        if text_depth > 0:
            symbol = _("is")
        else:
            symbol = "∈" if format_ == "utf8" else r"\in"
        return symbol
    if text_depth > 0:
        if math_type.is_prop(is_math_type=True) \
                or math_type.is_type(is_math_type=True) \
                or (math_type.is_function(is_math_type=True)
                    and text_depth > 1):
            symbol = _("is")
        elif math_type.is_function(is_math_type=True) and text_depth == 1:
            symbol = ":"
        else:
            symbol = _("belongs to")
    else:
        if math_type.is_function(is_math_type=True) \
                or math_type.is_prop(is_math_type=True) \
                or math_type.is_type(is_math_type=True):
            symbol = ":"
        else:
            symbol = "∈" if format_ == "utf8" else r"\in"
    return symbol
Exemple #19
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"))
    def __init__(
            self,
            log_format: str = '%(asctime)s - %(levelname)s - %(message)s'):
        """
        Init self with a logger formater (so specify the layout of the
        log entries, see logging module documentation), e.g.
        '%(asctime)s - %(levelname)s - %(message)s'.

        :param log_format: Logger formatter for the log entries.
        """

        super().__init__()
        self.setModal(True)

        self.setWindowTitle(f"{_('Installing missing dependencies')}" \
                             " — d∃∀duction")
        self.__text_edit_logger = TextEditLogger()
        self.__confirm_quit = True

        # Buttons
        self.__quit_btn = QPushButton(_('Quit'))
        self.__start_dead_btn = QPushButton(_('Start d∃∀duction'))
        self.__quit_btn.setAutoDefault(False)
        self.__start_dead_btn.setEnabled(False)
        self.__quit_btn.clicked.connect(self.__quit)
        self.__start_dead_btn.clicked.connect(self.plz_start_deaduction)

        # Layouts
        self.__main_layout = QVBoxLayout()
        btns_layout = QHBoxLayout()
        btns_layout.addStretch()
        btns_layout.addWidget(self.__quit_btn)
        btns_layout.addWidget(self.__start_dead_btn)
        self.__main_layout.addWidget(self.__text_edit_logger)
        self.__main_layout.addLayout(btns_layout)
        self.setLayout(self.__main_layout)

        # Logging facilities, avoid some segfault and thread-related nastyness
        self.__text_edit_logger_handler = TextEditLoggerHandler(
            self.__text_edit_logger, log_format)
        self.__log_queue = Queue(-1)
        self.__queue_handler = QueueHandler(self.__log_queue)
        self.__queue_listener = QueueListener(self.__log_queue,
                                              self.__text_edit_logger_handler)
Exemple #21
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"))
    def fireworks(self):
        """
        As of now,
        - display a dialog when the target is successfully solved,
        - replace the target by a message "No more goal"
        Note that the dialog is displayed only the first time the signal is
        triggered, thanks to the flag self.cqdf.
        """
        # TODO: make it a separate class

        # Display msg_box unless redoing or test mode
        # (Previously was: Display unless exercise already solved)
        # if not self.exercise_solved:
        if not self.proof_step.is_redo() and not self.test_mode:
            title = _('Target solved')
            text = _('The proof is complete!')
            msg_box = QMessageBox(parent=self)
            msg_box.setText(text)
            msg_box.setWindowTitle(title)
            button_ok = msg_box.addButton(_('Back to exercise'),
                                          QMessageBox.YesRole)
            button_change = msg_box.addButton(_('Change exercise'),
                                              QMessageBox.YesRole)
            button_change.clicked.connect(self.change_exercise)
            msg_box.exec()

        self.proof_step.no_more_goal = True
        self.proof_step.new_goals = []
        # Artificially create a final proof_state by replacing target by a msg
        # (We do not get the final proof_state from Lean).
        proof_state = deepcopy(self.proof_step.proof_state)
        target = proof_state.goals[0].target
        target.math_type = MathObject(
            node="NO_MORE_GOAL",
            info={},
            children=[],
        )
        # Update proof_step and UI
        self.update_proof_state(proof_state)

        if not self.exercise_solved:
            self.exercise_solved = True
            if not self.test_mode:  # Save exercise for auto-test
                self.lean_file.save_exercise_for_autotest(self)
Exemple #23
0
def method_contrapose(proof_step,
                      selected_objects: [MathObject]) -> CodeForLean:
    """
    If target is an implication, turn it to its contrapose.
    """

    goal = proof_step.goal

    if len(selected_objects) == 0:
        if goal.target.math_type.node == "PROP_IMPLIES":
            code = CodeForLean.from_string("contrapose")
            code.add_success_msg(_("Target replaced by contrapositive"))
            return code
        else:
            error = _('Proof by contraposition only applies when target is '
                      'an implication')
    else:
        error = _('Proof by contraposition only applies to target')
    raise WrongUserInput(error)
    def __init__(self, missing_dependencies: [str]):
        """
        Init self with the list of missing dependencies (to be
        displayed).

        :param missing_dependencies: List of missing dependencies to be
                                     displayed.
        """
        # @Florian: If you want I can do some more formatting for the
        # list of dependencied

        super().__init__()

        self.setText(_('Missing dependencies'))
        self.setInformativeText(_('Some dependencies are missing. Do you want'\
                                  ' to install them?'))
        self.setDetailedText('— ' + '\n— '.join(missing_dependencies))
        self.setIcon(QMessageBox.Warning)
        self.setDefaultButton(QMessageBox.Yes)
Exemple #25
0
def apply_implicate(proof_step, selected_object: [MathObject]) -> CodeForLean:
    """
    Here selected_object contains a single property which is an implication
    P ⇒ Q; if the target is Q then it will be replaced by P.
    """
    selected_hypo = selected_object[0].info["name"]
    code = CodeForLean.from_string(f'apply {selected_hypo}')
    code.add_success_msg(
        _("Target modified using implication {}").format(selected_hypo))
    return code
Exemple #26
0
def print_text_version(course):
    counter = 0
    for st in course.statements:
        print("-------------------------")
        if isinstance(st, Exercise):
            counter += 1
            print(_("Exercise") + f" n°{counter}: {st.pretty_name}")
            goal = st.initial_proof_state.goals[0]
            if 'open_question' in st.info:
                open_problem = True
            else:
                open_problem = False
            print(goal.goal_to_text(text_depth=1, open_problem=open_problem))
            # print("     More verbose:")
            # print(goal.goal_to_text(text_depth=2))
        else:
            print(_("Definition:") + f" {st.pretty_name}")
            goal = st.initial_proof_state.goals[0]
            print(goal.goal_to_text(to_prove=False, text_depth=1))
Exemple #27
0
def apply_function(proof_step, selected_objects: [MathObject]):
    """
    Apply l[-1], which is assumed to be a function f, to previous elements of
    l, which can be:
    - an equality
    - an object x (then create the new object f(x) )

    l should have length at least 2
    """

    log.debug('Applying function')
    codes = CodeForLean.empty_code()

    # let us check the input is indeed a function
    function = selected_objects[-1]
    # if function.math_type.node != "FUNCTION":
    #    raise WrongUserInput
    
    f = function.info["name"]
    Y = selected_objects[-1].math_type.children[1]
    
    while len(selected_objects) != 1:
        new_h = get_new_hyp(proof_step)
        
        # if function applied to a property, presumed to be an equality
        if selected_objects[0].math_type.is_prop():
            h = selected_objects[0].info["name"]
            codes = codes.or_else(f'have {new_h} := congr_arg {f} {h}')
            codes.add_success_msg(_("function {} applied to {}").format(f, h))
        # if function applied to element x:
        # create new element y and new equality y=f(x)
        else:
            x = selected_objects[0].info["name"]
            y = give_global_name(proof_step =proof_step,
                                 math_type=Y,
                                 hints=[Y.info["name"].lower()])
            msg = _("new objet {} added to the context").format(y)
            codes = codes.or_else(f'set {y} := {f} {x} with {new_h}',
                                  success_msg=msg)
        selected_objects = selected_objects[1:]

    return codes
Exemple #28
0
    def __init__(self, errors, lean_code):
        super().__init__(f"Failed request to server with errors : \n"
                         f"{pformat(errors, indent=4)}")
        if lean_code and lean_code.error_msg:
            self.message = lean_code.error_msg
        else:
            self.message = _('Error')

        details = ""
        for error in errors:
            details += "\n" + error.text
        self.info = {'details': details}
Exemple #29
0
 def print_goal(self, open_problem=False, to_prove=True) -> str:
     """
     Return context and target in a raw form.
     """
     context = self.context
     target = self.target
     text = ""
     if open_problem:
         text += _("True or False?") + "\n"
     if len(context) == 1:
         text += _("Hypothesis:") + "\n"
     elif len(context) > 1:
         text += _("Hypotheses:") + "\n"
     for math_object in context:
         math_type = math_object.math_type
         name = math_object.to_display()
         name_type = math_type.to_display(is_math_type=True)
         text_object = name + _(": ") + name_type
         text += "  " + text_object + "\n"
     if to_prove and not open_problem:
         text += _("Prove that") + "\n"
     elif context:
         text += _("Then") + "\n"
     text += target.math_type.to_display(is_math_type=True)
     return text
Exemple #30
0
def action_use_proof_methods(proof_step,
                             selected_objects: [MathObject],
                             user_input: [str] = [],
                             target_selected: bool = True) -> CodeForLean:

    # 1st call, choose proof method
    if not user_input:
        choices = [('1', _("Case-based reasoning")),
                   ('2', _("Proof by contraposition")),
                   ('3', _("Proof by contradiction"))]
        if allow_proof_by_sorry:
            choices.append(('4', _("Admit current sub-goal!")))
        raise MissingParametersError(InputType.Choice,
                                     choices,
                                     title=_("Choose proof method"),
                                     output=_("Which proof method?")
                                     )
    # 2nd call, call the adequate proof method. len(user_input) = 1.
    else:
        method = user_input[0] + 1
        if method == 1:
            return method_cbr(proof_step, selected_objects, user_input)
        if method == 2:
            return method_contrapose(proof_step, selected_objects)
        if method == 3:
            return method_absurdum(proof_step, selected_objects)
        if method == 4:
            return method_sorry(proof_step, selected_objects)
    raise WrongUserInput