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.
Files changed (237) hide show
  1. unicode_logic_kit/__init__.py +385 -0
  2. unicode_logic_kit/__main__.py +520 -0
  3. unicode_logic_kit/_deadline.py +219 -0
  4. unicode_logic_kit/ace/__init__.py +126 -0
  5. unicode_logic_kit/ace/_align.py +135 -0
  6. unicode_logic_kit/ace/chem_lexicon.py +128 -0
  7. unicode_logic_kit/ace/drs_reader.py +570 -0
  8. unicode_logic_kit/ace/mapping.py +666 -0
  9. unicode_logic_kit/ace/reverse_modal.py +138 -0
  10. unicode_logic_kit/ace/runner.py +551 -0
  11. unicode_logic_kit/ace/translate.py +452 -0
  12. unicode_logic_kit/ace/verbalize.py +1070 -0
  13. unicode_logic_kit/api.py +1284 -0
  14. unicode_logic_kit/atp/__init__.py +177 -0
  15. unicode_logic_kit/atp/_ascii_names.py +113 -0
  16. unicode_logic_kit/atp/_html.py +72 -0
  17. unicode_logic_kit/atp/_substructural_input.py +228 -0
  18. unicode_logic_kit/atp/_tff_problem.py +715 -0
  19. unicode_logic_kit/atp/_tptp_problem.py +1111 -0
  20. unicode_logic_kit/atp/_writer_support.py +289 -0
  21. unicode_logic_kit/atp/clingo_backend.py +1180 -0
  22. unicode_logic_kit/atp/cvc5_backend.py +1385 -0
  23. unicode_logic_kit/atp/eprover_backend.py +732 -0
  24. unicode_logic_kit/atp/finite_domain.py +1055 -0
  25. unicode_logic_kit/atp/fitch.py +1547 -0
  26. unicode_logic_kit/atp/fitch_search.py +551 -0
  27. unicode_logic_kit/atp/hets_backend.py +339 -0
  28. unicode_logic_kit/atp/hybrid_down.py +120 -0
  29. unicode_logic_kit/atp/incremental.py +250 -0
  30. unicode_logic_kit/atp/kripke_enum.py +741 -0
  31. unicode_logic_kit/atp/lambek.py +436 -0
  32. unicode_logic_kit/atp/leo3_backend.py +332 -0
  33. unicode_logic_kit/atp/linear.py +738 -0
  34. unicode_logic_kit/atp/lj.py +705 -0
  35. unicode_logic_kit/atp/logic_backends.py +566 -0
  36. unicode_logic_kit/atp/ltl_tableau.py +1084 -0
  37. unicode_logic_kit/atp/minizinc_backend.py +1402 -0
  38. unicode_logic_kit/atp/modal_tableau.py +1382 -0
  39. unicode_logic_kit/atp/nanocop_backend.py +410 -0
  40. unicode_logic_kit/atp/portfolio.py +489 -0
  41. unicode_logic_kit/atp/protocol.py +1803 -0
  42. unicode_logic_kit/atp/prover9_entailment.py +1153 -0
  43. unicode_logic_kit/atp/resolution.py +1376 -0
  44. unicode_logic_kit/atp/resolution_check.py +1114 -0
  45. unicode_logic_kit/atp/sequent.py +1050 -0
  46. unicode_logic_kit/atp/tableau.py +921 -0
  47. unicode_logic_kit/atp/tableau_check.py +543 -0
  48. unicode_logic_kit/atp/tptp_ncl.py +811 -0
  49. unicode_logic_kit/atp/tptp_tff.py +1546 -0
  50. unicode_logic_kit/atp/tstp.py +1333 -0
  51. unicode_logic_kit/atp/tstp_check.py +1096 -0
  52. unicode_logic_kit/atp/twee_backend.py +236 -0
  53. unicode_logic_kit/atp/twee_check.py +711 -0
  54. unicode_logic_kit/atp/twee_entailment.py +953 -0
  55. unicode_logic_kit/atp/vampire_entailment.py +540 -0
  56. unicode_logic_kit/atp/z3_arith.py +470 -0
  57. unicode_logic_kit/atp/z3_equivalence.py +36 -0
  58. unicode_logic_kit/atp/z3_fuzzy.py +362 -0
  59. unicode_logic_kit/atp/z3_input.py +500 -0
  60. unicode_logic_kit/atp/z3_models.py +208 -0
  61. unicode_logic_kit/chem/__init__.py +88 -0
  62. unicode_logic_kit/chem/_naming.py +284 -0
  63. unicode_logic_kit/chem/cache.py +185 -0
  64. unicode_logic_kit/chem/interop.py +244 -0
  65. unicode_logic_kit/chem/mol.py +525 -0
  66. unicode_logic_kit/chem/signature.py +112 -0
  67. unicode_logic_kit/comorphism.py +497 -0
  68. unicode_logic_kit/dl/__init__.py +384 -0
  69. unicode_logic_kit/dl/classification.py +227 -0
  70. unicode_logic_kit/dl/concepts.py +632 -0
  71. unicode_logic_kit/dl/datatypes.py +818 -0
  72. unicode_logic_kit/dl/owl_functional.py +2433 -0
  73. unicode_logic_kit/dl/owl_manchester.py +1637 -0
  74. unicode_logic_kit/dl/owl_reasoner.py +790 -0
  75. unicode_logic_kit/dl/parser.py +391 -0
  76. unicode_logic_kit/dl/tableau.py +4048 -0
  77. unicode_logic_kit/dl/translate.py +2704 -0
  78. unicode_logic_kit/drt/__init__.py +94 -0
  79. unicode_logic_kit/drt/export.py +179 -0
  80. unicode_logic_kit/drt/nodes.py +506 -0
  81. unicode_logic_kit/drt/parser.py +965 -0
  82. unicode_logic_kit/drt/resolve.py +195 -0
  83. unicode_logic_kit/drt/reverse.py +175 -0
  84. unicode_logic_kit/eval/__init__.py +106 -0
  85. unicode_logic_kit/eval/batch.py +382 -0
  86. unicode_logic_kit/eval/canonical.py +663 -0
  87. unicode_logic_kit/eval/chem_batch.py +606 -0
  88. unicode_logic_kit/eval/converses.py +200 -0
  89. unicode_logic_kit/eval/datasets/__init__.py +136 -0
  90. unicode_logic_kit/eval/datasets/_base.py +263 -0
  91. unicode_logic_kit/eval/datasets/_proofwriter_proof.py +422 -0
  92. unicode_logic_kit/eval/datasets/c3po.py +678 -0
  93. unicode_logic_kit/eval/datasets/folio.py +158 -0
  94. unicode_logic_kit/eval/datasets/fracas.py +418 -0
  95. unicode_logic_kit/eval/datasets/groves.py +191 -0
  96. unicode_logic_kit/eval/datasets/logicbench.py +467 -0
  97. unicode_logic_kit/eval/datasets/logicnli.py +303 -0
  98. unicode_logic_kit/eval/datasets/malls.py +133 -0
  99. unicode_logic_kit/eval/datasets/pfolio.py +594 -0
  100. unicode_logic_kit/eval/datasets/pmb.py +242 -0
  101. unicode_logic_kit/eval/datasets/prontoqa.py +611 -0
  102. unicode_logic_kit/eval/datasets/proofwriter.py +1431 -0
  103. unicode_logic_kit/eval/datasets/proverqa.py +674 -0
  104. unicode_logic_kit/eval/datasets/willow.py +478 -0
  105. unicode_logic_kit/eval/equivalence.py +466 -0
  106. unicode_logic_kit/eval/exercise_gen.py +533 -0
  107. unicode_logic_kit/eval/explain.py +791 -0
  108. unicode_logic_kit/eval/generality.py +750 -0
  109. unicode_logic_kit/eval/metric_hf.py +458 -0
  110. unicode_logic_kit/eval/predicate_match.py +343 -0
  111. unicode_logic_kit/eval/theory_check.py +1170 -0
  112. unicode_logic_kit/eval/validate.py +306 -0
  113. unicode_logic_kit/fol/__init__.py +177 -0
  114. unicode_logic_kit/fol/_atom_keys.py +510 -0
  115. unicode_logic_kit/fol/_fol_nodes.py +3586 -0
  116. unicode_logic_kit/fol/_free_parameters.py +105 -0
  117. unicode_logic_kit/fol/_ho_nodes.py +448 -0
  118. unicode_logic_kit/fol/_hybrid_nodes.py +308 -0
  119. unicode_logic_kit/fol/_identifiers.py +1091 -0
  120. unicode_logic_kit/fol/_lambek_nodes.py +112 -0
  121. unicode_logic_kit/fol/_linear_nodes.py +352 -0
  122. unicode_logic_kit/fol/_modal_nodes.py +1467 -0
  123. unicode_logic_kit/fol/_msfl_nodes.py +2196 -0
  124. unicode_logic_kit/fol/_numeral_symbols.py +231 -0
  125. unicode_logic_kit/fol/_so_nodes.py +200 -0
  126. unicode_logic_kit/fol/_symbol_names.py +81 -0
  127. unicode_logic_kit/fol/_team_nodes.py +181 -0
  128. unicode_logic_kit/fol/_tptp_symbols.py +551 -0
  129. unicode_logic_kit/fol/_truth_constants.py +117 -0
  130. unicode_logic_kit/fol/casl_export.py +1135 -0
  131. unicode_logic_kit/fol/casl_import.py +929 -0
  132. unicode_logic_kit/fol/derivation.py +367 -0
  133. unicode_logic_kit/fol/dialect_detect.py +70 -0
  134. unicode_logic_kit/fol/dialect_repair.py +537 -0
  135. unicode_logic_kit/fol/frames.py +637 -0
  136. unicode_logic_kit/fol/grammars/terminals.lark +31 -0
  137. unicode_logic_kit/fol/lambda_tools.py +297 -0
  138. unicode_logic_kit/fol/latex_input.py +429 -0
  139. unicode_logic_kit/fol/modal_translation.py +944 -0
  140. unicode_logic_kit/fol/msflparser.py +1033 -0
  141. unicode_logic_kit/fol/naming.py +422 -0
  142. unicode_logic_kit/fol/nodes.py +241 -0
  143. unicode_logic_kit/fol/normalforms.py +492 -0
  144. unicode_logic_kit/fol/pal.py +287 -0
  145. unicode_logic_kit/fol/prolog_export.py +566 -0
  146. unicode_logic_kit/fol/prolog_input.py +505 -0
  147. unicode_logic_kit/fol/prover9_input.py +1325 -0
  148. unicode_logic_kit/fol/qml.py +1760 -0
  149. unicode_logic_kit/fol/qmltp_input.py +525 -0
  150. unicode_logic_kit/fol/sanitize.py +221 -0
  151. unicode_logic_kit/fol/serialize.py +79 -0
  152. unicode_logic_kit/fol/signature.py +1290 -0
  153. unicode_logic_kit/fol/simplify_check.py +544 -0
  154. unicode_logic_kit/fol/spans.py +594 -0
  155. unicode_logic_kit/fol/tptp_input.py +1503 -0
  156. unicode_logic_kit/fol/tptp_repair.py +941 -0
  157. unicode_logic_kit/fol/unification.py +157 -0
  158. unicode_logic_kit/fol/verbalize.py +263 -0
  159. unicode_logic_kit/hets/__init__.py +163 -0
  160. unicode_logic_kit/hets/bridge.py +142 -0
  161. unicode_logic_kit/hets/client.py +748 -0
  162. unicode_logic_kit/hets/docker.py +420 -0
  163. unicode_logic_kit/hets/dol.py +712 -0
  164. unicode_logic_kit/hets/haskell_json.py +355 -0
  165. unicode_logic_kit/hets/owl_backend.py +794 -0
  166. unicode_logic_kit/hets/owl_cli.py +598 -0
  167. unicode_logic_kit/hets/symbols.py +512 -0
  168. unicode_logic_kit/hol/__init__.py +140 -0
  169. unicode_logic_kit/hol/_ho_common.py +323 -0
  170. unicode_logic_kit/hol/_isabelle_binders.py +125 -0
  171. unicode_logic_kit/hol/classical.py +812 -0
  172. unicode_logic_kit/hol/deepshallow/__init__.py +45 -0
  173. unicode_logic_kit/hol/deepshallow/_common.py +177 -0
  174. unicode_logic_kit/hol/deepshallow/conditional.py +225 -0
  175. unicode_logic_kit/hol/deepshallow/intuitionistic.py +181 -0
  176. unicode_logic_kit/hol/deepshallow/modal.py +217 -0
  177. unicode_logic_kit/hol/deepshallow/qml.py +406 -0
  178. unicode_logic_kit/hol/deepshallow/relevant.py +206 -0
  179. unicode_logic_kit/hol/free.py +753 -0
  180. unicode_logic_kit/hol/goedel.py +336 -0
  181. unicode_logic_kit/hol/ho_modal.py +1743 -0
  182. unicode_logic_kit/hol/intuitionistic.py +403 -0
  183. unicode_logic_kit/hol/isabelle_conditional.py +593 -0
  184. unicode_logic_kit/hol/isabelle_modal.py +1908 -0
  185. unicode_logic_kit/hol/isabelle_relevant.py +412 -0
  186. unicode_logic_kit/hol/isabelle_runner.py +1147 -0
  187. unicode_logic_kit/hol/isabelle_substructural.py +884 -0
  188. unicode_logic_kit/hol/lean.py +1018 -0
  189. unicode_logic_kit/hol/manyvalued.py +921 -0
  190. unicode_logic_kit/hol/secondorder.py +687 -0
  191. unicode_logic_kit/hol/thf_modal.py +941 -0
  192. unicode_logic_kit/hol/thirdorder.py +397 -0
  193. unicode_logic_kit/ilp/__init__.py +89 -0
  194. unicode_logic_kit/ilp/readback.py +389 -0
  195. unicode_logic_kit/ilp/separation.py +153 -0
  196. unicode_logic_kit/ilp/task.py +730 -0
  197. unicode_logic_kit/logic.py +163 -0
  198. unicode_logic_kit/mcp/__init__.py +28 -0
  199. unicode_logic_kit/mcp/__main__.py +5 -0
  200. unicode_logic_kit/mcp/chem_tools.py +1031 -0
  201. unicode_logic_kit/mcp/server.py +2453 -0
  202. unicode_logic_kit/mcp/syntax_spec.py +681 -0
  203. unicode_logic_kit/prob/__init__.py +53 -0
  204. unicode_logic_kit/prob/_bdd.py +225 -0
  205. unicode_logic_kit/prob/_column_gen.py +668 -0
  206. unicode_logic_kit/prob/distribution.py +686 -0
  207. unicode_logic_kit/prob/nilsson.py +470 -0
  208. unicode_logic_kit/py.typed +0 -0
  209. unicode_logic_kit/semantics/__init__.py +137 -0
  210. unicode_logic_kit/semantics/_modal_reject.py +156 -0
  211. unicode_logic_kit/semantics/action_models.py +466 -0
  212. unicode_logic_kit/semantics/asp_models.py +1200 -0
  213. unicode_logic_kit/semantics/conditional.py +580 -0
  214. unicode_logic_kit/semantics/dynamic_epistemic.py +95 -0
  215. unicode_logic_kit/semantics/free_logic.py +913 -0
  216. unicode_logic_kit/semantics/fuzzy.py +384 -0
  217. unicode_logic_kit/semantics/fuzzy_kripke.py +442 -0
  218. unicode_logic_kit/semantics/intuitionistic.py +581 -0
  219. unicode_logic_kit/semantics/kripke.py +1139 -0
  220. unicode_logic_kit/semantics/manyvalued.py +580 -0
  221. unicode_logic_kit/semantics/matrix.py +342 -0
  222. unicode_logic_kit/semantics/model_eval.py +1135 -0
  223. unicode_logic_kit/semantics/modelfinder.py +1036 -0
  224. unicode_logic_kit/semantics/nonmonotonic.py +372 -0
  225. unicode_logic_kit/semantics/relevant.py +331 -0
  226. unicode_logic_kit/semantics/secondorder.py +657 -0
  227. unicode_logic_kit/semantics/structures.py +352 -0
  228. unicode_logic_kit/semantics/tarski.py +975 -0
  229. unicode_logic_kit/semantics/team.py +315 -0
  230. unicode_logic_kit/semantics/team_translation.py +416 -0
  231. unicode_logic_kit/semantics/thirdorder.py +358 -0
  232. unicode_logic_kit/semantics/tnorm.py +85 -0
  233. unicode_logic_kit/semantics/truthtable.py +201 -0
  234. unicode_logic_kit-0.31.0.dist-info/METADATA +333 -0
  235. unicode_logic_kit-0.31.0.dist-info/RECORD +237 -0
  236. unicode_logic_kit-0.31.0.dist-info/WHEEL +4 -0
  237. 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)