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,289 @@
|
|
|
1
|
+
"""What the whole-problem TPTP writers share: premise names and the entry point's name.
|
|
2
|
+
|
|
3
|
+
Every whole-problem writer (the ``fof`` writer in :mod:`~unicode_logic_kit.atp._tptp_problem`,
|
|
4
|
+
the TF0 writer in :mod:`~unicode_logic_kit.atp.tptp_tff` and the TFA writer in
|
|
5
|
+
:mod:`~unicode_logic_kit.atp._tff_problem`) writes one ``axiom`` line per premise. By default
|
|
6
|
+
the lines are called ``premise_1``, ``premise_2``, ... and ``premise_names=`` lets a caller
|
|
7
|
+
name them, so that what a prover prints about its proof (the axioms it used) can be read
|
|
8
|
+
as the caller's own names: a TPTP library problem keeps the names of its axioms, and an
|
|
9
|
+
application that holds its premises under identifiers wants them back.
|
|
10
|
+
|
|
11
|
+
**What is written.** A name is a TPTP ``<name>``: a lower-case word
|
|
12
|
+
(``[a-z][A-Za-z0-9_]*``) or an unsigned integer without leading zeros is written as it
|
|
13
|
+
is, and anything else is a single-quoted word in which ``\\`` and ``'`` are escaped
|
|
14
|
+
(``it's`` is written ``'it\\'s'``). A name that no TPTP name can spell is refused: the
|
|
15
|
+
empty name, a name with a control character (a line break would end the statement, and the
|
|
16
|
+
TPTP grammar of a quoted word has no spelling for a character below the space), and a
|
|
17
|
+
string that cannot be encoded as UTF-8 (a lone surrogate). A non-ASCII letter is written
|
|
18
|
+
as it is: Vampire and E read UTF-8 and print it back unchanged.
|
|
19
|
+
|
|
20
|
+
**What is checked.** The names are pairwise distinct AS WRITTEN, and each is distinct from
|
|
21
|
+
every name the writer generates for the other lines of the problem (the conjecture
|
|
22
|
+
``goal``, the non-emptiness line of a sort, the membership line of a sorted constant, the
|
|
23
|
+
type declarations). A clash is a ``ValueError`` that names both. A name that a prover's
|
|
24
|
+
OWN output uses for something else is refused too (:func:`prover_own_name`): Vampire prints
|
|
25
|
+
``unknown`` for an axiom whose name it does not know and numbers its statements ``f1``,
|
|
26
|
+
``f2``, ..., and E names the clauses it derives ``c_0_5`` and ``i_0_5``; a premise called
|
|
27
|
+
by one of these would be read back as another formula.
|
|
28
|
+
|
|
29
|
+
**What comes back.** The writer returns a
|
|
30
|
+
:class:`~unicode_logic_kit.atp._tptp_problem.TptpNameMap`, which records the premise names
|
|
31
|
+
in order (also the default ones) and the names and meaning of the background axioms the
|
|
32
|
+
writer added. :func:`axiom_leaf_label` and :func:`match_premise_label` read a prover's
|
|
33
|
+
printed axiom names against that record.
|
|
34
|
+
|
|
35
|
+
**What a prover prints.** Vampire echoes the name of an axiom only when asked
|
|
36
|
+
(``--output_axiom_names on``) and then in the second argument of the leaf's ``file(...)``
|
|
37
|
+
source; E prints the name as the statement name and in that argument too. Measured on
|
|
38
|
+
Vampire 5.0.1 and E 3.5.1: both print a quoted name back unchanged, except that E reads a
|
|
39
|
+
backslash followed by any character as one backslash, so an apostrophe in a name comes
|
|
40
|
+
back from E as a backslash (``it's`` is printed ``it\\s``). :func:`match_premise_label`
|
|
41
|
+
takes that into account when it is told the prover is E and refuses to choose between
|
|
42
|
+
two names that E would print alike.
|
|
43
|
+
|
|
44
|
+
**The entry point's name.** A refusal of a whole-problem writer starts with the name of the
|
|
45
|
+
function the caller called (:func:`refusals_speak_as`).
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
import contextlib
|
|
49
|
+
import re
|
|
50
|
+
from typing import Dict, Iterable, Iterator, List, Optional, Sequence, Tuple
|
|
51
|
+
|
|
52
|
+
__all__: List[str] = []
|
|
53
|
+
|
|
54
|
+
#: A TPTP lower word, which is a name as it stands.
|
|
55
|
+
_LOWER_WORD = re.compile(r"[a-z][A-Za-z0-9_]*")
|
|
56
|
+
|
|
57
|
+
#: An unsigned integer without leading zeros, which is a TPTP name as it stands.
|
|
58
|
+
_INTEGER = re.compile(r"0|[1-9][0-9]*")
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def default_premise_names(count: int) -> Tuple[str, ...]:
|
|
62
|
+
"""``premise_1`` ... ``premise_<count>``: the names every writer uses by default."""
|
|
63
|
+
return tuple(f"premise_{i}" for i in range(1, count + 1))
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def names_kwargs(premise_names: Optional[Sequence[str]]) -> Dict[str, Sequence[str]]:
|
|
67
|
+
"""``{"premise_names": premise_names}``, or ``{}`` when it is ``None``: a caller that
|
|
68
|
+
forwards the argument to a writer it did not write passes it only when it was given."""
|
|
69
|
+
return {} if premise_names is None else {"premise_names": premise_names}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def tptp_name_token(name: str) -> str:
|
|
73
|
+
"""The TPTP spelling of ``name`` (see the module docstring): the name itself when it
|
|
74
|
+
is a lower word or an unsigned integer, otherwise a single-quoted word with ``\\`` and
|
|
75
|
+
``'`` escaped. ``name`` must be a name :func:`normalise_premise_names` accepts."""
|
|
76
|
+
if _LOWER_WORD.fullmatch(name) or _INTEGER.fullmatch(name):
|
|
77
|
+
return name
|
|
78
|
+
return "'" + name.replace("\\", "\\\\").replace("'", "\\'") + "'"
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def decode_tptp_name(token: str) -> str:
|
|
82
|
+
"""The text a TPTP name token stands for: a single-quoted word without its quotes and
|
|
83
|
+
with ``\\\\`` read as ``\\`` and ``\\'`` as ``'``; any other token (a lower word, an
|
|
84
|
+
integer) as it is. A backslash before any other character is kept as it is."""
|
|
85
|
+
token = token.strip()
|
|
86
|
+
if len(token) >= 2 and token[0] == "'" and token[-1] == "'":
|
|
87
|
+
out: List[str] = []
|
|
88
|
+
body = token[1:-1]
|
|
89
|
+
i = 0
|
|
90
|
+
while i < len(body):
|
|
91
|
+
c = body[i]
|
|
92
|
+
if c == "\\" and i + 1 < len(body) and body[i + 1] in ("\\", "'"):
|
|
93
|
+
out.append(body[i + 1])
|
|
94
|
+
i += 2
|
|
95
|
+
else:
|
|
96
|
+
out.append(c)
|
|
97
|
+
i += 1
|
|
98
|
+
return "".join(out)
|
|
99
|
+
return token
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
#: Names a prover's output uses for something of its own, with what each is. Measured on
|
|
103
|
+
#: Vampire 5.0.1 and E 3.5.1: Vampire prints ``unknown`` as the name of an axiom it was not
|
|
104
|
+
#: told the name of, and names its statements ``f<k>`` (and the ``sat_conversion`` ones
|
|
105
|
+
#: ``s<k>``); E keeps the names of the problem's axioms and calls every clause it derives
|
|
106
|
+
#: ``c_<i>_<j>`` (``i_<i>_<j>`` in some of its strategies).
|
|
107
|
+
_PROVER_OWN_NAMES = (
|
|
108
|
+
(re.compile(r"unknown"), "the word Vampire prints for an axiom whose name it does not know"),
|
|
109
|
+
(re.compile(r"f[0-9]+"), "a name Vampire gives its own statements (f1, f2, ...)"),
|
|
110
|
+
(re.compile(r"[ci]_[0-9]+_[0-9]+"), "a name E gives the clauses it derives (c_0_5, i_0_5)"),
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def prover_own_name(name: str) -> Optional[str]:
|
|
115
|
+
"""What a prover uses ``name`` for in its own output (a sentence), or ``None`` when it is
|
|
116
|
+
not a name the provers use: the name of a premise must not be one, because the premise
|
|
117
|
+
that a proof's leaf is read as is decided by the name the prover prints for it."""
|
|
118
|
+
for pattern, what in _PROVER_OWN_NAMES:
|
|
119
|
+
if pattern.fullmatch(name):
|
|
120
|
+
return what
|
|
121
|
+
return None
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def _unspellable(name: str) -> Optional[str]:
|
|
125
|
+
"""Why no TPTP name spells ``name``, or ``None`` when one does."""
|
|
126
|
+
if name == "":
|
|
127
|
+
return "it is empty"
|
|
128
|
+
for ch in name:
|
|
129
|
+
if ord(ch) < 0x20 or ord(ch) == 0x7F:
|
|
130
|
+
return (f"it contains the control character U+{ord(ch):04X}, which a TPTP "
|
|
131
|
+
"quoted name cannot spell")
|
|
132
|
+
try:
|
|
133
|
+
name.encode("utf-8")
|
|
134
|
+
except UnicodeEncodeError:
|
|
135
|
+
return "it cannot be encoded as UTF-8 (it contains a lone surrogate)"
|
|
136
|
+
return None
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def normalise_premise_names(premise_names: Optional[Sequence[str]], count: int,
|
|
140
|
+
*, where: str) -> Tuple[str, ...]:
|
|
141
|
+
"""The names of ``count`` premises: ``premise_names`` checked, or the default ones.
|
|
142
|
+
|
|
143
|
+
Raises:
|
|
144
|
+
TypeError: ``premise_names`` is one string rather than a sequence of strings, or
|
|
145
|
+
one of its entries is not a string.
|
|
146
|
+
ValueError: it holds other than one name per premise, a name no TPTP name spells
|
|
147
|
+
(see the module docstring), a name a prover uses in its own output
|
|
148
|
+
(:func:`prover_own_name`), or two names that are the same as written.
|
|
149
|
+
"""
|
|
150
|
+
if premise_names is None:
|
|
151
|
+
return default_premise_names(count)
|
|
152
|
+
if isinstance(premise_names, (str, bytes)):
|
|
153
|
+
raise TypeError(
|
|
154
|
+
f"{where}: premise_names is a sequence of strings, one per premise; got the "
|
|
155
|
+
f"single {type(premise_names).__name__} {premise_names!r}")
|
|
156
|
+
names = tuple(premise_names)
|
|
157
|
+
for i, name in enumerate(names):
|
|
158
|
+
if not isinstance(name, str):
|
|
159
|
+
raise TypeError(
|
|
160
|
+
f"{where}: premise_names[{i}] must be a string, got "
|
|
161
|
+
f"{type(name).__name__} {name!r}")
|
|
162
|
+
if len(names) != count:
|
|
163
|
+
raise ValueError(
|
|
164
|
+
f"{where}: premise_names must hold one name per premise, but there "
|
|
165
|
+
f"{'is' if count == 1 else 'are'} {count} premise{'' if count == 1 else 's'} "
|
|
166
|
+
f"and {len(names)} name{'' if len(names) == 1 else 's'}")
|
|
167
|
+
written: Dict[str, int] = {}
|
|
168
|
+
for i, name in enumerate(names):
|
|
169
|
+
why = _unspellable(name)
|
|
170
|
+
if why is not None:
|
|
171
|
+
raise ValueError(f"{where}: premise_names[{i}] = {name!r} is not a premise "
|
|
172
|
+
f"name: {why}")
|
|
173
|
+
own = prover_own_name(name)
|
|
174
|
+
if own is not None:
|
|
175
|
+
raise ValueError(
|
|
176
|
+
f"{where}: premise_names[{i}] = {name!r} is {own}, so a proof that uses this "
|
|
177
|
+
"premise could be read as using another; give the premise another name")
|
|
178
|
+
token = tptp_name_token(name)
|
|
179
|
+
if token in written:
|
|
180
|
+
raise ValueError(
|
|
181
|
+
f"{where}: premise_names[{written[token]}] and premise_names[{i}] are "
|
|
182
|
+
f"both {name!r}, which is written {token}; premise names must be pairwise "
|
|
183
|
+
"distinct as written")
|
|
184
|
+
written[token] = i
|
|
185
|
+
return names
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def name_background_premises(premise_names: Sequence[str], given: int, total: int,
|
|
189
|
+
*, where: str) -> Tuple[str, ...]:
|
|
190
|
+
"""``premise_names`` for ``given`` premises, extended by one name for each of the
|
|
191
|
+
``total - given`` premises a caller's routine appended after them.
|
|
192
|
+
|
|
193
|
+
The sentences a signature declares (``api.prove(signature=...)``) and the side axioms
|
|
194
|
+
of a :class:`~unicode_logic_kit.logic.Sentence` follow the premises the caller passed.
|
|
195
|
+
The caller names the premises it passed; the others are background, named
|
|
196
|
+
``background_<k>`` (``k`` from 1) by the writer, with ``_`` appended to a name that is
|
|
197
|
+
already one of the caller's, as written. ``premise_names`` is checked as every writer
|
|
198
|
+
checks it (:func:`normalise_premise_names`) against ``given``, and the message names
|
|
199
|
+
``where``.
|
|
200
|
+
|
|
201
|
+
Raises:
|
|
202
|
+
TypeError: ``premise_names`` is one string rather than a sequence of strings, or
|
|
203
|
+
one of its entries is not a string.
|
|
204
|
+
ValueError: it holds other than ``given`` names, a name no TPTP name spells, a name a
|
|
205
|
+
prover uses in its own output (:func:`prover_own_name`), or two names that are the
|
|
206
|
+
same as written.
|
|
207
|
+
"""
|
|
208
|
+
names = normalise_premise_names(premise_names, given, where=where)
|
|
209
|
+
taken = {tptp_name_token(name) for name in names}
|
|
210
|
+
extended = list(names)
|
|
211
|
+
for k in range(1, total - given + 1):
|
|
212
|
+
candidate = f"background_{k}"
|
|
213
|
+
while tptp_name_token(candidate) in taken:
|
|
214
|
+
candidate += "_"
|
|
215
|
+
taken.add(tptp_name_token(candidate))
|
|
216
|
+
extended.append(candidate)
|
|
217
|
+
return tuple(extended)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def check_against_generated(names: Sequence[str], generated: Iterable[Tuple[str, str]],
|
|
221
|
+
*, where: str) -> None:
|
|
222
|
+
"""Refuse a premise name that is one of the names the writer gives its own lines.
|
|
223
|
+
|
|
224
|
+
``generated`` holds ``(written name, what the writer uses it for)`` for every other
|
|
225
|
+
line of the problem. Raises ``ValueError`` naming the premise and the line."""
|
|
226
|
+
used = {tptp_name_token(name): i for i, name in enumerate(names)}
|
|
227
|
+
for written, what in generated:
|
|
228
|
+
i = used.get(written)
|
|
229
|
+
if i is not None:
|
|
230
|
+
raise ValueError(
|
|
231
|
+
f"{where}: premise_names[{i}] = {names[i]!r} is the name the writer gives "
|
|
232
|
+
f"{what} ({written}); give the premise another name")
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def axiom_leaf_label(name_token: str, source_text: Optional[str]) -> str:
|
|
236
|
+
"""The name under which the problem called an axiom leaf of a proof, as printed.
|
|
237
|
+
|
|
238
|
+
E names the statement after the axiom, and Vampire (asked for axiom names) puts the
|
|
239
|
+
name in the second argument of the ``file(path, name)`` source of a leaf whose own
|
|
240
|
+
name is its running number. A ``file(...)`` source that names nothing (Vampire without
|
|
241
|
+
the option prints the word ``unknown``) leaves the statement's own name."""
|
|
242
|
+
if source_text is not None and source_text.startswith("file(") and source_text.endswith(")"):
|
|
243
|
+
from .tstp import _split_top_level
|
|
244
|
+
fields = _split_top_level(source_text[len("file("):-1])
|
|
245
|
+
if len(fields) >= 2 and fields[1].strip() not in ("", "unknown"):
|
|
246
|
+
return decode_tptp_name(fields[1])
|
|
247
|
+
return decode_tptp_name(name_token)
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def _as_eprover_prints(name: str) -> str:
|
|
251
|
+
"""What E prints for the premise ``name``: it reads a backslash and the character after
|
|
252
|
+
it as one backslash, so every apostrophe of the written name (``\\'``) is a backslash."""
|
|
253
|
+
return name.replace("'", "\\")
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def match_premise_label(label: str, names: Sequence[str],
|
|
257
|
+
*, eprover: bool = False) -> Optional[int]:
|
|
258
|
+
"""The 0-based index of the premise a printed axiom ``label`` names, or ``None``.
|
|
259
|
+
|
|
260
|
+
``label`` is the decoded name a prover printed (:func:`axiom_leaf_label`). With
|
|
261
|
+
``eprover=True`` the premise names are compared as E prints them (see the module
|
|
262
|
+
docstring), and a label that two or more premises would be printed as is not matched
|
|
263
|
+
(``None``): the proof does not say which of them it used."""
|
|
264
|
+
if not eprover:
|
|
265
|
+
for i, name in enumerate(names):
|
|
266
|
+
if name == label:
|
|
267
|
+
return i
|
|
268
|
+
return None
|
|
269
|
+
hits = [i for i, name in enumerate(names) if _as_eprover_prints(name) == label]
|
|
270
|
+
return hits[0] if len(hits) == 1 else None
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
@contextlib.contextmanager
|
|
274
|
+
def refusals_speak_as(own: str, default: str) -> Iterator[None]:
|
|
275
|
+
"""Word the refusals raised inside the block as coming from ``own``.
|
|
276
|
+
|
|
277
|
+
A writer's inner checks open their messages with the name of the writer function they
|
|
278
|
+
were written for (``default``); a caller of another entry point over the same checks
|
|
279
|
+
(``generate_tff_problem_with_mapping`` over the body of ``generate_tff_problem``) is
|
|
280
|
+
told its own name instead. Only a message that opens with ``default`` and a colon is
|
|
281
|
+
changed, so the message of a check of another layer (``Node.to_tptp: ...``) stays as
|
|
282
|
+
it is; the exception keeps its class, its other arguments and its traceback."""
|
|
283
|
+
try:
|
|
284
|
+
yield
|
|
285
|
+
except (NotImplementedError, ValueError) as exc:
|
|
286
|
+
prefix = default + ":"
|
|
287
|
+
if exc.args and isinstance(exc.args[0], str) and exc.args[0].startswith(prefix):
|
|
288
|
+
exc.args = (own + exc.args[0][len(default):],) + exc.args[1:]
|
|
289
|
+
raise
|