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))
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
def type(self): if self.is_definition(): return _('definition') elif self.is_theorem(): return _('theorem') elif self.is_exercise(): return _('exercise')
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"))
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')])
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"))
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
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)
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
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
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
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())
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
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)
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
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)
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)
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)
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
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))
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
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}
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
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