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,540 @@
|
|
|
1
|
+
"""Entailment checking via the Vampire theorem prover (TPTP backend).
|
|
2
|
+
|
|
3
|
+
The companion to :func:`prover9_entailment.check_logical_entailment`, but driving
|
|
4
|
+
`Vampire <https://vprover.github.io/>`_ instead of Prover9. The problem is emitted
|
|
5
|
+
in TPTP ``fof`` syntax — every premise as an ``axiom`` and the conclusion as a
|
|
6
|
+
``conjecture`` — and handed to a Vampire binary whose path the caller supplies.
|
|
7
|
+
Vampire negates the conjecture internally and reports ``SZS status Theorem`` when
|
|
8
|
+
the premises entail the conclusion.
|
|
9
|
+
|
|
10
|
+
Only the classical FOL fragment is supported, exactly as far as ``Node.to_tptp``
|
|
11
|
+
reaches: a modal, second-order, Łukasiewicz, or lambda node raises
|
|
12
|
+
``NotImplementedError`` from ``to_tptp`` and that error propagates here.
|
|
13
|
+
|
|
14
|
+
A Windows host can drive a Linux Vampire installed in WSL by passing
|
|
15
|
+
``use_wsl=True``: Vampire is then launched through ``wsl.exe`` and the temporary
|
|
16
|
+
problem file's path is translated to its ``/mnt/...`` form with ``wslpath``.
|
|
17
|
+
|
|
18
|
+
:func:`check_logical_entailment_vampire` is the original bool-returning entry
|
|
19
|
+
point and its behaviour is unchanged below. :func:`check_entailment_vampire_detailed`
|
|
20
|
+
is an additive alternative that reads Vampire's SZS status line and TSTP
|
|
21
|
+
derivation (via :mod:`atp.tstp`) instead of the old substring heuristic, for
|
|
22
|
+
callers that want the full ``atp.protocol`` status/reason vocabulary and a proof
|
|
23
|
+
DAG rather than a bare bool.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
import os
|
|
27
|
+
import re
|
|
28
|
+
import subprocess
|
|
29
|
+
import tempfile
|
|
30
|
+
from typing import List, Optional, Sequence, Tuple
|
|
31
|
+
|
|
32
|
+
from ..fol.nodes import Node
|
|
33
|
+
from ._ascii_names import reverse_map_text
|
|
34
|
+
from ._tff_problem import generate_tff_arith_problem
|
|
35
|
+
from ._tptp_problem import generate_tptp_problem_for_prover, generate_tptp_problem_with_mapping
|
|
36
|
+
from ._writer_support import names_kwargs
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _generate_vampire_input(premises: List[Node], conclusion: Node,
|
|
40
|
+
*, tff: Optional[bool] = None,
|
|
41
|
+
sort: Optional[str] = None,
|
|
42
|
+
premise_names: Optional[Sequence[str]] = None) -> str:
|
|
43
|
+
"""Build a TPTP problem string from premises and a conclusion.
|
|
44
|
+
|
|
45
|
+
Each premise becomes an ``axiom`` and the conclusion the single
|
|
46
|
+
``conjecture``. Vampire treats the single conjecture as the goal to
|
|
47
|
+
prove from the axioms.
|
|
48
|
+
|
|
49
|
+
``sort`` (``None`` by default) selects the single-numeric-sort typed
|
|
50
|
+
arithmetic route (:func:`atp._tff_problem.generate_tff_arith_problem`,
|
|
51
|
+
``'real'`` or ``'int'`` — see that module's docstring) UNCONDITIONALLY
|
|
52
|
+
when given, taking priority over ``tff``: an opt-in alternative, so a
|
|
53
|
+
caller must ask for it explicitly (every existing caller that never
|
|
54
|
+
passes ``sort`` keeps its current ``tff``-selected/auto-selected
|
|
55
|
+
behaviour byte-for-byte). With ``sort=None``, ``tff`` selects between
|
|
56
|
+
the two dialects: ``None`` (the default) tries the native, genuinely-typed
|
|
57
|
+
``tff`` route (:func:`atp.tptp_tff.generate_tff_problem`) when
|
|
58
|
+
``premises``/``conclusion`` contain a SortedQuantifier/SortedConstant/
|
|
59
|
+
SortedCount node (see :func:`atp.tptp_tff.problem_needs_tff`), and falls back
|
|
60
|
+
to the classical guard-predicate ``fof`` route when the typed writer refuses
|
|
61
|
+
the problem (a :class:`~unicode_logic_kit.atp.tptp_tff.Tf0Refusal`: its text would
|
|
62
|
+
ask another question than the kit's; or a node it does not cover that the ``fof``
|
|
63
|
+
writer does: a counting quantifier, ``Contrast``, ``Measure`` — see
|
|
64
|
+
:func:`atp._tptp_problem.generate_tptp_problem_for_prover`); a problem without a sorted node goes to
|
|
65
|
+
the ``fof`` route (:func:`atp._tptp_problem.generate_tptp_problem` — also
|
|
66
|
+
used by :mod:`atp.eprover_backend` and :mod:`atp.twee_entailment`, which build
|
|
67
|
+
the identical ``fof`` problem shape). ``tff=True``/``False`` force one route
|
|
68
|
+
explicitly, and ``True`` raises the typed writer's refusal. Every route's own
|
|
69
|
+
cross-formula symbol-collision guard can raise ``NotImplementedError`` before
|
|
70
|
+
any TPTP text is produced. ``premise_names`` names the premises' ``axiom`` lines
|
|
71
|
+
in whichever route is written (see :func:`atp._tptp_problem
|
|
72
|
+
.generate_tptp_problem_with_mapping`), ``premise_<i>`` when it is ``None``.
|
|
73
|
+
"""
|
|
74
|
+
if sort is not None:
|
|
75
|
+
problem, _name_map = generate_tff_arith_problem(
|
|
76
|
+
premises, conclusion, sort=sort, **names_kwargs(premise_names))
|
|
77
|
+
return problem
|
|
78
|
+
return generate_tptp_problem_for_prover(
|
|
79
|
+
premises, conclusion, tff=tff, fof_writer=generate_tptp_problem_with_mapping,
|
|
80
|
+
premise_names=premise_names).text
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _is_entailed_output(stdout: str) -> bool:
|
|
84
|
+
"""Decide entailment from Vampire's stdout.
|
|
85
|
+
|
|
86
|
+
Vampire reports ``SZS status Theorem`` when it proves the conjecture from the
|
|
87
|
+
axioms; ``Refutation found`` is the equivalent message in its default proof
|
|
88
|
+
output (and also covers the vacuous case of inconsistent premises, which
|
|
89
|
+
entail anything). Either signal means the entailment holds. A
|
|
90
|
+
``CounterSatisfiable`` / ``Satisfiable`` / ``Timeout`` status — or no proof at
|
|
91
|
+
all — means it does not.
|
|
92
|
+
"""
|
|
93
|
+
return ("SZS status Theorem" in stdout) or ("Refutation found" in stdout)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
#: Text that says Vampire FAILED rather than ended a search: its own
|
|
97
|
+
#: ``User error: ...``, a parse error or exception, a crash. Seen in an output
|
|
98
|
+
#: it rules out the "ended by itself" reading below, whatever else is printed.
|
|
99
|
+
_FAILURE_TEXT = re.compile(
|
|
100
|
+
r"\berror\b|exception|assertion|segmentation|core dumped|abort", re.IGNORECASE)
|
|
101
|
+
|
|
102
|
+
#: The line Vampire's statistics block ends a search with:
|
|
103
|
+
#: ``% Termination reason: Refutation not found, incomplete strategy``.
|
|
104
|
+
_TERMINATION_REASON = re.compile(r"^\s*%?\s*Termination reason:\s*(?P<why>.*?)\s*$",
|
|
105
|
+
re.MULTILINE)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _ended_by_itself(stdout: str) -> Optional[Tuple[str, str]]:
|
|
109
|
+
"""Whether a run WITHOUT an SZS status line is a search Vampire ended itself.
|
|
110
|
+
|
|
111
|
+
Vampire does not always print an SZS line when it gives up. Measured on
|
|
112
|
+
Vampire 5.0.1: a non-theorem of a typed-arithmetic (``$int``) problem ends
|
|
113
|
+
``% Refutation not found, incomplete strategy`` ... ``% Termination reason:
|
|
114
|
+
Refutation not found, incomplete strategy`` (exit code 1, no SZS line), and
|
|
115
|
+
a run stopped by its own ``--time_limit`` / ``--activation_limit`` ends
|
|
116
|
+
``% Termination reason: Time limit`` / ``Activation limit`` the same way.
|
|
117
|
+
Those are honest answers, not refusals: the problem WAS read and searched.
|
|
118
|
+
|
|
119
|
+
Returns ``(reason, why)`` -- the :mod:`atp.protocol` reason axis value and
|
|
120
|
+
the termination reason as Vampire worded it -- or ``None`` when the output
|
|
121
|
+
does not show a search that ended: no ``Termination reason`` line and no
|
|
122
|
+
``Refutation not found``, or any text of a failure (``User error``, a parse
|
|
123
|
+
error, an exception, a crash), in which case the caller reports an ERROR.
|
|
124
|
+
A reason naming a ``limit`` is a budget Vampire was given: ``Time limit`` is
|
|
125
|
+
``"timeout"``, any other limit ``"bound_hit"``; every other reason is the
|
|
126
|
+
prover giving up, ``"incomplete"``.
|
|
127
|
+
"""
|
|
128
|
+
if _FAILURE_TEXT.search(stdout):
|
|
129
|
+
return None
|
|
130
|
+
match = _TERMINATION_REASON.search(stdout)
|
|
131
|
+
if match is not None:
|
|
132
|
+
why = match.group("why")
|
|
133
|
+
elif "Refutation not found" in stdout:
|
|
134
|
+
why = "Refutation not found"
|
|
135
|
+
else:
|
|
136
|
+
return None
|
|
137
|
+
if re.search(r"\blimit\b", why, re.IGNORECASE):
|
|
138
|
+
return ("timeout" if re.match(r"time\b", why, re.IGNORECASE) else "bound_hit"), why
|
|
139
|
+
return "incomplete", why
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def _to_wsl_path(windows_path: str) -> str:
|
|
143
|
+
"""Translate a Windows path to its WSL ``/mnt/...`` form via ``wslpath``.
|
|
144
|
+
|
|
145
|
+
Backslashes are turned into forward slashes first: the WSL interop layer
|
|
146
|
+
swallows backslashes in arguments (``C:\\Users\\…`` reaches ``wslpath`` as
|
|
147
|
+
``C:Users…`` with the separators gone), whereas ``wslpath`` accepts the
|
|
148
|
+
forward-slash spelling ``C:/Users/…`` directly.
|
|
149
|
+
"""
|
|
150
|
+
result = subprocess.run(
|
|
151
|
+
["wsl.exe", "wslpath", "-u", windows_path.replace("\\", "/")],
|
|
152
|
+
capture_output=True,
|
|
153
|
+
text=True,
|
|
154
|
+
timeout=20,
|
|
155
|
+
)
|
|
156
|
+
wsl_path = result.stdout.strip()
|
|
157
|
+
if not wsl_path:
|
|
158
|
+
raise RuntimeError(
|
|
159
|
+
f"wslpath could not translate {windows_path!r} (is WSL available?): "
|
|
160
|
+
f"{result.stderr.strip()}"
|
|
161
|
+
)
|
|
162
|
+
return wsl_path
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def _spawn_vampire(input_str: str, vampire_path: str, timeout: int = 30,
|
|
166
|
+
use_wsl: bool = False,
|
|
167
|
+
extra_args: Tuple[str, ...] = ()) -> Tuple[str, bool]:
|
|
168
|
+
"""Write the TPTP problem to a temp file, run Vampire, return its raw stdout.
|
|
169
|
+
|
|
170
|
+
Shared by :func:`_run_vampire` (the original bool-returning route, which
|
|
171
|
+
calls this with ``extra_args=()`` — an unchanged command line) and
|
|
172
|
+
:func:`check_entailment_vampire_detailed` (the SZS/TSTP-reading route,
|
|
173
|
+
which adds ``--proof tptp`` so Vampire's proof is printed as annotated
|
|
174
|
+
TSTP ``fof(...)`` statements instead of its native ``N. formula [rule
|
|
175
|
+
N1,N2]`` numbered-line format — only the TSTP form is what
|
|
176
|
+
:func:`atp.tstp.parse_tstp_derivation` reads).
|
|
177
|
+
|
|
178
|
+
Returns:
|
|
179
|
+
``(stdout, timed_out)`` — ``stdout`` is Vampire's captured stdout text
|
|
180
|
+
followed by its stderr (``""`` if the process timed out before
|
|
181
|
+
producing any): Vampire writes its own ``User error: ...`` to stdout,
|
|
182
|
+
but a launcher failure (``wsl.exe`` cannot find the binary) or a crash
|
|
183
|
+
speaks on stderr, and a refusal whose explanation was dropped would
|
|
184
|
+
read like a run that merely found nothing. ``timed_out``
|
|
185
|
+
is ``True`` iff the subprocess exceeded ``timeout`` seconds. A
|
|
186
|
+
subprocess timeout is swallowed into this return value, exactly as the
|
|
187
|
+
Prover9 runner swallows one into a bool; any OTHER error — notably
|
|
188
|
+
``FileNotFoundError`` for a wrong ``vampire_path`` — propagates to the
|
|
189
|
+
caller. The temporary file is always removed, even when the subprocess
|
|
190
|
+
raises.
|
|
191
|
+
|
|
192
|
+
With ``use_wsl=True`` Vampire is invoked inside WSL as
|
|
193
|
+
``wsl.exe <vampire_path> <extra_args...> <file>``, and the Windows temp-file
|
|
194
|
+
path is first translated to its ``/mnt/...`` form with ``wslpath`` so a
|
|
195
|
+
Linux Vampire under WSL can read the file the Windows side created.
|
|
196
|
+
"""
|
|
197
|
+
with tempfile.NamedTemporaryFile(mode="w", suffix=".p", delete=False,
|
|
198
|
+
encoding="utf-8") as temp_file:
|
|
199
|
+
temp_file.write(input_str)
|
|
200
|
+
temp_filename = temp_file.name
|
|
201
|
+
|
|
202
|
+
try:
|
|
203
|
+
if use_wsl:
|
|
204
|
+
command = ["wsl.exe", vampire_path, *extra_args, _to_wsl_path(temp_filename)]
|
|
205
|
+
else:
|
|
206
|
+
command = [vampire_path, *extra_args, temp_filename]
|
|
207
|
+
result = subprocess.run(
|
|
208
|
+
command,
|
|
209
|
+
capture_output=True,
|
|
210
|
+
text=True,
|
|
211
|
+
timeout=timeout,
|
|
212
|
+
)
|
|
213
|
+
return (result.stdout or "") + (result.stderr or ""), False
|
|
214
|
+
except subprocess.TimeoutExpired:
|
|
215
|
+
return "", True
|
|
216
|
+
finally:
|
|
217
|
+
try:
|
|
218
|
+
os.unlink(temp_filename)
|
|
219
|
+
except OSError:
|
|
220
|
+
pass
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def _run_vampire(input_str: str, vampire_path: str, timeout: int = 30,
|
|
224
|
+
use_wsl: bool = False) -> bool:
|
|
225
|
+
"""Run Vampire and decide entailment from its stdout (see :func:`_spawn_vampire`
|
|
226
|
+
for the process plumbing this delegates to; behaviour is unchanged from before
|
|
227
|
+
the refactor — a timeout still reports ``False``, other errors still propagate).
|
|
228
|
+
"""
|
|
229
|
+
stdout, timed_out = _spawn_vampire(input_str, vampire_path, timeout=timeout,
|
|
230
|
+
use_wsl=use_wsl)
|
|
231
|
+
if timed_out:
|
|
232
|
+
return False
|
|
233
|
+
return _is_entailed_output(stdout)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def check_logical_entailment_vampire(premises: List[Node], conclusion: Node,
|
|
237
|
+
vampire_path: str, timeout: int = 30,
|
|
238
|
+
use_wsl: bool = False,
|
|
239
|
+
tff: Optional[bool] = None,
|
|
240
|
+
sort: Optional[str] = None) -> bool:
|
|
241
|
+
"""Return whether ``premises`` entail ``conclusion``, decided by Vampire.
|
|
242
|
+
|
|
243
|
+
Args:
|
|
244
|
+
premises: a list of classical (or many-sorted) FOL premise formulas.
|
|
245
|
+
conclusion: the (classical or many-sorted) FOL conclusion formula.
|
|
246
|
+
vampire_path: path to a Vampire executable (e.g. ``"/usr/bin/vampire"``).
|
|
247
|
+
With ``use_wsl=True`` this is the command/path INSIDE WSL — e.g.
|
|
248
|
+
``"vampire"`` if it is on the WSL ``PATH``, or ``"/home/me/vampire"``.
|
|
249
|
+
timeout: seconds to allow the Vampire process before giving up and
|
|
250
|
+
returning ``False`` (default 30).
|
|
251
|
+
use_wsl: when True, run Vampire inside WSL via ``wsl.exe`` and translate
|
|
252
|
+
the temp-file path to its ``/mnt/...`` form, so a Windows host can
|
|
253
|
+
drive a Linux Vampire installed in WSL.
|
|
254
|
+
tff: which TPTP dialect to export as — see :func:`_generate_vampire_input`.
|
|
255
|
+
``None`` (the default) tries the native typed ``tff`` route whenever
|
|
256
|
+
a sort is used and writes ``fof`` when the typed writer refuses the
|
|
257
|
+
problem; ``True``/``False`` force one route (``True`` raises the
|
|
258
|
+
typed writer's refusal).
|
|
259
|
+
sort: ``None`` (default) leaves ``tff`` in charge as above; ``'real'``
|
|
260
|
+
or ``'int'`` opts into the single-numeric-sort typed arithmetic
|
|
261
|
+
route (:func:`atp._tff_problem.generate_tff_arith_problem`)
|
|
262
|
+
UNCONDITIONALLY, activating Vampire's native arithmetic decision
|
|
263
|
+
procedures — see that module's docstring for the fragment it
|
|
264
|
+
covers (a formula that genuinely mixes several sorts, or is
|
|
265
|
+
outside the arithmetic fragment, raises ``NotImplementedError``
|
|
266
|
+
naming the construct rather than silently falling back). Without
|
|
267
|
+
``sort`` arithmetic is NOT asked for: a numeral is a constant identified
|
|
268
|
+
by its value and ``+ - * / < > ≤ ≥`` are uninterpreted symbols, which
|
|
269
|
+
the problem writers write under ordinary words (see
|
|
270
|
+
:mod:`unicode_logic_kit.atp._tptp_problem`), so ``1 ≠ 2`` and ``1 + 1 = 2``
|
|
271
|
+
are not provable here and are with ``sort='int'``.
|
|
272
|
+
|
|
273
|
+
Returns:
|
|
274
|
+
``True`` iff Vampire proves the conclusion follows from the premises.
|
|
275
|
+
Note that every premise and the conclusion must be a closed sentence:
|
|
276
|
+
Vampire rejects formulas with unquantified (free) variables, and such a
|
|
277
|
+
rejection is reported as ``False`` (no proof), not raised — EXCEPT on
|
|
278
|
+
the ``sort=`` route, which refuses a free variable
|
|
279
|
+
(:class:`~unicode_logic_kit.atp._tff_problem.TfaRefusal`, a ``ValueError`` and a
|
|
280
|
+
``NotImplementedError``) instead of silently picking an implicit-closure
|
|
281
|
+
convention (see :mod:`atp._tff_problem`'s module docstring).
|
|
282
|
+
|
|
283
|
+
Raises:
|
|
284
|
+
FileNotFoundError: ``vampire_path`` does not point to an executable (or,
|
|
285
|
+
with ``use_wsl=True``, ``wsl.exe`` itself is not found).
|
|
286
|
+
NotImplementedError: either a formula is outside the fragment the
|
|
287
|
+
selected route covers (see :func:`_generate_vampire_input`), or
|
|
288
|
+
two distinct predicate (or function/constant, or — ``tff``/
|
|
289
|
+
``sort`` route — sort) names across ``premises``/``conclusion``
|
|
290
|
+
would render as the same TPTP identifier — see
|
|
291
|
+
:mod:`atp._tptp_problem`'s, :mod:`atp.tptp_tff`'s, and
|
|
292
|
+
:mod:`atp._tff_problem`'s module docstrings for why that is
|
|
293
|
+
refused rather than silently merged into one symbol. With
|
|
294
|
+
``tff=True`` it is also a :class:`~unicode_logic_kit.atp.tptp_tff.Tf0Refusal`
|
|
295
|
+
when the typed text would ask another question than the kit's (that
|
|
296
|
+
class is a ``ValueError`` too). On the ``sort=`` route it is also a
|
|
297
|
+
:class:`~unicode_logic_kit.atp._tff_problem.TfaRefusal` for a free
|
|
298
|
+
variable, an arity conflict, or a constant-vs-function name clash
|
|
299
|
+
(a ``ValueError`` too; see :mod:`atp._tff_problem`'s module docstring).
|
|
300
|
+
ValueError: on the ``sort=`` route only — an invalid ``sort``.
|
|
301
|
+
"""
|
|
302
|
+
vampire_input = _generate_vampire_input(premises, conclusion, tff=tff, sort=sort)
|
|
303
|
+
return _run_vampire(vampire_input, vampire_path, timeout=timeout,
|
|
304
|
+
use_wsl=use_wsl)
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
# ---------------------------------------------------------------------------
|
|
308
|
+
# SZS/TSTP-reading route (additive)
|
|
309
|
+
# ---------------------------------------------------------------------------
|
|
310
|
+
|
|
311
|
+
# How much of Vampire's stdout to keep in "output_excerpt": the TAIL, since
|
|
312
|
+
# that is where the SZS status line and (when present) the end of the proof
|
|
313
|
+
# live for Vampire's default output ordering; the full text is kept whenever
|
|
314
|
+
# it is already shorter than this.
|
|
315
|
+
_EXCERPT_CHARS = 4000
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
def check_entailment_vampire_detailed(premises: List[Node], conclusion: Node,
|
|
319
|
+
vampire_path: str, timeout: int = 30,
|
|
320
|
+
use_wsl: bool = False,
|
|
321
|
+
tff: Optional[bool] = None,
|
|
322
|
+
sort: Optional[str] = None,
|
|
323
|
+
premise_names: Optional[Sequence[str]] = None,
|
|
324
|
+
axiom_names: bool = False) -> dict:
|
|
325
|
+
"""Run Vampire and read its SZS status + TSTP derivation, not just a bool.
|
|
326
|
+
|
|
327
|
+
Builds the same TPTP ``fof`` problem as :func:`check_logical_entailment_vampire`
|
|
328
|
+
(every premise an ``axiom``, the conclusion the single ``conjecture`` — a
|
|
329
|
+
``query="conjecture"`` framing in :mod:`atp.tstp` terms) and drives the same
|
|
330
|
+
subprocess plumbing (:func:`_spawn_vampire`), but decides the outcome by
|
|
331
|
+
reading the ``% SZS status ...`` line with :func:`atp.tstp.extract_szs_status`
|
|
332
|
+
and :func:`atp.tstp.szs_to_verdict_fields` instead of the old
|
|
333
|
+
``"SZS status Theorem" in stdout`` substring test — so ``CounterSatisfiable``,
|
|
334
|
+
``Timeout``, ``GaveUp``, etc. each come back as their own honest
|
|
335
|
+
``atp.protocol`` status/reason pair rather than all collapsing into "not
|
|
336
|
+
entailed". Unlike :func:`check_logical_entailment_vampire`, this function
|
|
337
|
+
passes ``--proof tptp`` on Vampire's command line: Vampire's DEFAULT proof
|
|
338
|
+
output is its own native numbered-line format (``10. mortal(socrates)
|
|
339
|
+
[resolution 7,8]``), which carries the same information but is not
|
|
340
|
+
TSTP-annotated ``fof``/``cnf`` syntax, so ``--proof tptp`` is what makes
|
|
341
|
+
:func:`atp.tstp.parse_tstp_derivation` able to read it into a proof DAG.
|
|
342
|
+
|
|
343
|
+
Args:
|
|
344
|
+
premises: a list of classical FOL premise formulas.
|
|
345
|
+
conclusion: the classical FOL conclusion formula.
|
|
346
|
+
vampire_path: path to a Vampire executable — see
|
|
347
|
+
:func:`check_logical_entailment_vampire`.
|
|
348
|
+
timeout: seconds to allow the Vampire process before giving up
|
|
349
|
+
(default 30).
|
|
350
|
+
use_wsl: drive a Linux Vampire under WSL — see
|
|
351
|
+
:func:`check_logical_entailment_vampire`.
|
|
352
|
+
sort: ``None`` (default) leaves ``tff`` in charge; ``'real'``/``'int'``
|
|
353
|
+
opts into the single-numeric-sort typed arithmetic route — see
|
|
354
|
+
:func:`check_logical_entailment_vampire`'s ``sort`` for the full
|
|
355
|
+
contract. Every route (``fof``, ``tff``, ``sort``) hands back a
|
|
356
|
+
:class:`~unicode_logic_kit.atp._tptp_problem.TptpNameMap`, so
|
|
357
|
+
``output_excerpt`` below IS reverse-mapped to original kit-level
|
|
358
|
+
names on all of them. ``derivation`` still degrades to ``None``
|
|
359
|
+
on the ``tff`` and ``sort`` routes (see below) — :mod:`atp.tstp`
|
|
360
|
+
reads only ``fof``/``cnf`` derivation lines, never ``tff``, a
|
|
361
|
+
pre-existing gap.
|
|
362
|
+
premise_names: one name per premise for the problem's ``axiom`` lines
|
|
363
|
+
instead of ``premise_<i>``, in whichever dialect is written (see
|
|
364
|
+
:func:`atp._tptp_problem.generate_tptp_problem_with_mapping`). Naming the
|
|
365
|
+
premises also asks Vampire to print the names of the axioms of its proof
|
|
366
|
+
(``--output_axiom_names on``), which it otherwise replaces by ``unknown``, so
|
|
367
|
+
that ``relevant_premises`` below can be read.
|
|
368
|
+
axiom_names: ask Vampire for the names of the axioms of its proof without naming
|
|
369
|
+
the premises (they are then ``premise_<i>``). The command line stays
|
|
370
|
+
``--proof tptp`` when neither this nor ``premise_names`` is given.
|
|
371
|
+
|
|
372
|
+
Returns:
|
|
373
|
+
A JSON-compatible dict:
|
|
374
|
+
|
|
375
|
+
* ``szs_status``: the raw SZS status token (e.g. ``"Theorem"``), or
|
|
376
|
+
``None`` if Vampire's output had no ``SZS status`` line at all (a
|
|
377
|
+
timeout before any output, a Vampire build/mode that suppresses
|
|
378
|
+
the line, or Vampire REFUSING the problem). With no line,
|
|
379
|
+
``status``/``reason`` fall back to the same "Refutation found"
|
|
380
|
+
substring heuristic :func:`check_logical_entailment_vampire` uses
|
|
381
|
+
(``PROVED`` when it is there, so this function is never STRICTLY
|
|
382
|
+
less informative than the old one); otherwise to what Vampire
|
|
383
|
+
printed about how its search ended. A ``Termination reason:`` line
|
|
384
|
+
(``Refutation not found, incomplete strategy`` — Vampire 5.0.1 ends
|
|
385
|
+
a non-theorem of a typed-arithmetic problem this way, with no SZS
|
|
386
|
+
line) is an honest ``UNKNOWN``: ``"incomplete"``, or ``"timeout"``
|
|
387
|
+
/ ``"bound_hit"`` when the reason is Vampire's own ``Time limit`` /
|
|
388
|
+
another limit (see :func:`_ended_by_itself`). Only when it printed
|
|
389
|
+
neither a verdict, a refutation nor such an account, although
|
|
390
|
+
nothing cut it off — or printed an error — is it ``ERROR``/
|
|
391
|
+
``"infra"``: a refusal or a crash. Its own message is in
|
|
392
|
+
``output_excerpt``.
|
|
393
|
+
* ``status``: ``atp.protocol.PROVED`` / ``REFUTED`` / ``UNKNOWN`` /
|
|
394
|
+
``ERROR`` (``UNKNOWN``/``"timeout"`` on a subprocess timeout;
|
|
395
|
+
``ERROR``/``"infra"`` when there is no SZS line and no account of
|
|
396
|
+
a search that ended, or an SZS line that itself names an error such
|
|
397
|
+
as ``SyntaxError``).
|
|
398
|
+
* ``reason``: the matching ``atp.protocol`` reason axis value, or
|
|
399
|
+
``None`` for a definitive verdict.
|
|
400
|
+
* ``output_excerpt``: the last :data:`_EXCERPT_CHARS` characters of
|
|
401
|
+
Vampire's stdout and stderr (the whole thing, if shorter) — always
|
|
402
|
+
present, even ``""`` on a timeout, so a caller always has something
|
|
403
|
+
to show.
|
|
404
|
+
* ``derivation``: :class:`atp.tstp.TstpDerivation`'s ``to_dict()``
|
|
405
|
+
when the output contained at least one parseable ``fof``/``cnf``
|
|
406
|
+
statement, else ``None`` (no derivation to report — not an error).
|
|
407
|
+
:func:`atp.tstp.parse_tstp_derivation` only recognises ``fof``/
|
|
408
|
+
``cnf`` statements (see its own docstring), never ``tff``/``tcf``
|
|
409
|
+
ones, so on the ``tff`` route ``derivation`` is CURRENTLY ALWAYS
|
|
410
|
+
``None`` — even for a genuine, successful proof whose stdout is
|
|
411
|
+
full of well-formed ``tff(...)`` proof lines. This is a real gap
|
|
412
|
+
in the READER (:func:`atp.tstp.parse_tstp_derivation` reads
|
|
413
|
+
``fof``/``cnf`` lines only), not in the name mapping: the excerpt
|
|
414
|
+
of a ``tff`` run IS translated back through the TF0 writer's name
|
|
415
|
+
map.
|
|
416
|
+
* ``dialect``: which writer produced the problem Vampire was given:
|
|
417
|
+
``"fof"``, ``"tff"`` or ``"tfa"`` (the ``sort=`` route).
|
|
418
|
+
* ``tff_fallback``: ``None``, or — when ``tff=None`` tried the typed
|
|
419
|
+
writer for a sorted problem, was refused, and wrote ``fof`` instead —
|
|
420
|
+
the sentence that says so and quotes the typed writer's reason (the
|
|
421
|
+
backend puts it into the verdict's ``detail``).
|
|
422
|
+
* ``relevant_premises``: for a PROVED answer to a run that asked for the axiom
|
|
423
|
+
names (``premise_names`` or ``axiom_names``), the sorted 0-based indices of the
|
|
424
|
+
premises the proof's axiom leaves are
|
|
425
|
+
(:func:`atp.tstp.relevant_premises_from_tstp`, read through the problem's name
|
|
426
|
+
map); ``None`` otherwise, and when the proof cannot be read that way.
|
|
427
|
+
* ``background_used``: the ``(name, meaning)`` pairs of the background axioms the
|
|
428
|
+
writer added on its own (the non-emptiness of a sort, the membership of a sorted
|
|
429
|
+
constant) that the proof used — background, not premises, so they are not in
|
|
430
|
+
``relevant_premises``; ``()`` when none, or when ``relevant_premises`` is
|
|
431
|
+
``None``.
|
|
432
|
+
|
|
433
|
+
Every symbol name in ``output_excerpt`` and in ``derivation``'s
|
|
434
|
+
formulas has already been translated back from whatever ASCII-safe
|
|
435
|
+
token the problem writer may have substituted (a non-ASCII or
|
|
436
|
+
digit-leading kit-level name, or a function/constant renamed because
|
|
437
|
+
its word is a predicate's: ``agent`` -> ``agent_term``) to the
|
|
438
|
+
ORIGINAL kit-level name — on the ``fof`` route
|
|
439
|
+
(:func:`atp._tptp_problem.generate_tptp_problem_with_mapping`), the
|
|
440
|
+
``tff`` route (:func:`atp.tptp_tff.generate_tff_problem_with_mapping`)
|
|
441
|
+
and the ``sort`` route alike. A name Vampire introduced itself (a
|
|
442
|
+
Skolem constant, a clausification symbol) was never one of ours and
|
|
443
|
+
is left as Vampire printed it, and so is a SORT name on the ``tff``
|
|
444
|
+
route (the TF0 map covers predicates, functions and constants, not
|
|
445
|
+
sorts).
|
|
446
|
+
|
|
447
|
+
Raises:
|
|
448
|
+
FileNotFoundError: ``vampire_path`` does not point to an executable
|
|
449
|
+
(or, with ``use_wsl=True``, ``wsl.exe`` itself is not found) —
|
|
450
|
+
same contract as :func:`check_logical_entailment_vampire`.
|
|
451
|
+
NotImplementedError: a formula is outside the fragment the selected
|
|
452
|
+
route covers, or a symbol-folding collision (see
|
|
453
|
+
:func:`check_logical_entailment_vampire`'s ``Raises`` for both),
|
|
454
|
+
surfaced before any subprocess is spawned — same contract as
|
|
455
|
+
:func:`check_logical_entailment_vampire`.
|
|
456
|
+
"""
|
|
457
|
+
from .protocol import ERROR, PROVED, UNKNOWN
|
|
458
|
+
from .tstp import (
|
|
459
|
+
_premise_use_from_tstp, extract_szs_status, parse_tstp_derivation,
|
|
460
|
+
reverse_map_derivation, szs_to_verdict_fields,
|
|
461
|
+
)
|
|
462
|
+
|
|
463
|
+
if sort is not None:
|
|
464
|
+
vampire_input, name_map = generate_tff_arith_problem(
|
|
465
|
+
premises, conclusion, sort=sort, **names_kwargs(premise_names))
|
|
466
|
+
dialect, fallback_note = "tfa", None
|
|
467
|
+
else:
|
|
468
|
+
built = generate_tptp_problem_for_prover(
|
|
469
|
+
premises, conclusion, tff=tff, fof_writer=generate_tptp_problem_with_mapping,
|
|
470
|
+
premise_names=premise_names)
|
|
471
|
+
vampire_input, name_map = built.text, built.name_map
|
|
472
|
+
dialect, fallback_note = built.dialect, built.fallback_note
|
|
473
|
+
read_axiom_names = axiom_names or premise_names is not None
|
|
474
|
+
extra_args = ("--proof", "tptp") + (("--output_axiom_names", "on") if read_axiom_names else ())
|
|
475
|
+
stdout, timed_out = _spawn_vampire(vampire_input, vampire_path, timeout=timeout,
|
|
476
|
+
use_wsl=use_wsl, extra_args=extra_args)
|
|
477
|
+
|
|
478
|
+
if timed_out:
|
|
479
|
+
return {
|
|
480
|
+
"szs_status": None,
|
|
481
|
+
"status": UNKNOWN,
|
|
482
|
+
"reason": "timeout",
|
|
483
|
+
"output_excerpt": "",
|
|
484
|
+
"derivation": None,
|
|
485
|
+
"dialect": dialect,
|
|
486
|
+
"tff_fallback": fallback_note,
|
|
487
|
+
"relevant_premises": None,
|
|
488
|
+
"background_used": (),
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
if name_map is None:
|
|
492
|
+
excerpt = stdout[-_EXCERPT_CHARS:]
|
|
493
|
+
else:
|
|
494
|
+
pred_rev, term_rev = name_map.reverse_rendered()
|
|
495
|
+
excerpt = reverse_map_text(stdout[-_EXCERPT_CHARS:], pred_rev, term_rev)
|
|
496
|
+
szs = extract_szs_status(stdout)
|
|
497
|
+
if szs is None:
|
|
498
|
+
if _is_entailed_output(stdout):
|
|
499
|
+
status, reason = PROVED, None
|
|
500
|
+
elif (ended := _ended_by_itself(stdout)) is not None:
|
|
501
|
+
# No SZS line, but Vampire printed how its search ended
|
|
502
|
+
# ("Termination reason: Refutation not found, incomplete strategy"):
|
|
503
|
+
# it READ the problem and gave up (or hit its own limit). That is
|
|
504
|
+
# an honest UNKNOWN, not a refusal.
|
|
505
|
+
status, reason = UNKNOWN, ended[0]
|
|
506
|
+
else:
|
|
507
|
+
# No SZS verdict, no refutation and no account of a search, and the
|
|
508
|
+
# process was not cut off by our timeout (handled above): Vampire
|
|
509
|
+
# REFUSED the problem (its "User error: ..." / parse-error text is
|
|
510
|
+
# in the output) or died. That is a failure, not "incomplete" --
|
|
511
|
+
# reporting it as UNKNOWN made a problem Vampire could not read
|
|
512
|
+
# look like one it ran out of time on.
|
|
513
|
+
status, reason = ERROR, "infra"
|
|
514
|
+
else:
|
|
515
|
+
status, reason = szs_to_verdict_fields(szs, query="conjecture")
|
|
516
|
+
|
|
517
|
+
parsed = parse_tstp_derivation(stdout)
|
|
518
|
+
derivation = parsed if name_map is None else reverse_map_derivation(parsed, name_map)
|
|
519
|
+
derivation_dict = derivation.to_dict() if derivation.steps else None
|
|
520
|
+
|
|
521
|
+
# The proof's axiom leaves, by the names the problem gave them: read from the text
|
|
522
|
+
# Vampire printed (a premise name is not a symbol, so never the renamed excerpt).
|
|
523
|
+
relevant: Optional[Tuple[int, ...]] = None
|
|
524
|
+
background_used: Tuple[Tuple[str, str], ...] = ()
|
|
525
|
+
if read_axiom_names and status == PROVED:
|
|
526
|
+
use = _premise_use_from_tstp(stdout, len(premises), name_map)
|
|
527
|
+
if use is not None:
|
|
528
|
+
relevant, background_used = use
|
|
529
|
+
|
|
530
|
+
return {
|
|
531
|
+
"szs_status": szs,
|
|
532
|
+
"status": status,
|
|
533
|
+
"reason": reason,
|
|
534
|
+
"output_excerpt": excerpt,
|
|
535
|
+
"derivation": derivation_dict,
|
|
536
|
+
"dialect": dialect,
|
|
537
|
+
"tff_fallback": fallback_note,
|
|
538
|
+
"relevant_premises": relevant,
|
|
539
|
+
"background_used": background_used,
|
|
540
|
+
}
|