unicode-logic-kit 0.31.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- unicode_logic_kit/__init__.py +385 -0
- unicode_logic_kit/__main__.py +520 -0
- unicode_logic_kit/_deadline.py +219 -0
- unicode_logic_kit/ace/__init__.py +126 -0
- unicode_logic_kit/ace/_align.py +135 -0
- unicode_logic_kit/ace/chem_lexicon.py +128 -0
- unicode_logic_kit/ace/drs_reader.py +570 -0
- unicode_logic_kit/ace/mapping.py +666 -0
- unicode_logic_kit/ace/reverse_modal.py +138 -0
- unicode_logic_kit/ace/runner.py +551 -0
- unicode_logic_kit/ace/translate.py +452 -0
- unicode_logic_kit/ace/verbalize.py +1070 -0
- unicode_logic_kit/api.py +1284 -0
- unicode_logic_kit/atp/__init__.py +177 -0
- unicode_logic_kit/atp/_ascii_names.py +113 -0
- unicode_logic_kit/atp/_html.py +72 -0
- unicode_logic_kit/atp/_substructural_input.py +228 -0
- unicode_logic_kit/atp/_tff_problem.py +715 -0
- unicode_logic_kit/atp/_tptp_problem.py +1111 -0
- unicode_logic_kit/atp/_writer_support.py +289 -0
- unicode_logic_kit/atp/clingo_backend.py +1180 -0
- unicode_logic_kit/atp/cvc5_backend.py +1385 -0
- unicode_logic_kit/atp/eprover_backend.py +732 -0
- unicode_logic_kit/atp/finite_domain.py +1055 -0
- unicode_logic_kit/atp/fitch.py +1547 -0
- unicode_logic_kit/atp/fitch_search.py +551 -0
- unicode_logic_kit/atp/hets_backend.py +339 -0
- unicode_logic_kit/atp/hybrid_down.py +120 -0
- unicode_logic_kit/atp/incremental.py +250 -0
- unicode_logic_kit/atp/kripke_enum.py +741 -0
- unicode_logic_kit/atp/lambek.py +436 -0
- unicode_logic_kit/atp/leo3_backend.py +332 -0
- unicode_logic_kit/atp/linear.py +738 -0
- unicode_logic_kit/atp/lj.py +705 -0
- unicode_logic_kit/atp/logic_backends.py +566 -0
- unicode_logic_kit/atp/ltl_tableau.py +1084 -0
- unicode_logic_kit/atp/minizinc_backend.py +1402 -0
- unicode_logic_kit/atp/modal_tableau.py +1382 -0
- unicode_logic_kit/atp/nanocop_backend.py +410 -0
- unicode_logic_kit/atp/portfolio.py +489 -0
- unicode_logic_kit/atp/protocol.py +1803 -0
- unicode_logic_kit/atp/prover9_entailment.py +1153 -0
- unicode_logic_kit/atp/resolution.py +1376 -0
- unicode_logic_kit/atp/resolution_check.py +1114 -0
- unicode_logic_kit/atp/sequent.py +1050 -0
- unicode_logic_kit/atp/tableau.py +921 -0
- unicode_logic_kit/atp/tableau_check.py +543 -0
- unicode_logic_kit/atp/tptp_ncl.py +811 -0
- unicode_logic_kit/atp/tptp_tff.py +1546 -0
- unicode_logic_kit/atp/tstp.py +1333 -0
- unicode_logic_kit/atp/tstp_check.py +1096 -0
- unicode_logic_kit/atp/twee_backend.py +236 -0
- unicode_logic_kit/atp/twee_check.py +711 -0
- unicode_logic_kit/atp/twee_entailment.py +953 -0
- unicode_logic_kit/atp/vampire_entailment.py +540 -0
- unicode_logic_kit/atp/z3_arith.py +470 -0
- unicode_logic_kit/atp/z3_equivalence.py +36 -0
- unicode_logic_kit/atp/z3_fuzzy.py +362 -0
- unicode_logic_kit/atp/z3_input.py +500 -0
- unicode_logic_kit/atp/z3_models.py +208 -0
- unicode_logic_kit/chem/__init__.py +88 -0
- unicode_logic_kit/chem/_naming.py +284 -0
- unicode_logic_kit/chem/cache.py +185 -0
- unicode_logic_kit/chem/interop.py +244 -0
- unicode_logic_kit/chem/mol.py +525 -0
- unicode_logic_kit/chem/signature.py +112 -0
- unicode_logic_kit/comorphism.py +497 -0
- unicode_logic_kit/dl/__init__.py +384 -0
- unicode_logic_kit/dl/classification.py +227 -0
- unicode_logic_kit/dl/concepts.py +632 -0
- unicode_logic_kit/dl/datatypes.py +818 -0
- unicode_logic_kit/dl/owl_functional.py +2433 -0
- unicode_logic_kit/dl/owl_manchester.py +1637 -0
- unicode_logic_kit/dl/owl_reasoner.py +790 -0
- unicode_logic_kit/dl/parser.py +391 -0
- unicode_logic_kit/dl/tableau.py +4048 -0
- unicode_logic_kit/dl/translate.py +2704 -0
- unicode_logic_kit/drt/__init__.py +94 -0
- unicode_logic_kit/drt/export.py +179 -0
- unicode_logic_kit/drt/nodes.py +506 -0
- unicode_logic_kit/drt/parser.py +965 -0
- unicode_logic_kit/drt/resolve.py +195 -0
- unicode_logic_kit/drt/reverse.py +175 -0
- unicode_logic_kit/eval/__init__.py +106 -0
- unicode_logic_kit/eval/batch.py +382 -0
- unicode_logic_kit/eval/canonical.py +663 -0
- unicode_logic_kit/eval/chem_batch.py +606 -0
- unicode_logic_kit/eval/converses.py +200 -0
- unicode_logic_kit/eval/datasets/__init__.py +136 -0
- unicode_logic_kit/eval/datasets/_base.py +263 -0
- unicode_logic_kit/eval/datasets/_proofwriter_proof.py +422 -0
- unicode_logic_kit/eval/datasets/c3po.py +678 -0
- unicode_logic_kit/eval/datasets/folio.py +158 -0
- unicode_logic_kit/eval/datasets/fracas.py +418 -0
- unicode_logic_kit/eval/datasets/groves.py +191 -0
- unicode_logic_kit/eval/datasets/logicbench.py +467 -0
- unicode_logic_kit/eval/datasets/logicnli.py +303 -0
- unicode_logic_kit/eval/datasets/malls.py +133 -0
- unicode_logic_kit/eval/datasets/pfolio.py +594 -0
- unicode_logic_kit/eval/datasets/pmb.py +242 -0
- unicode_logic_kit/eval/datasets/prontoqa.py +611 -0
- unicode_logic_kit/eval/datasets/proofwriter.py +1431 -0
- unicode_logic_kit/eval/datasets/proverqa.py +674 -0
- unicode_logic_kit/eval/datasets/willow.py +478 -0
- unicode_logic_kit/eval/equivalence.py +466 -0
- unicode_logic_kit/eval/exercise_gen.py +533 -0
- unicode_logic_kit/eval/explain.py +791 -0
- unicode_logic_kit/eval/generality.py +750 -0
- unicode_logic_kit/eval/metric_hf.py +458 -0
- unicode_logic_kit/eval/predicate_match.py +343 -0
- unicode_logic_kit/eval/theory_check.py +1170 -0
- unicode_logic_kit/eval/validate.py +306 -0
- unicode_logic_kit/fol/__init__.py +177 -0
- unicode_logic_kit/fol/_atom_keys.py +510 -0
- unicode_logic_kit/fol/_fol_nodes.py +3586 -0
- unicode_logic_kit/fol/_free_parameters.py +105 -0
- unicode_logic_kit/fol/_ho_nodes.py +448 -0
- unicode_logic_kit/fol/_hybrid_nodes.py +308 -0
- unicode_logic_kit/fol/_identifiers.py +1091 -0
- unicode_logic_kit/fol/_lambek_nodes.py +112 -0
- unicode_logic_kit/fol/_linear_nodes.py +352 -0
- unicode_logic_kit/fol/_modal_nodes.py +1467 -0
- unicode_logic_kit/fol/_msfl_nodes.py +2196 -0
- unicode_logic_kit/fol/_numeral_symbols.py +231 -0
- unicode_logic_kit/fol/_so_nodes.py +200 -0
- unicode_logic_kit/fol/_symbol_names.py +81 -0
- unicode_logic_kit/fol/_team_nodes.py +181 -0
- unicode_logic_kit/fol/_tptp_symbols.py +551 -0
- unicode_logic_kit/fol/_truth_constants.py +117 -0
- unicode_logic_kit/fol/casl_export.py +1135 -0
- unicode_logic_kit/fol/casl_import.py +929 -0
- unicode_logic_kit/fol/derivation.py +367 -0
- unicode_logic_kit/fol/dialect_detect.py +70 -0
- unicode_logic_kit/fol/dialect_repair.py +537 -0
- unicode_logic_kit/fol/frames.py +637 -0
- unicode_logic_kit/fol/grammars/terminals.lark +31 -0
- unicode_logic_kit/fol/lambda_tools.py +297 -0
- unicode_logic_kit/fol/latex_input.py +429 -0
- unicode_logic_kit/fol/modal_translation.py +944 -0
- unicode_logic_kit/fol/msflparser.py +1033 -0
- unicode_logic_kit/fol/naming.py +422 -0
- unicode_logic_kit/fol/nodes.py +241 -0
- unicode_logic_kit/fol/normalforms.py +492 -0
- unicode_logic_kit/fol/pal.py +287 -0
- unicode_logic_kit/fol/prolog_export.py +566 -0
- unicode_logic_kit/fol/prolog_input.py +505 -0
- unicode_logic_kit/fol/prover9_input.py +1325 -0
- unicode_logic_kit/fol/qml.py +1760 -0
- unicode_logic_kit/fol/qmltp_input.py +525 -0
- unicode_logic_kit/fol/sanitize.py +221 -0
- unicode_logic_kit/fol/serialize.py +79 -0
- unicode_logic_kit/fol/signature.py +1290 -0
- unicode_logic_kit/fol/simplify_check.py +544 -0
- unicode_logic_kit/fol/spans.py +594 -0
- unicode_logic_kit/fol/tptp_input.py +1503 -0
- unicode_logic_kit/fol/tptp_repair.py +941 -0
- unicode_logic_kit/fol/unification.py +157 -0
- unicode_logic_kit/fol/verbalize.py +263 -0
- unicode_logic_kit/hets/__init__.py +163 -0
- unicode_logic_kit/hets/bridge.py +142 -0
- unicode_logic_kit/hets/client.py +748 -0
- unicode_logic_kit/hets/docker.py +420 -0
- unicode_logic_kit/hets/dol.py +712 -0
- unicode_logic_kit/hets/haskell_json.py +355 -0
- unicode_logic_kit/hets/owl_backend.py +794 -0
- unicode_logic_kit/hets/owl_cli.py +598 -0
- unicode_logic_kit/hets/symbols.py +512 -0
- unicode_logic_kit/hol/__init__.py +140 -0
- unicode_logic_kit/hol/_ho_common.py +323 -0
- unicode_logic_kit/hol/_isabelle_binders.py +125 -0
- unicode_logic_kit/hol/classical.py +812 -0
- unicode_logic_kit/hol/deepshallow/__init__.py +45 -0
- unicode_logic_kit/hol/deepshallow/_common.py +177 -0
- unicode_logic_kit/hol/deepshallow/conditional.py +225 -0
- unicode_logic_kit/hol/deepshallow/intuitionistic.py +181 -0
- unicode_logic_kit/hol/deepshallow/modal.py +217 -0
- unicode_logic_kit/hol/deepshallow/qml.py +406 -0
- unicode_logic_kit/hol/deepshallow/relevant.py +206 -0
- unicode_logic_kit/hol/free.py +753 -0
- unicode_logic_kit/hol/goedel.py +336 -0
- unicode_logic_kit/hol/ho_modal.py +1743 -0
- unicode_logic_kit/hol/intuitionistic.py +403 -0
- unicode_logic_kit/hol/isabelle_conditional.py +593 -0
- unicode_logic_kit/hol/isabelle_modal.py +1908 -0
- unicode_logic_kit/hol/isabelle_relevant.py +412 -0
- unicode_logic_kit/hol/isabelle_runner.py +1147 -0
- unicode_logic_kit/hol/isabelle_substructural.py +884 -0
- unicode_logic_kit/hol/lean.py +1018 -0
- unicode_logic_kit/hol/manyvalued.py +921 -0
- unicode_logic_kit/hol/secondorder.py +687 -0
- unicode_logic_kit/hol/thf_modal.py +941 -0
- unicode_logic_kit/hol/thirdorder.py +397 -0
- unicode_logic_kit/ilp/__init__.py +89 -0
- unicode_logic_kit/ilp/readback.py +389 -0
- unicode_logic_kit/ilp/separation.py +153 -0
- unicode_logic_kit/ilp/task.py +730 -0
- unicode_logic_kit/logic.py +163 -0
- unicode_logic_kit/mcp/__init__.py +28 -0
- unicode_logic_kit/mcp/__main__.py +5 -0
- unicode_logic_kit/mcp/chem_tools.py +1031 -0
- unicode_logic_kit/mcp/server.py +2453 -0
- unicode_logic_kit/mcp/syntax_spec.py +681 -0
- unicode_logic_kit/prob/__init__.py +53 -0
- unicode_logic_kit/prob/_bdd.py +225 -0
- unicode_logic_kit/prob/_column_gen.py +668 -0
- unicode_logic_kit/prob/distribution.py +686 -0
- unicode_logic_kit/prob/nilsson.py +470 -0
- unicode_logic_kit/py.typed +0 -0
- unicode_logic_kit/semantics/__init__.py +137 -0
- unicode_logic_kit/semantics/_modal_reject.py +156 -0
- unicode_logic_kit/semantics/action_models.py +466 -0
- unicode_logic_kit/semantics/asp_models.py +1200 -0
- unicode_logic_kit/semantics/conditional.py +580 -0
- unicode_logic_kit/semantics/dynamic_epistemic.py +95 -0
- unicode_logic_kit/semantics/free_logic.py +913 -0
- unicode_logic_kit/semantics/fuzzy.py +384 -0
- unicode_logic_kit/semantics/fuzzy_kripke.py +442 -0
- unicode_logic_kit/semantics/intuitionistic.py +581 -0
- unicode_logic_kit/semantics/kripke.py +1139 -0
- unicode_logic_kit/semantics/manyvalued.py +580 -0
- unicode_logic_kit/semantics/matrix.py +342 -0
- unicode_logic_kit/semantics/model_eval.py +1135 -0
- unicode_logic_kit/semantics/modelfinder.py +1036 -0
- unicode_logic_kit/semantics/nonmonotonic.py +372 -0
- unicode_logic_kit/semantics/relevant.py +331 -0
- unicode_logic_kit/semantics/secondorder.py +657 -0
- unicode_logic_kit/semantics/structures.py +352 -0
- unicode_logic_kit/semantics/tarski.py +975 -0
- unicode_logic_kit/semantics/team.py +315 -0
- unicode_logic_kit/semantics/team_translation.py +416 -0
- unicode_logic_kit/semantics/thirdorder.py +358 -0
- unicode_logic_kit/semantics/tnorm.py +85 -0
- unicode_logic_kit/semantics/truthtable.py +201 -0
- unicode_logic_kit-0.31.0.dist-info/METADATA +333 -0
- unicode_logic_kit-0.31.0.dist-info/RECORD +237 -0
- unicode_logic_kit-0.31.0.dist-info/WHEEL +4 -0
- unicode_logic_kit-0.31.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"""Modal/deontic formula → DRS shell (``fol_to_modal_drs``) — the two ACE-7
|
|
2
|
+
surface shapes, measured against live APE, on top of the untouched classical
|
|
3
|
+
route.
|
|
4
|
+
|
|
5
|
+
:func:`unicode_logic_kit.drt.reverse.fol_to_drs` recognizes exactly the
|
|
6
|
+
classical standard-translation image and refuses ``Box``/``Diamond``/
|
|
7
|
+
``Obligatory``/``Permitted`` by name wherever they occur — read-only here,
|
|
8
|
+
reused verbatim for every classical subformula (see its module docstring).
|
|
9
|
+
This module adds exactly the two shapes ACE's modal surface can carry
|
|
10
|
+
(Attempto's own reading: the modal auxiliary sits INSIDE the verb phrase,
|
|
11
|
+
"John must wait.", not a sentence-level paraphrase — see
|
|
12
|
+
:mod:`unicode_logic_kit.ace.verbalize`'s module docstring), each probed live
|
|
13
|
+
before being written (``tests/test_ace_modal_verbalize.py``):
|
|
14
|
+
|
|
15
|
+
- **FLAT**: a modality wrapping a whole formula, ``Modality(∃-chain
|
|
16
|
+
classical)`` — "John must wait." — becomes :class:`ModalBox`.
|
|
17
|
+
- **NESTED IN A DUPLEX CONSEQUENT**: ``∀-chain(antecedent → Modality(∃-chain
|
|
18
|
+
classical))`` — the probed "modal-universal" fixture, rendered as "If
|
|
19
|
+
there is a man X1 then X1 must wait." — becomes :class:`ModalImpl`.
|
|
20
|
+
|
|
21
|
+
Neither wrapper joins :class:`unicode_logic_kit.drt.nodes.Condition`: the
|
|
22
|
+
classical DRS core stays modality-free by design (``drt/reverse.py``'s own
|
|
23
|
+
module docstring), so these are small standalone dataclasses that sit ABOVE
|
|
24
|
+
``drt.nodes.DRS``/``Impl``, used only inside this package.
|
|
25
|
+
|
|
26
|
+
Any other placement — modality mixed with classical conjuncts in one box,
|
|
27
|
+
modality inside a negation/disjunction/antecedent, modality nested inside
|
|
28
|
+
another modality, a duplex two ∀-levels deep whose INNER consequent is
|
|
29
|
+
modal — is refused by the SAME message ``fol_to_drs`` already gives a bare
|
|
30
|
+
modal node reached in a position it does not expect ("... has no classical
|
|
31
|
+
DRS condition ..."): every shape outside the two above falls straight
|
|
32
|
+
through to :func:`~unicode_logic_kit.drt.reverse.fol_to_drs` on the ORIGINAL
|
|
33
|
+
formula, unchanged, so the refusal is exactly as loud and as precisely
|
|
34
|
+
located as the classical route's own.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
from __future__ import annotations
|
|
38
|
+
|
|
39
|
+
from dataclasses import dataclass
|
|
40
|
+
from typing import Optional, Union
|
|
41
|
+
|
|
42
|
+
from ..drt.nodes import DRS
|
|
43
|
+
from ..drt.reverse import fol_to_drs
|
|
44
|
+
from ..fol.nodes import (
|
|
45
|
+
Box, Diamond, Implies, Node, Obligatory, Permitted, Quantifier,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
__all__ = ["ModalBox", "ModalImpl", "fol_to_modal_drs"]
|
|
49
|
+
|
|
50
|
+
#: Inverts ace.translate._MODAL_NODES: the kit modal node type -> ACE's
|
|
51
|
+
#: auxiliary word. Kept local (not imported from .translate) because that
|
|
52
|
+
#: module imports drs_reader/mapping machinery this one has no other need
|
|
53
|
+
#: of; the table itself is tiny and the inverse relationship is asserted by
|
|
54
|
+
#: the tests, not merely assumed.
|
|
55
|
+
_MODAL_TYPES = (Box, Diamond, Obligatory, Permitted)
|
|
56
|
+
_MODALITY_OF = {Box: "must", Diamond: "can", Obligatory: "should",
|
|
57
|
+
Permitted: "may"}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@dataclass(frozen=True)
|
|
61
|
+
class ModalBox:
|
|
62
|
+
"""A modality wrapping a whole classical box: ``Modality[drs]`` —
|
|
63
|
+
"John must wait." ``modality`` is one of "must"/"can"/"should"/"may";
|
|
64
|
+
``drs`` is exactly what :func:`~unicode_logic_kit.drt.reverse.fol_to_drs`
|
|
65
|
+
would build for the modal node's own inner formula."""
|
|
66
|
+
|
|
67
|
+
modality: str
|
|
68
|
+
drs: DRS
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@dataclass(frozen=True)
|
|
72
|
+
class ModalImpl:
|
|
73
|
+
"""A duplex condition whose CONSEQUENT carries a modality:
|
|
74
|
+
``[antecedent] => Modality[consequent]`` — "Every man must wait.",
|
|
75
|
+
verbalized as "If there is a man X1 then X1 must wait." Mirrors
|
|
76
|
+
:class:`unicode_logic_kit.drt.nodes.Impl` (donkey-sentence accessibility:
|
|
77
|
+
``antecedent``'s referents are visible in ``consequent``), except the
|
|
78
|
+
consequent sits under a modality instead of being a plain box."""
|
|
79
|
+
|
|
80
|
+
antecedent: DRS
|
|
81
|
+
modality: str
|
|
82
|
+
consequent: DRS
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def fol_to_modal_drs(formula: Node) -> Union[DRS, ModalBox, ModalImpl]:
|
|
86
|
+
"""Rebuild the DRS (or modal DRS shell) ``formula`` is the standard
|
|
87
|
+
translation of, recognizing the two probed modal shapes on top of the
|
|
88
|
+
classical image (see the module docstring for the exact boundary).
|
|
89
|
+
|
|
90
|
+
Raises:
|
|
91
|
+
unicode_logic_kit.drt.reverse.FolToDrsError: ``formula`` is outside
|
|
92
|
+
the classical image AND outside the two probed modal shapes —
|
|
93
|
+
the same exception :func:`~unicode_logic_kit.drt.reverse.fol_to_drs`
|
|
94
|
+
raises, since every unsupported placement is delegated to it
|
|
95
|
+
unchanged.
|
|
96
|
+
"""
|
|
97
|
+
if isinstance(formula, _MODAL_TYPES):
|
|
98
|
+
return ModalBox(_MODALITY_OF[type(formula)],
|
|
99
|
+
fol_to_drs(formula.formula))
|
|
100
|
+
if isinstance(formula, Quantifier) and formula.type == "∀":
|
|
101
|
+
grafted = _duplex_with_modal_consequent(formula)
|
|
102
|
+
if grafted is not None:
|
|
103
|
+
return grafted
|
|
104
|
+
return fol_to_drs(formula)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def _duplex_with_modal_consequent(formula: Node) -> Optional[ModalImpl]:
|
|
108
|
+
"""``None`` when ``formula``'s ∀-chain does not end in ``Implies`` with a
|
|
109
|
+
modal right-hand side (the caller then falls back to plain
|
|
110
|
+
``fol_to_drs``, which gives the exact classical refusal). Otherwise the
|
|
111
|
+
graft: substitute the modal node's OWN inner formula for the modal node
|
|
112
|
+
in the ∀-chain, hand the now-fully-classical formula to ``fol_to_drs``
|
|
113
|
+
(which rebuilds antecedent AND consequent correctly, donkey accessibility
|
|
114
|
+
included), then re-attach the modality to the resulting consequent —
|
|
115
|
+
reusing ``fol_to_drs`` for every classical piece rather than
|
|
116
|
+
re-deriving ``_duplex_condition``'s logic here."""
|
|
117
|
+
inner = formula
|
|
118
|
+
while isinstance(inner, Quantifier) and inner.type == "∀":
|
|
119
|
+
inner = inner.formula
|
|
120
|
+
if not (isinstance(inner, Implies) and isinstance(inner.right, _MODAL_TYPES)):
|
|
121
|
+
return None
|
|
122
|
+
modality = _MODALITY_OF[type(inner.right)]
|
|
123
|
+
classical = fol_to_drs(_replace_consequent(formula, inner.right.formula))
|
|
124
|
+
# fol_to_drs(∀-chain(... -> ...)) always rebuilds to a DRS with no
|
|
125
|
+
# referents of its own and exactly one Impl condition (mirrors
|
|
126
|
+
# drt.reverse._duplex_condition's return shape).
|
|
127
|
+
impl = classical.conditions[0]
|
|
128
|
+
return ModalImpl(impl.antecedent, modality, impl.consequent)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def _replace_consequent(formula: Node, new_right: Node) -> Node:
|
|
132
|
+
"""Rebuild ``formula``'s ∀-chain with its Implies' right-hand side
|
|
133
|
+
swapped for ``new_right`` — the modal node's own inner formula."""
|
|
134
|
+
if isinstance(formula, Quantifier) and formula.type == "∀":
|
|
135
|
+
return Quantifier("∀", formula.variable,
|
|
136
|
+
_replace_consequent(formula.formula, new_right))
|
|
137
|
+
assert isinstance(formula, Implies) # guaranteed by the caller's check
|
|
138
|
+
return Implies(formula.left, new_right)
|