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,45 @@
|
|
|
1
|
+
r"""Deep + maximal-shallow + minimal-shallow HOL embeddings with faithfulness proofs.
|
|
2
|
+
|
|
3
|
+
Reproduces, per non-classical object logic, the three faithful HOL embeddings of
|
|
4
|
+
Benzmüller, *Faithful Logic Embeddings in HOL — Deep and Shallow*
|
|
5
|
+
(arXiv:2502.19311v3), together with the **machine-checked faithfulness proofs**
|
|
6
|
+
relating them. See :mod:`unicode_logic_kit.hol.deepshallow._common` for the shared
|
|
7
|
+
construction and honesty notes.
|
|
8
|
+
|
|
9
|
+
Currently provided (Tier 1 — worlds-based logics that carry the deep/maximal/minimal
|
|
10
|
+
+ faithfulness scheme cleanly):
|
|
11
|
+
|
|
12
|
+
- :mod:`~unicode_logic_kit.hol.deepshallow.modal` — propositional modal logic K.
|
|
13
|
+
- :mod:`~unicode_logic_kit.hol.deepshallow.intuitionistic` — intuitionistic
|
|
14
|
+
propositional logic (Kripke semantics).
|
|
15
|
+
- :mod:`~unicode_logic_kit.hol.deepshallow.conditional` — Lewis counterfactual
|
|
16
|
+
(sphere) logic.
|
|
17
|
+
- :mod:`~unicode_logic_kit.hol.deepshallow.relevant` — relevant logic B
|
|
18
|
+
(simplified Routley–Meyer semantics).
|
|
19
|
+
|
|
20
|
+
Tier 2 (K, constant domain only) — the first *quantified* member of the family,
|
|
21
|
+
with a genuinely binder-carrying deep embedding (de Bruijn-indexed object
|
|
22
|
+
variables) rather than a propositional/schematic syntax tree:
|
|
23
|
+
|
|
24
|
+
- :mod:`~unicode_logic_kit.hol.deepshallow.qml` — quantified modal logic, scoped to
|
|
25
|
+
the base frame K, the CONSTANT domain regime, and the alethic ``□``/``◇``
|
|
26
|
+
modalities only. Every other frame, domain regime, agent-indexed/temporal/
|
|
27
|
+
deontic operator, equality and function term is refused by name — see the
|
|
28
|
+
module docstring and :mod:`unicode_logic_kit.hol.isabelle_modal` for those.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
from .modal import modal_faithfulness_theory, modal_to_deep
|
|
32
|
+
from .intuitionistic import intuitionistic_faithfulness_theory, int_to_deep
|
|
33
|
+
from .conditional import conditional_faithfulness_theory, counterfactual_to_deep
|
|
34
|
+
from .relevant import relevant_faithfulness_theory, rel_to_deep
|
|
35
|
+
from .qml import qml_deep_faithfulness_theory, qml_to_deep
|
|
36
|
+
from ._common import AtomConsts, sanitize_atom
|
|
37
|
+
|
|
38
|
+
__all__ = [
|
|
39
|
+
"modal_faithfulness_theory", "modal_to_deep",
|
|
40
|
+
"intuitionistic_faithfulness_theory", "int_to_deep",
|
|
41
|
+
"conditional_faithfulness_theory", "counterfactual_to_deep",
|
|
42
|
+
"relevant_faithfulness_theory", "rel_to_deep",
|
|
43
|
+
"qml_deep_faithfulness_theory", "qml_to_deep",
|
|
44
|
+
"AtomConsts", "sanitize_atom",
|
|
45
|
+
]
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
r"""Shared scaffolding for the deep / maximal-shallow / minimal-shallow embeddings.
|
|
2
|
+
|
|
3
|
+
This subpackage reproduces, per non-classical object logic, the three faithful
|
|
4
|
+
HOL embeddings of Benzmüller, *Faithful Logic Embeddings in HOL — Deep and
|
|
5
|
+
Shallow* (arXiv:2502.19311v3) and the **machine-checked faithfulness proofs**
|
|
6
|
+
between them:
|
|
7
|
+
|
|
8
|
+
- a **deep** embedding (the object syntax as an Isabelle ``datatype`` with a
|
|
9
|
+
recursive ``primrec`` truth predicate ``truthD``), enabling reasoning *about*
|
|
10
|
+
the object logic (induction over formula structure, meta-theorems);
|
|
11
|
+
- a **maximal (heavyweight) shallow** embedding (formulas as predicates with
|
|
12
|
+
*every* semantic parameter explicit, ``... \<Rightarrow> w \<Rightarrow> bool``);
|
|
13
|
+
- a **minimal (lightweight) shallow** embedding (the accessibility structure and
|
|
14
|
+
valuation fixed as metalogical ``consts``, formulas as ``w \<Rightarrow> bool``) — the
|
|
15
|
+
variant the paper found automates best, and the style of the toolkit's existing
|
|
16
|
+
:mod:`unicode_logic_kit.hol.isabelle_modal` decision path;
|
|
17
|
+
- and the ``primrec`` mappings ``dpToMax`` / ``dpToMin`` plus the theorems
|
|
18
|
+
``faithful1a/1b`` (deep \<leftrightarrow> maximal), ``faithful2/3`` (deep/maximal
|
|
19
|
+
\<leftrightarrow> minimal in the fixed model) and ``sound_min``, each closed by a
|
|
20
|
+
one-line ``induct`` proof.
|
|
21
|
+
|
|
22
|
+
The toolkit only *emits* these theories. With a local Isabelle/HOL they are
|
|
23
|
+
**machine-verified** end to end via
|
|
24
|
+
:func:`unicode_logic_kit.hol.isabelle_runner.check_theory` (exit 0 \<Longrightarrow>
|
|
25
|
+
Isabelle's kernel discharged every ``induct`` proof); this is what the
|
|
26
|
+
Isabelle-gated tests assert. Without Isabelle, the emitted text still has a fixed,
|
|
27
|
+
tested structure. The stack targets the **propositional / schematic** fragment,
|
|
28
|
+
where induction over the syntax datatype applies; the *quantified* decision path
|
|
29
|
+
stays in :mod:`unicode_logic_kit.hol.isabelle_modal`.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
from dataclasses import dataclass, field
|
|
33
|
+
from typing import Dict, List, Optional, Tuple, Type
|
|
34
|
+
|
|
35
|
+
from unicode_logic_kit.fol.nodes import Node, Atom, Iff, Xor, Variable, Quantifier
|
|
36
|
+
from unicode_logic_kit.fol._msfl_nodes import key_text
|
|
37
|
+
from unicode_logic_kit.fol._truth_constants import refuse_truth_constants
|
|
38
|
+
|
|
39
|
+
#: Why a deep embedding refuses the TPTP constants ``$true`` / ``$false``: its
|
|
40
|
+
#: formula datatype has a constructor for an atom and one per connective, and none
|
|
41
|
+
#: for a truth constant, so the only reading it could give one is an unrelated letter.
|
|
42
|
+
NO_CONSTANT_WHY = (
|
|
43
|
+
"the deep embedding's formula datatype has constructors for atoms and "
|
|
44
|
+
"connectives only, none for a truth constant, and an atom named $true would "
|
|
45
|
+
"be a letter that is neither true nor false")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def sanitize_atom(name: str) -> str:
|
|
49
|
+
"""Turn a propositional-atom label into a legal lowercase Isabelle constant id.
|
|
50
|
+
|
|
51
|
+
Distinct atoms get distinct ``consts`` of the shared signature type ``s``; the
|
|
52
|
+
resolver (:class:`AtomConsts`) keeps the mapping injective so two source atoms
|
|
53
|
+
that sanitise alike do not collapse.
|
|
54
|
+
"""
|
|
55
|
+
out = "".join(c if (c.isalnum() or c == "_") else "_" for c in str(name))
|
|
56
|
+
if not out:
|
|
57
|
+
out = "p"
|
|
58
|
+
if not (out[0].isalpha() or out[0] == "_"):
|
|
59
|
+
out = "p_" + out
|
|
60
|
+
return "p_" + out if not out.startswith("p_") else out
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@dataclass
|
|
64
|
+
class AtomConsts:
|
|
65
|
+
"""Injective map from propositional-atom label to an Isabelle ``s`` constant.
|
|
66
|
+
|
|
67
|
+
Encoders call :meth:`name` while walking a formula; :meth:`decls` then yields the
|
|
68
|
+
``consts NAME :: "s"`` declarations for exactly the atoms that occurred.
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
_by_label: Dict[str, str] = field(default_factory=dict)
|
|
72
|
+
_used: set = field(default_factory=set)
|
|
73
|
+
|
|
74
|
+
def name(self, label: str) -> str:
|
|
75
|
+
"""The constant naming propositional atom ``label`` (stable, de-collided)."""
|
|
76
|
+
if label in self._by_label:
|
|
77
|
+
return self._by_label[label]
|
|
78
|
+
base = sanitize_atom(label)
|
|
79
|
+
cand, k = base, 1
|
|
80
|
+
while cand in self._used:
|
|
81
|
+
k += 1
|
|
82
|
+
cand = f"{base}_{k}"
|
|
83
|
+
self._by_label[label] = cand
|
|
84
|
+
self._used.add(cand)
|
|
85
|
+
return cand
|
|
86
|
+
|
|
87
|
+
def decls(self, typ: str = "s") -> List[str]:
|
|
88
|
+
"""``consts`` lines for every atom constant handed out (sorted, stable).
|
|
89
|
+
|
|
90
|
+
``typ`` is the Isabelle type ascribed to each constant. It defaults to the
|
|
91
|
+
signature type ``s`` the deep embeddings index their valuation by; a shallow
|
|
92
|
+
decision theory that has no separate valuation passes the world-predicate
|
|
93
|
+
type instead.
|
|
94
|
+
"""
|
|
95
|
+
return [f'consts {c} :: "{typ}"' for c in sorted(self._by_label.values())]
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def theory_name_ok(name: str) -> bool:
|
|
99
|
+
"""True if ``name`` is a legal Isabelle theory identifier (letters/digits/_)."""
|
|
100
|
+
return bool(name) and name[0].isalpha() and all(
|
|
101
|
+
c.isalnum() or c == "_" for c in name)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _atom_is_propositional(node: Atom) -> bool:
|
|
105
|
+
"""True unless an argument carries a :class:`Variable` (⇒ genuinely first-order)."""
|
|
106
|
+
return not any(isinstance(n, Variable) for a in node.args for n in a.walk())
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def encode_deep(formula: Node, atoms: AtomConsts,
|
|
110
|
+
ctors: Dict[Type[Node], Tuple[str, int]], *,
|
|
111
|
+
logic: str, allow_xor: bool = True) -> str:
|
|
112
|
+
r"""Encode a **propositional** formula as a deep datatype term.
|
|
113
|
+
|
|
114
|
+
Shared by the per-logic encoders. ``ctors`` maps a toolkit node type to its deep
|
|
115
|
+
constructor name and arity (1 ⇒ ``.formula`` child, 2 ⇒ ``.left`` / ``.right``);
|
|
116
|
+
each distinct ground atom becomes an ``s`` constant collected into ``atoms``.
|
|
117
|
+
``Xor`` desugars to ``NegD (IffD ...)`` when ``allow_xor``. Raises
|
|
118
|
+
:class:`NotImplementedError` on a quantifier, a free variable, or any node type
|
|
119
|
+
absent from ``ctors`` — the deep embedding is propositional.
|
|
120
|
+
"""
|
|
121
|
+
if isinstance(formula, Atom):
|
|
122
|
+
refuse_truth_constants([formula], logic, NO_CONSTANT_WHY)
|
|
123
|
+
if not _atom_is_propositional(formula):
|
|
124
|
+
raise NotImplementedError(
|
|
125
|
+
f"{logic}: atom with a free variable is first-order; the deep "
|
|
126
|
+
"embedding is propositional.")
|
|
127
|
+
return f"(Atm {atoms.name(key_text(formula))})"
|
|
128
|
+
if isinstance(formula, (Quantifier, Variable)):
|
|
129
|
+
raise NotImplementedError(
|
|
130
|
+
f"{logic}: quantifiers/variables are first-order; the deep embedding is "
|
|
131
|
+
"propositional.")
|
|
132
|
+
if isinstance(formula, Xor):
|
|
133
|
+
if not (allow_xor and Iff in ctors):
|
|
134
|
+
raise NotImplementedError(f"{logic}: Xor is not supported.")
|
|
135
|
+
left = encode_deep(formula.left, atoms, ctors, logic=logic, allow_xor=allow_xor)
|
|
136
|
+
right = encode_deep(formula.right, atoms, ctors, logic=logic, allow_xor=allow_xor)
|
|
137
|
+
return f"(NegD (IffD {left} {right}))"
|
|
138
|
+
spec = ctors.get(type(formula))
|
|
139
|
+
if spec is None:
|
|
140
|
+
if type(formula).__name__ == "Nominal":
|
|
141
|
+
raise NotImplementedError(
|
|
142
|
+
f"{logic}: a bare lowercase name parses as a hybrid-logic NOMINAL in "
|
|
143
|
+
"modal mode, not a propositional atom. Write atoms as 0-ary predicates "
|
|
144
|
+
"(e.g. P()) or build Atom nodes directly.")
|
|
145
|
+
raise NotImplementedError(
|
|
146
|
+
f"{logic}: unsupported node type {type(formula).__name__} "
|
|
147
|
+
"(the deep embedding covers the propositional fragment only). For "
|
|
148
|
+
"the full modal family — epistemic/doxastic/assertive/bouletic, "
|
|
149
|
+
"deontic, temporal incl. Until/Since, hybrid — use "
|
|
150
|
+
"hol.isabelle_modal.to_isabelle_modal / isabelle_decide_modal or "
|
|
151
|
+
"hol.thf_modal.to_thf_modal_full instead.")
|
|
152
|
+
name, arity = spec
|
|
153
|
+
if arity == 1:
|
|
154
|
+
inner = encode_deep(formula.formula, atoms, ctors, logic=logic, allow_xor=allow_xor)
|
|
155
|
+
return f"({name} {inner})"
|
|
156
|
+
left = encode_deep(formula.left, atoms, ctors, logic=logic, allow_xor=allow_xor)
|
|
157
|
+
right = encode_deep(formula.right, atoms, ctors, logic=logic, allow_xor=allow_xor)
|
|
158
|
+
return f"({name} {left} {right})"
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def wrap_theory(theory_name: str, body: str, extra: str = "") -> str:
|
|
162
|
+
"""Wrap a verified theory ``body`` in ``theory <name> imports Main begin ... end``."""
|
|
163
|
+
if not theory_name_ok(theory_name):
|
|
164
|
+
raise ValueError(f"illegal theory name {theory_name!r}.")
|
|
165
|
+
parts = [f"theory {theory_name}", " imports Main", "begin", "", body, ""]
|
|
166
|
+
if extra:
|
|
167
|
+
parts.append(extra)
|
|
168
|
+
parts.append("end")
|
|
169
|
+
return "\n".join(parts) + "\n"
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def formula_section(term: str, atoms: AtomConsts, datatype: str) -> str:
|
|
173
|
+
"""The ``consts`` + ``definition example`` block grounding a concrete formula."""
|
|
174
|
+
lines = ["", "section \\<open>A concrete embedded formula\\<close>", ""]
|
|
175
|
+
lines += atoms.decls()
|
|
176
|
+
lines.append(f'definition example :: {datatype} where "example = {term}"')
|
|
177
|
+
return "\n".join(lines)
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
r"""Deep + maximal-shallow + minimal-shallow embeddings of **Lewis counterfactual
|
|
2
|
+
(sphere) logic**, with machine-checked faithfulness proofs.
|
|
3
|
+
|
|
4
|
+
The Boolean base is classical (per-world), and the counterfactual ``A \<box>\<rightarrow> B`` is
|
|
5
|
+
read over a system of spheres ``Sph x S`` (``S`` is a sphere of worlds around ``x``,
|
|
6
|
+
innermost = closest) with Lewis's truth condition — vacuously true if no sphere holds
|
|
7
|
+
an ``A``-world, else some sphere holds an ``A``-world and all its ``A``-worlds are
|
|
8
|
+
``B``-worlds — matching :func:`unicode_logic_kit.semantics.conditional.would`. Validity
|
|
9
|
+
ranges over ``nested`` sphere systems (any two spheres of a world are
|
|
10
|
+
\<subseteq>-comparable), the property Lewis's nested spheres have by construction; that
|
|
11
|
+
is the weakest sphere logic **V**. The dual "might" ``A \<diamond>\<rightarrow> B`` is
|
|
12
|
+
``\<not>(A \<box>\<rightarrow> \<not>B)``.
|
|
13
|
+
|
|
14
|
+
**Which sphere class this is** — and how it differs from the decision routes. ``validD``
|
|
15
|
+
/ ``validS`` here fix ``nested Sp`` and nothing more, so they denote the class
|
|
16
|
+
:data:`~unicode_logic_kit.semantics.conditional.CENTERING_LEVELS`'s ``"none"`` names, i.e.
|
|
17
|
+
Lewis's **V**. :func:`~unicode_logic_kit.semantics.conditional.cf_valid` and
|
|
18
|
+
:func:`~unicode_logic_kit.hol.isabelle_runner.isabelle_decide_counterfactual` default to
|
|
19
|
+
``"weak"`` (**VW**) instead, because modus ponens for ``\<box>\<rightarrow>`` fails in V.
|
|
20
|
+
That difference is deliberate: what is machine-checked in this module is the *faithfulness*
|
|
21
|
+
of the three embeddings to each other, which is a statement about the truth condition and
|
|
22
|
+
holds at every centering level — adding a centering premise here would constrain the
|
|
23
|
+
sphere systems without changing anything the faithfulness theorems say. Do not read a
|
|
24
|
+
``validD`` verdict as a verdict about the logic ``cf_valid`` decides.
|
|
25
|
+
|
|
26
|
+
The deep term is built from an antecedent/consequent **pair** rather than from a single
|
|
27
|
+
formula node: the encoder predates the ``Would`` / ``Might`` AST nodes and mirrors the
|
|
28
|
+
argument form of ``would`` / ``might``, whose propositional-only contract it shares.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
from typing import Optional
|
|
32
|
+
|
|
33
|
+
from unicode_logic_kit.fol.nodes import Node, Not, And, Or, Implies, Iff
|
|
34
|
+
from ._common import AtomConsts, encode_deep, wrap_theory, formula_section
|
|
35
|
+
|
|
36
|
+
# --------------------------------------------------------------------------- #
|
|
37
|
+
# Verified theory body (checked verbatim by the Isabelle-gated tests).
|
|
38
|
+
# --------------------------------------------------------------------------- #
|
|
39
|
+
|
|
40
|
+
_COND_BODY = r'''typedecl w \<comment> \<open>worlds\<close>
|
|
41
|
+
typedecl s \<comment> \<open>signature: propositional symbols (shared by all three embeddings)\<close>
|
|
42
|
+
type_synonym wset = "w \<Rightarrow> bool"
|
|
43
|
+
type_synonym sph = "w \<Rightarrow> (w \<Rightarrow> bool) \<Rightarrow> bool" \<comment> \<open>Sph x S: S is a sphere around x\<close>
|
|
44
|
+
type_synonym val = "s \<Rightarrow> w \<Rightarrow> bool"
|
|
45
|
+
|
|
46
|
+
definition nested :: "sph \<Rightarrow> bool" where
|
|
47
|
+
"nested Sp \<equiv> \<forall>x S T. Sp x S \<longrightarrow> Sp x T \<longrightarrow> (\<forall>u. S u \<longrightarrow> T u) \<or> (\<forall>u. T u \<longrightarrow> S u)"
|
|
48
|
+
|
|
49
|
+
section \<open>Deep embedding: object syntax as a datatype + recursive truth\<close>
|
|
50
|
+
|
|
51
|
+
datatype cpl =
|
|
52
|
+
Atm s | TopD | BotD
|
|
53
|
+
| NegD cpl | AndD cpl cpl | OrD cpl cpl | ImpD cpl cpl | IffD cpl cpl
|
|
54
|
+
| CondD cpl cpl
|
|
55
|
+
|
|
56
|
+
primrec truthD :: "wset \<Rightarrow> sph \<Rightarrow> val \<Rightarrow> w \<Rightarrow> cpl \<Rightarrow> bool" where
|
|
57
|
+
"truthD W Sp V x (Atm p) = V p x"
|
|
58
|
+
| "truthD W Sp V x TopD = True"
|
|
59
|
+
| "truthD W Sp V x BotD = False"
|
|
60
|
+
| "truthD W Sp V x (NegD f) = (\<not> truthD W Sp V x f)"
|
|
61
|
+
| "truthD W Sp V x (AndD f g) = (truthD W Sp V x f \<and> truthD W Sp V x g)"
|
|
62
|
+
| "truthD W Sp V x (OrD f g) = (truthD W Sp V x f \<or> truthD W Sp V x g)"
|
|
63
|
+
| "truthD W Sp V x (ImpD f g) = (truthD W Sp V x f \<longrightarrow> truthD W Sp V x g)"
|
|
64
|
+
| "truthD W Sp V x (IffD f g) = (truthD W Sp V x f = truthD W Sp V x g)"
|
|
65
|
+
| "truthD W Sp V x (CondD f g) =
|
|
66
|
+
((\<exists>S. Sp x S \<and> (\<exists>u. S u \<and> truthD W Sp V u f)
|
|
67
|
+
\<and> (\<forall>u. S u \<longrightarrow> truthD W Sp V u f \<longrightarrow> truthD W Sp V u g))
|
|
68
|
+
\<or> (\<forall>S. Sp x S \<longrightarrow> (\<forall>u. S u \<longrightarrow> \<not> truthD W Sp V u f)))"
|
|
69
|
+
|
|
70
|
+
definition validD :: "cpl \<Rightarrow> bool" where
|
|
71
|
+
"validD f \<equiv> \<forall>W Sp V. nested Sp \<longrightarrow> (\<forall>x. W x \<longrightarrow> truthD W Sp V x f)"
|
|
72
|
+
|
|
73
|
+
section \<open>Maximal (heavyweight) shallow embedding: every parameter explicit\<close>
|
|
74
|
+
|
|
75
|
+
type_synonym sigma = "wset \<Rightarrow> sph \<Rightarrow> val \<Rightarrow> w \<Rightarrow> bool"
|
|
76
|
+
definition AtmS :: "s \<Rightarrow> sigma" where "AtmS p \<equiv> \<lambda>W Sp V x. V p x"
|
|
77
|
+
definition TopS :: "sigma" where "TopS \<equiv> \<lambda>W Sp V x. True"
|
|
78
|
+
definition BotS :: "sigma" where "BotS \<equiv> \<lambda>W Sp V x. False"
|
|
79
|
+
definition NegS :: "sigma \<Rightarrow> sigma" where "NegS f \<equiv> \<lambda>W Sp V x. \<not> f W Sp V x"
|
|
80
|
+
definition AndS :: "sigma \<Rightarrow> sigma \<Rightarrow> sigma" where
|
|
81
|
+
"AndS f g \<equiv> \<lambda>W Sp V x. f W Sp V x \<and> g W Sp V x"
|
|
82
|
+
definition OrS :: "sigma \<Rightarrow> sigma \<Rightarrow> sigma" where
|
|
83
|
+
"OrS f g \<equiv> \<lambda>W Sp V x. f W Sp V x \<or> g W Sp V x"
|
|
84
|
+
definition ImpS :: "sigma \<Rightarrow> sigma \<Rightarrow> sigma" where
|
|
85
|
+
"ImpS f g \<equiv> \<lambda>W Sp V x. f W Sp V x \<longrightarrow> g W Sp V x"
|
|
86
|
+
definition IffS :: "sigma \<Rightarrow> sigma \<Rightarrow> sigma" where
|
|
87
|
+
"IffS f g \<equiv> \<lambda>W Sp V x. f W Sp V x = g W Sp V x"
|
|
88
|
+
definition CondS :: "sigma \<Rightarrow> sigma \<Rightarrow> sigma" where
|
|
89
|
+
"CondS f g \<equiv> \<lambda>W Sp V x.
|
|
90
|
+
(\<exists>S. Sp x S \<and> (\<exists>u. S u \<and> f W Sp V u)
|
|
91
|
+
\<and> (\<forall>u. S u \<longrightarrow> f W Sp V u \<longrightarrow> g W Sp V u))
|
|
92
|
+
\<or> (\<forall>S. Sp x S \<longrightarrow> (\<forall>u. S u \<longrightarrow> \<not> f W Sp V u))"
|
|
93
|
+
definition validS :: "sigma \<Rightarrow> bool" where
|
|
94
|
+
"validS f \<equiv> \<forall>W Sp V. nested Sp \<longrightarrow> (\<forall>x. W x \<longrightarrow> f W Sp V x)"
|
|
95
|
+
|
|
96
|
+
section \<open>Minimal (lightweight) shallow embedding: Sph, V fixed as metalogical consts\<close>
|
|
97
|
+
|
|
98
|
+
consts Sel :: "sph"
|
|
99
|
+
consts Vval :: "val"
|
|
100
|
+
type_synonym tau = "w \<Rightarrow> bool"
|
|
101
|
+
definition AtmM :: "s \<Rightarrow> tau" where "AtmM p \<equiv> \<lambda>x. Vval p x"
|
|
102
|
+
definition TopM :: "tau" where "TopM \<equiv> \<lambda>x. True"
|
|
103
|
+
definition BotM :: "tau" where "BotM \<equiv> \<lambda>x. False"
|
|
104
|
+
definition NegM :: "tau \<Rightarrow> tau" where "NegM f \<equiv> \<lambda>x. \<not> f x"
|
|
105
|
+
definition AndM :: "tau \<Rightarrow> tau \<Rightarrow> tau" where "AndM f g \<equiv> \<lambda>x. f x \<and> g x"
|
|
106
|
+
definition OrM :: "tau \<Rightarrow> tau \<Rightarrow> tau" where "OrM f g \<equiv> \<lambda>x. f x \<or> g x"
|
|
107
|
+
definition ImpM :: "tau \<Rightarrow> tau \<Rightarrow> tau" where "ImpM f g \<equiv> \<lambda>x. f x \<longrightarrow> g x"
|
|
108
|
+
definition IffM :: "tau \<Rightarrow> tau \<Rightarrow> tau" where "IffM f g \<equiv> \<lambda>x. f x = g x"
|
|
109
|
+
definition CondM :: "tau \<Rightarrow> tau \<Rightarrow> tau" where
|
|
110
|
+
"CondM f g \<equiv> \<lambda>x.
|
|
111
|
+
(\<exists>S. Sel x S \<and> (\<exists>u. S u \<and> f u) \<and> (\<forall>u. S u \<longrightarrow> f u \<longrightarrow> g u))
|
|
112
|
+
\<or> (\<forall>S. Sel x S \<longrightarrow> (\<forall>u. S u \<longrightarrow> \<not> f u))"
|
|
113
|
+
definition validM :: "tau \<Rightarrow> bool" where "validM f \<equiv> \<forall>x. f x"
|
|
114
|
+
|
|
115
|
+
section \<open>Mappings between the embeddings\<close>
|
|
116
|
+
|
|
117
|
+
primrec dpToMax :: "cpl \<Rightarrow> sigma" where
|
|
118
|
+
"dpToMax (Atm p) = AtmS p"
|
|
119
|
+
| "dpToMax TopD = TopS"
|
|
120
|
+
| "dpToMax BotD = BotS"
|
|
121
|
+
| "dpToMax (NegD f) = NegS (dpToMax f)"
|
|
122
|
+
| "dpToMax (AndD f g) = AndS (dpToMax f) (dpToMax g)"
|
|
123
|
+
| "dpToMax (OrD f g) = OrS (dpToMax f) (dpToMax g)"
|
|
124
|
+
| "dpToMax (ImpD f g) = ImpS (dpToMax f) (dpToMax g)"
|
|
125
|
+
| "dpToMax (IffD f g) = IffS (dpToMax f) (dpToMax g)"
|
|
126
|
+
| "dpToMax (CondD f g) = CondS (dpToMax f) (dpToMax g)"
|
|
127
|
+
|
|
128
|
+
primrec dpToMin :: "cpl \<Rightarrow> tau" where
|
|
129
|
+
"dpToMin (Atm p) = AtmM p"
|
|
130
|
+
| "dpToMin TopD = TopM"
|
|
131
|
+
| "dpToMin BotD = BotM"
|
|
132
|
+
| "dpToMin (NegD f) = NegM (dpToMin f)"
|
|
133
|
+
| "dpToMin (AndD f g) = AndM (dpToMin f) (dpToMin g)"
|
|
134
|
+
| "dpToMin (OrD f g) = OrM (dpToMin f) (dpToMin g)"
|
|
135
|
+
| "dpToMin (ImpD f g) = ImpM (dpToMin f) (dpToMin g)"
|
|
136
|
+
| "dpToMin (IffD f g) = IffM (dpToMin f) (dpToMin g)"
|
|
137
|
+
| "dpToMin (CondD f g) = CondM (dpToMin f) (dpToMin g)"
|
|
138
|
+
|
|
139
|
+
section \<open>Faithfulness (machine-checked by Isabelle's kernel)\<close>
|
|
140
|
+
|
|
141
|
+
lemmas maxdefs = AtmS_def TopS_def BotS_def NegS_def AndS_def OrS_def
|
|
142
|
+
ImpS_def IffS_def CondS_def
|
|
143
|
+
lemmas mindefs = AtmM_def TopM_def BotM_def NegM_def AndM_def OrM_def
|
|
144
|
+
ImpM_def IffM_def CondM_def
|
|
145
|
+
|
|
146
|
+
text \<open>Deep truth coincides pointwise with maximal-shallow truth.\<close>
|
|
147
|
+
theorem faithful1a: "truthD W Sp V x f = dpToMax f W Sp V x"
|
|
148
|
+
by (induct f arbitrary: x) (simp_all add: maxdefs)
|
|
149
|
+
|
|
150
|
+
text \<open>Hence deep validity coincides with maximal-shallow validity.\<close>
|
|
151
|
+
theorem faithful1b: "validD f = validS (dpToMax f)"
|
|
152
|
+
by (simp add: validD_def validS_def faithful1a)
|
|
153
|
+
|
|
154
|
+
text \<open>Deep truth in the fixed model coincides with minimal-shallow truth.\<close>
|
|
155
|
+
theorem faithful2: "truthD (\<lambda>_. True) Sel Vval x f = dpToMin f x"
|
|
156
|
+
by (induct f arbitrary: x) (simp_all add: mindefs)
|
|
157
|
+
|
|
158
|
+
text \<open>Maximal- and minimal-shallow truth coincide in that fixed model.\<close>
|
|
159
|
+
theorem faithful3: "dpToMax f (\<lambda>_. True) Sel Vval x = dpToMin f x"
|
|
160
|
+
by (induct f arbitrary: x) (simp_all add: maxdefs mindefs)
|
|
161
|
+
|
|
162
|
+
text \<open>Soundness of the minimal embedding for deep validity (under the nesting
|
|
163
|
+
assumption the minimal embedding fixes as a const).\<close>
|
|
164
|
+
theorem sound_min: "nested Sel \<Longrightarrow> validD f \<Longrightarrow> validM (dpToMin f)"
|
|
165
|
+
proof -
|
|
166
|
+
assume ne: "nested Sel" and *: "validD f"
|
|
167
|
+
have "truthD (\<lambda>_. True) Sel Vval x f" for x
|
|
168
|
+
using * ne by (simp add: validD_def)
|
|
169
|
+
then show "validM (dpToMin f)"
|
|
170
|
+
by (simp add: validM_def faithful2)
|
|
171
|
+
qed'''
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
# --------------------------------------------------------------------------- #
|
|
175
|
+
# Encoder + public entry point.
|
|
176
|
+
# --------------------------------------------------------------------------- #
|
|
177
|
+
|
|
178
|
+
# Boolean base (classical, per world); the counterfactual is built explicitly from
|
|
179
|
+
# an antecedent/consequent pair — there is no counterfactual node in the AST.
|
|
180
|
+
_BOOL_CTORS = {
|
|
181
|
+
Not: ("NegD", 1), And: ("AndD", 2), Or: ("OrD", 2),
|
|
182
|
+
Implies: ("ImpD", 2), Iff: ("IffD", 2),
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def counterfactual_to_deep(antecedent: Node, consequent: Node,
|
|
187
|
+
atoms: AtomConsts, kind: str = "would") -> str:
|
|
188
|
+
r"""Encode a counterfactual as a deep ``cpl`` term.
|
|
189
|
+
|
|
190
|
+
``kind="would"`` builds ``(CondD <a> <b>)`` (``a \<box>\<rightarrow> b``); ``kind="might"``
|
|
191
|
+
builds ``(NegD (CondD <a> (NegD <b>)))`` (``a \<diamond>\<rightarrow> b \<equiv> \<not>(a \<box>\<rightarrow> \<not>b)``).
|
|
192
|
+
Antecedent and consequent are **propositional** (atoms + Boolean connectives),
|
|
193
|
+
matching :func:`unicode_logic_kit.semantics.conditional.would`.
|
|
194
|
+
"""
|
|
195
|
+
a = encode_deep(antecedent, atoms, _BOOL_CTORS, logic="counterfactual_to_deep")
|
|
196
|
+
b = encode_deep(consequent, atoms, _BOOL_CTORS, logic="counterfactual_to_deep")
|
|
197
|
+
if kind == "would":
|
|
198
|
+
return f"(CondD {a} {b})"
|
|
199
|
+
if kind == "might":
|
|
200
|
+
return f"(NegD (CondD {a} (NegD {b})))"
|
|
201
|
+
raise ValueError(f"counterfactual_to_deep: kind must be 'would' or 'might', got {kind!r}.")
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def conditional_faithfulness_theory(
|
|
205
|
+
theory_name: str = "CondFaithfulness",
|
|
206
|
+
antecedent: Optional[Node] = None,
|
|
207
|
+
consequent: Optional[Node] = None,
|
|
208
|
+
kind: str = "would",
|
|
209
|
+
) -> str:
|
|
210
|
+
r"""Emit the self-contained Lewis-conditional deep/maximal/minimal + faithfulness theory.
|
|
211
|
+
|
|
212
|
+
When both ``antecedent`` and ``consequent`` are given, the corresponding
|
|
213
|
+
counterfactual (``kind`` ``"would"`` / ``"might"``) is appended as
|
|
214
|
+
``definition example :: cpl``. With a local Isabelle/HOL the theory is verified
|
|
215
|
+
end to end by :func:`unicode_logic_kit.hol.isabelle_runner.check_theory`.
|
|
216
|
+
"""
|
|
217
|
+
extra = ""
|
|
218
|
+
if antecedent is not None and consequent is not None:
|
|
219
|
+
atoms = AtomConsts()
|
|
220
|
+
term = counterfactual_to_deep(antecedent, consequent, atoms, kind=kind)
|
|
221
|
+
extra = formula_section(term, atoms, "cpl")
|
|
222
|
+
elif (antecedent is None) != (consequent is None):
|
|
223
|
+
raise ValueError(
|
|
224
|
+
"conditional_faithfulness_theory: pass both antecedent and consequent, or neither.")
|
|
225
|
+
return wrap_theory(theory_name, _COND_BODY, extra)
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
r"""Deep + maximal-shallow + minimal-shallow embeddings of **intuitionistic
|
|
2
|
+
propositional logic** (Kripke semantics), with machine-checked faithfulness proofs.
|
|
3
|
+
|
|
4
|
+
The accessibility relation is a preorder ``\<le>`` (``preorder``) and the valuation is
|
|
5
|
+
persistent (``monotone``); ``\<rightarrow>`` and ``\<not>`` quantify over ``\<le>``-successors, matching
|
|
6
|
+
the toolkit's :func:`unicode_logic_kit.semantics.intuitionistic.int_valid`. As in the
|
|
7
|
+
modal case, ``faithful1a/1b/2/3`` relate the three embeddings; here ``sound_min``
|
|
8
|
+
carries the two frame hypotheses (the minimal embedding fixes ``\<le>`` and ``V`` as
|
|
9
|
+
metalogical ``consts``, so their preorder/persistence must be assumed, not derived).
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from typing import Optional
|
|
13
|
+
|
|
14
|
+
from unicode_logic_kit.fol.nodes import Node, Not, And, Or, Implies, Iff
|
|
15
|
+
from ._common import AtomConsts, encode_deep, wrap_theory, formula_section
|
|
16
|
+
|
|
17
|
+
# --------------------------------------------------------------------------- #
|
|
18
|
+
# Verified theory body (checked verbatim by the Isabelle-gated tests).
|
|
19
|
+
# --------------------------------------------------------------------------- #
|
|
20
|
+
|
|
21
|
+
_INT_BODY = r'''typedecl w \<comment> \<open>worlds\<close>
|
|
22
|
+
typedecl s \<comment> \<open>signature: propositional symbols (shared by all three embeddings)\<close>
|
|
23
|
+
type_synonym wset = "w \<Rightarrow> bool"
|
|
24
|
+
type_synonym acc = "w \<Rightarrow> w \<Rightarrow> bool" \<comment> \<open>the accessibility preorder \<le>\<close>
|
|
25
|
+
type_synonym val = "s \<Rightarrow> w \<Rightarrow> bool"
|
|
26
|
+
|
|
27
|
+
definition preorder :: "acc \<Rightarrow> bool" where
|
|
28
|
+
"preorder L \<equiv> (\<forall>x. L x x) \<and> (\<forall>x y z. L x y \<longrightarrow> L y z \<longrightarrow> L x z)"
|
|
29
|
+
definition monotone :: "acc \<Rightarrow> val \<Rightarrow> bool" where
|
|
30
|
+
"monotone L V \<equiv> \<forall>p x y. L x y \<longrightarrow> V p x \<longrightarrow> V p y"
|
|
31
|
+
|
|
32
|
+
section \<open>Deep embedding: object syntax as a datatype + recursive truth\<close>
|
|
33
|
+
|
|
34
|
+
datatype ipl =
|
|
35
|
+
Atm s | TopD | BotD
|
|
36
|
+
| NegD ipl | AndD ipl ipl | OrD ipl ipl | ImpD ipl ipl | IffD ipl ipl
|
|
37
|
+
|
|
38
|
+
primrec truthD :: "wset \<Rightarrow> acc \<Rightarrow> val \<Rightarrow> w \<Rightarrow> ipl \<Rightarrow> bool" where
|
|
39
|
+
"truthD W L V x (Atm p) = V p x"
|
|
40
|
+
| "truthD W L V x TopD = True"
|
|
41
|
+
| "truthD W L V x BotD = False"
|
|
42
|
+
| "truthD W L V x (AndD f g) = (truthD W L V x f \<and> truthD W L V x g)"
|
|
43
|
+
| "truthD W L V x (OrD f g) = (truthD W L V x f \<or> truthD W L V x g)"
|
|
44
|
+
| "truthD W L V x (NegD f) = (\<forall>y. L x y \<longrightarrow> \<not> truthD W L V y f)"
|
|
45
|
+
| "truthD W L V x (ImpD f g) = (\<forall>y. L x y \<longrightarrow> truthD W L V y f \<longrightarrow> truthD W L V y g)"
|
|
46
|
+
| "truthD W L V x (IffD f g) = ((\<forall>y. L x y \<longrightarrow> truthD W L V y f \<longrightarrow> truthD W L V y g)
|
|
47
|
+
\<and> (\<forall>y. L x y \<longrightarrow> truthD W L V y g \<longrightarrow> truthD W L V y f))"
|
|
48
|
+
|
|
49
|
+
definition validD :: "ipl \<Rightarrow> bool" where
|
|
50
|
+
"validD f \<equiv> \<forall>W L V. preorder L \<longrightarrow> monotone L V \<longrightarrow> (\<forall>x. W x \<longrightarrow> truthD W L V x f)"
|
|
51
|
+
|
|
52
|
+
section \<open>Maximal (heavyweight) shallow embedding: every parameter explicit\<close>
|
|
53
|
+
|
|
54
|
+
type_synonym sigma = "wset \<Rightarrow> acc \<Rightarrow> val \<Rightarrow> w \<Rightarrow> bool"
|
|
55
|
+
definition AtmS :: "s \<Rightarrow> sigma" where "AtmS p \<equiv> \<lambda>W L V x. V p x"
|
|
56
|
+
definition TopS :: "sigma" where "TopS \<equiv> \<lambda>W L V x. True"
|
|
57
|
+
definition BotS :: "sigma" where "BotS \<equiv> \<lambda>W L V x. False"
|
|
58
|
+
definition AndS :: "sigma \<Rightarrow> sigma \<Rightarrow> sigma" where
|
|
59
|
+
"AndS f g \<equiv> \<lambda>W L V x. f W L V x \<and> g W L V x"
|
|
60
|
+
definition OrS :: "sigma \<Rightarrow> sigma \<Rightarrow> sigma" where
|
|
61
|
+
"OrS f g \<equiv> \<lambda>W L V x. f W L V x \<or> g W L V x"
|
|
62
|
+
definition NegS :: "sigma \<Rightarrow> sigma" where
|
|
63
|
+
"NegS f \<equiv> \<lambda>W L V x. \<forall>y. L x y \<longrightarrow> \<not> f W L V y"
|
|
64
|
+
definition ImpS :: "sigma \<Rightarrow> sigma \<Rightarrow> sigma" where
|
|
65
|
+
"ImpS f g \<equiv> \<lambda>W L V x. \<forall>y. L x y \<longrightarrow> f W L V y \<longrightarrow> g W L V y"
|
|
66
|
+
definition IffS :: "sigma \<Rightarrow> sigma \<Rightarrow> sigma" where
|
|
67
|
+
"IffS f g \<equiv> \<lambda>W L V x. (\<forall>y. L x y \<longrightarrow> f W L V y \<longrightarrow> g W L V y)
|
|
68
|
+
\<and> (\<forall>y. L x y \<longrightarrow> g W L V y \<longrightarrow> f W L V y)"
|
|
69
|
+
definition validS :: "sigma \<Rightarrow> bool" where
|
|
70
|
+
"validS f \<equiv> \<forall>W L V. preorder L \<longrightarrow> monotone L V \<longrightarrow> (\<forall>x. W x \<longrightarrow> f W L V x)"
|
|
71
|
+
|
|
72
|
+
section \<open>Minimal (lightweight) shallow embedding: \<le>, V fixed as metalogical consts\<close>
|
|
73
|
+
|
|
74
|
+
consts Leq :: "acc"
|
|
75
|
+
consts Vval :: "val"
|
|
76
|
+
type_synonym tau = "w \<Rightarrow> bool"
|
|
77
|
+
definition AtmM :: "s \<Rightarrow> tau" where "AtmM p \<equiv> \<lambda>x. Vval p x"
|
|
78
|
+
definition TopM :: "tau" where "TopM \<equiv> \<lambda>x. True"
|
|
79
|
+
definition BotM :: "tau" where "BotM \<equiv> \<lambda>x. False"
|
|
80
|
+
definition AndM :: "tau \<Rightarrow> tau \<Rightarrow> tau" where "AndM f g \<equiv> \<lambda>x. f x \<and> g x"
|
|
81
|
+
definition OrM :: "tau \<Rightarrow> tau \<Rightarrow> tau" where "OrM f g \<equiv> \<lambda>x. f x \<or> g x"
|
|
82
|
+
definition NegM :: "tau \<Rightarrow> tau" where "NegM f \<equiv> \<lambda>x. \<forall>y. Leq x y \<longrightarrow> \<not> f y"
|
|
83
|
+
definition ImpM :: "tau \<Rightarrow> tau \<Rightarrow> tau" where
|
|
84
|
+
"ImpM f g \<equiv> \<lambda>x. \<forall>y. Leq x y \<longrightarrow> f y \<longrightarrow> g y"
|
|
85
|
+
definition IffM :: "tau \<Rightarrow> tau \<Rightarrow> tau" where
|
|
86
|
+
"IffM f g \<equiv> \<lambda>x. (\<forall>y. Leq x y \<longrightarrow> f y \<longrightarrow> g y) \<and> (\<forall>y. Leq x y \<longrightarrow> g y \<longrightarrow> f y)"
|
|
87
|
+
definition validM :: "tau \<Rightarrow> bool" where "validM f \<equiv> \<forall>x. f x"
|
|
88
|
+
|
|
89
|
+
section \<open>Mappings between the embeddings\<close>
|
|
90
|
+
|
|
91
|
+
primrec dpToMax :: "ipl \<Rightarrow> sigma" where
|
|
92
|
+
"dpToMax (Atm p) = AtmS p"
|
|
93
|
+
| "dpToMax TopD = TopS"
|
|
94
|
+
| "dpToMax BotD = BotS"
|
|
95
|
+
| "dpToMax (NegD f) = NegS (dpToMax f)"
|
|
96
|
+
| "dpToMax (AndD f g) = AndS (dpToMax f) (dpToMax g)"
|
|
97
|
+
| "dpToMax (OrD f g) = OrS (dpToMax f) (dpToMax g)"
|
|
98
|
+
| "dpToMax (ImpD f g) = ImpS (dpToMax f) (dpToMax g)"
|
|
99
|
+
| "dpToMax (IffD f g) = IffS (dpToMax f) (dpToMax g)"
|
|
100
|
+
|
|
101
|
+
primrec dpToMin :: "ipl \<Rightarrow> tau" where
|
|
102
|
+
"dpToMin (Atm p) = AtmM p"
|
|
103
|
+
| "dpToMin TopD = TopM"
|
|
104
|
+
| "dpToMin BotD = BotM"
|
|
105
|
+
| "dpToMin (NegD f) = NegM (dpToMin f)"
|
|
106
|
+
| "dpToMin (AndD f g) = AndM (dpToMin f) (dpToMin g)"
|
|
107
|
+
| "dpToMin (OrD f g) = OrM (dpToMin f) (dpToMin g)"
|
|
108
|
+
| "dpToMin (ImpD f g) = ImpM (dpToMin f) (dpToMin g)"
|
|
109
|
+
| "dpToMin (IffD f g) = IffM (dpToMin f) (dpToMin g)"
|
|
110
|
+
|
|
111
|
+
section \<open>Faithfulness (machine-checked by Isabelle's kernel)\<close>
|
|
112
|
+
|
|
113
|
+
lemmas maxdefs = AtmS_def TopS_def BotS_def NegS_def AndS_def OrS_def ImpS_def IffS_def
|
|
114
|
+
lemmas mindefs = AtmM_def TopM_def BotM_def NegM_def AndM_def OrM_def ImpM_def IffM_def
|
|
115
|
+
|
|
116
|
+
text \<open>Deep truth coincides pointwise with maximal-shallow truth.\<close>
|
|
117
|
+
theorem faithful1a: "truthD W L V x f = dpToMax f W L V x"
|
|
118
|
+
by (induct f arbitrary: x) (simp_all add: maxdefs)
|
|
119
|
+
|
|
120
|
+
text \<open>Hence deep validity coincides with maximal-shallow validity.\<close>
|
|
121
|
+
theorem faithful1b: "validD f = validS (dpToMax f)"
|
|
122
|
+
by (simp add: validD_def validS_def faithful1a)
|
|
123
|
+
|
|
124
|
+
text \<open>Deep truth in the fixed model coincides with minimal-shallow truth.\<close>
|
|
125
|
+
theorem faithful2: "truthD (\<lambda>_. True) Leq Vval x f = dpToMin f x"
|
|
126
|
+
by (induct f arbitrary: x) (simp_all add: mindefs)
|
|
127
|
+
|
|
128
|
+
text \<open>Maximal- and minimal-shallow truth coincide in that fixed model.\<close>
|
|
129
|
+
theorem faithful3: "dpToMax f (\<lambda>_. True) Leq Vval x = dpToMin f x"
|
|
130
|
+
by (induct f arbitrary: x) (simp_all add: maxdefs mindefs)
|
|
131
|
+
|
|
132
|
+
text \<open>Soundness of the minimal embedding for deep validity (under the frame
|
|
133
|
+
assumptions the minimal embedding fixes as consts).\<close>
|
|
134
|
+
theorem sound_min:
|
|
135
|
+
"preorder Leq \<Longrightarrow> monotone Leq Vval \<Longrightarrow> validD f \<Longrightarrow> validM (dpToMin f)"
|
|
136
|
+
proof -
|
|
137
|
+
assume pre: "preorder Leq" and mono: "monotone Leq Vval" and *: "validD f"
|
|
138
|
+
have "truthD (\<lambda>_. True) Leq Vval x f" for x
|
|
139
|
+
using * pre mono by (simp add: validD_def)
|
|
140
|
+
then show "validM (dpToMin f)"
|
|
141
|
+
by (simp add: validM_def faithful2)
|
|
142
|
+
qed'''
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
# --------------------------------------------------------------------------- #
|
|
146
|
+
# Encoder + public entry point.
|
|
147
|
+
# --------------------------------------------------------------------------- #
|
|
148
|
+
|
|
149
|
+
# Intuitionistic propositional connectives (no modalities; Xor is not admitted).
|
|
150
|
+
_CTORS = {
|
|
151
|
+
Not: ("NegD", 1), And: ("AndD", 2), Or: ("OrD", 2),
|
|
152
|
+
Implies: ("ImpD", 2), Iff: ("IffD", 2),
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def int_to_deep(formula: Node, atoms: AtomConsts) -> str:
|
|
157
|
+
r"""Encode a **propositional intuitionistic** formula as a deep ``ipl`` term.
|
|
158
|
+
|
|
159
|
+
Maps ``\<not> \<and> \<or> \<rightarrow> \<leftrightarrow>`` and atoms; raises :class:`NotImplementedError` on
|
|
160
|
+
modalities, ``Xor``, quantifiers, or free variables (the deep embedding is
|
|
161
|
+
propositional intuitionistic).
|
|
162
|
+
"""
|
|
163
|
+
return encode_deep(formula, atoms, _CTORS, logic="int_to_deep", allow_xor=False)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def intuitionistic_faithfulness_theory(
|
|
167
|
+
theory_name: str = "IntFaithfulness",
|
|
168
|
+
formula: Optional[Node] = None,
|
|
169
|
+
) -> str:
|
|
170
|
+
r"""Emit the self-contained intuitionistic deep/maximal/minimal + faithfulness theory.
|
|
171
|
+
|
|
172
|
+
See :func:`unicode_logic_kit.hol.deepshallow.modal.modal_faithfulness_theory`; this
|
|
173
|
+
is the intuitionistic-Kripke counterpart. With a local Isabelle/HOL it is verified
|
|
174
|
+
end to end by :func:`unicode_logic_kit.hol.isabelle_runner.check_theory`.
|
|
175
|
+
"""
|
|
176
|
+
extra = ""
|
|
177
|
+
if formula is not None:
|
|
178
|
+
atoms = AtomConsts()
|
|
179
|
+
term = int_to_deep(formula, atoms)
|
|
180
|
+
extra = formula_section(term, atoms, "ipl")
|
|
181
|
+
return wrap_theory(theory_name, _INT_BODY, extra)
|