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,217 @@
|
|
|
1
|
+
r"""Deep + maximal-shallow + minimal-shallow embeddings of **propositional modal
|
|
2
|
+
logic** K, with machine-checked faithfulness proofs (the Benzmüller construction).
|
|
3
|
+
|
|
4
|
+
The emitted theory is self-contained and, with a local Isabelle/HOL, verifies end
|
|
5
|
+
to end: ``faithful1a/1b`` relate the deep and maximal-shallow embeddings,
|
|
6
|
+
``faithful2/3`` relate them to the minimal-shallow embedding in the fixed model
|
|
7
|
+
``(W := \<lambda>_. True, R := Racc, V := Vval)``, and ``sound_min`` records that the
|
|
8
|
+
minimal embedding is sound for deep validity. Each proof is a one-line
|
|
9
|
+
``induct`` — see :func:`modal_faithfulness_theory`.
|
|
10
|
+
|
|
11
|
+
The accessibility relation ``R`` is left arbitrary, so faithfulness holds for the
|
|
12
|
+
base logic K (and hence, a fortiori, under any frame conditions). Deciding
|
|
13
|
+
validity *under a specific frame* is the job of the quantified minimal embedding in
|
|
14
|
+
:mod:`unicode_logic_kit.hol.isabelle_modal`; this module is about the three
|
|
15
|
+
embeddings and the faithful bridges between them.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from typing import Optional
|
|
19
|
+
|
|
20
|
+
from unicode_logic_kit.fol.nodes import (
|
|
21
|
+
Node, Not, And, Or, Implies, Iff, Box, Diamond,
|
|
22
|
+
)
|
|
23
|
+
from ._common import AtomConsts, encode_deep, wrap_theory, formula_section
|
|
24
|
+
|
|
25
|
+
# --------------------------------------------------------------------------- #
|
|
26
|
+
# The verified theory body (everything between ``begin`` and ``end``).
|
|
27
|
+
#
|
|
28
|
+
# This text is checked verbatim by the Isabelle-gated tests: exit 0 from
|
|
29
|
+
# ``check_theory`` means Isabelle's kernel discharged all five faithfulness
|
|
30
|
+
# theorems. Do not edit a clause without re-running that check — the ``induct``
|
|
31
|
+
# proofs depend on the exact operator definitions and the ``maxdefs`` / ``mindefs``
|
|
32
|
+
# simp bundles.
|
|
33
|
+
# --------------------------------------------------------------------------- #
|
|
34
|
+
|
|
35
|
+
_MODAL_BODY = r'''typedecl w \<comment> \<open>worlds\<close>
|
|
36
|
+
typedecl s \<comment> \<open>signature: propositional symbols (shared by all three embeddings)\<close>
|
|
37
|
+
type_synonym wset = "w \<Rightarrow> bool" \<comment> \<open>a set of worlds W\<close>
|
|
38
|
+
type_synonym acc = "w \<Rightarrow> w \<Rightarrow> bool" \<comment> \<open>accessibility relation R\<close>
|
|
39
|
+
type_synonym val = "s \<Rightarrow> w \<Rightarrow> bool" \<comment> \<open>valuation V\<close>
|
|
40
|
+
|
|
41
|
+
section \<open>Deep embedding: object syntax as a datatype + recursive truth\<close>
|
|
42
|
+
|
|
43
|
+
datatype pml =
|
|
44
|
+
Atm s | TopD | BotD
|
|
45
|
+
| NegD pml | AndD pml pml | OrD pml pml | ImpD pml pml | IffD pml pml
|
|
46
|
+
| BoxD pml | DiaD pml
|
|
47
|
+
|
|
48
|
+
primrec truthD :: "wset \<Rightarrow> acc \<Rightarrow> val \<Rightarrow> w \<Rightarrow> pml \<Rightarrow> bool" where
|
|
49
|
+
"truthD W R V x (Atm p) = V p x"
|
|
50
|
+
| "truthD W R V x TopD = True"
|
|
51
|
+
| "truthD W R V x BotD = False"
|
|
52
|
+
| "truthD W R V x (NegD f) = (\<not> truthD W R V x f)"
|
|
53
|
+
| "truthD W R V x (AndD f g) = (truthD W R V x f \<and> truthD W R V x g)"
|
|
54
|
+
| "truthD W R V x (OrD f g) = (truthD W R V x f \<or> truthD W R V x g)"
|
|
55
|
+
| "truthD W R V x (ImpD f g) = (truthD W R V x f \<longrightarrow> truthD W R V x g)"
|
|
56
|
+
| "truthD W R V x (IffD f g) = (truthD W R V x f = truthD W R V x g)"
|
|
57
|
+
| "truthD W R V x (BoxD f) = (\<forall>y. R x y \<longrightarrow> truthD W R V y f)"
|
|
58
|
+
| "truthD W R V x (DiaD f) = (\<exists>y. R x y \<and> truthD W R V y f)"
|
|
59
|
+
|
|
60
|
+
definition validD :: "pml \<Rightarrow> bool" where
|
|
61
|
+
"validD f \<equiv> \<forall>W R V. \<forall>x. W x \<longrightarrow> truthD W R V x f"
|
|
62
|
+
|
|
63
|
+
section \<open>Maximal (heavyweight) shallow embedding: every parameter explicit\<close>
|
|
64
|
+
|
|
65
|
+
type_synonym sigma = "wset \<Rightarrow> acc \<Rightarrow> val \<Rightarrow> w \<Rightarrow> bool"
|
|
66
|
+
definition AtmS :: "s \<Rightarrow> sigma" where "AtmS p \<equiv> \<lambda>W R V x. V p x"
|
|
67
|
+
definition TopS :: "sigma" where "TopS \<equiv> \<lambda>W R V x. True"
|
|
68
|
+
definition BotS :: "sigma" where "BotS \<equiv> \<lambda>W R V x. False"
|
|
69
|
+
definition NegS :: "sigma \<Rightarrow> sigma" where "NegS f \<equiv> \<lambda>W R V x. \<not> f W R V x"
|
|
70
|
+
definition AndS :: "sigma \<Rightarrow> sigma \<Rightarrow> sigma" where
|
|
71
|
+
"AndS f g \<equiv> \<lambda>W R V x. f W R V x \<and> g W R V x"
|
|
72
|
+
definition OrS :: "sigma \<Rightarrow> sigma \<Rightarrow> sigma" where
|
|
73
|
+
"OrS f g \<equiv> \<lambda>W R V x. f W R V x \<or> g W R V x"
|
|
74
|
+
definition ImpS :: "sigma \<Rightarrow> sigma \<Rightarrow> sigma" where
|
|
75
|
+
"ImpS f g \<equiv> \<lambda>W R V x. f W R V x \<longrightarrow> g W R V x"
|
|
76
|
+
definition IffS :: "sigma \<Rightarrow> sigma \<Rightarrow> sigma" where
|
|
77
|
+
"IffS f g \<equiv> \<lambda>W R V x. f W R V x = g W R V x"
|
|
78
|
+
definition BoxS :: "sigma \<Rightarrow> sigma" where
|
|
79
|
+
"BoxS f \<equiv> \<lambda>W R V x. \<forall>y. R x y \<longrightarrow> f W R V y"
|
|
80
|
+
definition DiaS :: "sigma \<Rightarrow> sigma" where
|
|
81
|
+
"DiaS f \<equiv> \<lambda>W R V x. \<exists>y. R x y \<and> f W R V y"
|
|
82
|
+
definition validS :: "sigma \<Rightarrow> bool" where
|
|
83
|
+
"validS f \<equiv> \<forall>W R V. \<forall>x. W x \<longrightarrow> f W R V x"
|
|
84
|
+
|
|
85
|
+
section \<open>Minimal (lightweight) shallow embedding: R, V fixed as metalogical consts\<close>
|
|
86
|
+
|
|
87
|
+
consts Racc :: "acc"
|
|
88
|
+
consts Vval :: "val"
|
|
89
|
+
type_synonym tau = "w \<Rightarrow> bool"
|
|
90
|
+
definition AtmM :: "s \<Rightarrow> tau" where "AtmM p \<equiv> \<lambda>x. Vval p x"
|
|
91
|
+
definition TopM :: "tau" where "TopM \<equiv> \<lambda>x. True"
|
|
92
|
+
definition BotM :: "tau" where "BotM \<equiv> \<lambda>x. False"
|
|
93
|
+
definition NegM :: "tau \<Rightarrow> tau" where "NegM f \<equiv> \<lambda>x. \<not> f x"
|
|
94
|
+
definition AndM :: "tau \<Rightarrow> tau \<Rightarrow> tau" where "AndM f g \<equiv> \<lambda>x. f x \<and> g x"
|
|
95
|
+
definition OrM :: "tau \<Rightarrow> tau \<Rightarrow> tau" where "OrM f g \<equiv> \<lambda>x. f x \<or> g x"
|
|
96
|
+
definition ImpM :: "tau \<Rightarrow> tau \<Rightarrow> tau" where "ImpM f g \<equiv> \<lambda>x. f x \<longrightarrow> g x"
|
|
97
|
+
definition IffM :: "tau \<Rightarrow> tau \<Rightarrow> tau" where "IffM f g \<equiv> \<lambda>x. f x = g x"
|
|
98
|
+
definition BoxM :: "tau \<Rightarrow> tau" where "BoxM f \<equiv> \<lambda>x. \<forall>y. Racc x y \<longrightarrow> f y"
|
|
99
|
+
definition DiaM :: "tau \<Rightarrow> tau" where "DiaM f \<equiv> \<lambda>x. \<exists>y. Racc x y \<and> f y"
|
|
100
|
+
definition validM :: "tau \<Rightarrow> bool" where "validM f \<equiv> \<forall>x. f x"
|
|
101
|
+
|
|
102
|
+
section \<open>Mappings between the embeddings\<close>
|
|
103
|
+
|
|
104
|
+
primrec dpToMax :: "pml \<Rightarrow> sigma" where
|
|
105
|
+
"dpToMax (Atm p) = AtmS p"
|
|
106
|
+
| "dpToMax TopD = TopS"
|
|
107
|
+
| "dpToMax BotD = BotS"
|
|
108
|
+
| "dpToMax (NegD f) = NegS (dpToMax f)"
|
|
109
|
+
| "dpToMax (AndD f g) = AndS (dpToMax f) (dpToMax g)"
|
|
110
|
+
| "dpToMax (OrD f g) = OrS (dpToMax f) (dpToMax g)"
|
|
111
|
+
| "dpToMax (ImpD f g) = ImpS (dpToMax f) (dpToMax g)"
|
|
112
|
+
| "dpToMax (IffD f g) = IffS (dpToMax f) (dpToMax g)"
|
|
113
|
+
| "dpToMax (BoxD f) = BoxS (dpToMax f)"
|
|
114
|
+
| "dpToMax (DiaD f) = DiaS (dpToMax f)"
|
|
115
|
+
|
|
116
|
+
primrec dpToMin :: "pml \<Rightarrow> tau" where
|
|
117
|
+
"dpToMin (Atm p) = AtmM p"
|
|
118
|
+
| "dpToMin TopD = TopM"
|
|
119
|
+
| "dpToMin BotD = BotM"
|
|
120
|
+
| "dpToMin (NegD f) = NegM (dpToMin f)"
|
|
121
|
+
| "dpToMin (AndD f g) = AndM (dpToMin f) (dpToMin g)"
|
|
122
|
+
| "dpToMin (OrD f g) = OrM (dpToMin f) (dpToMin g)"
|
|
123
|
+
| "dpToMin (ImpD f g) = ImpM (dpToMin f) (dpToMin g)"
|
|
124
|
+
| "dpToMin (IffD f g) = IffM (dpToMin f) (dpToMin g)"
|
|
125
|
+
| "dpToMin (BoxD f) = BoxM (dpToMin f)"
|
|
126
|
+
| "dpToMin (DiaD f) = DiaM (dpToMin f)"
|
|
127
|
+
|
|
128
|
+
section \<open>Faithfulness (machine-checked by Isabelle's kernel)\<close>
|
|
129
|
+
|
|
130
|
+
lemmas maxdefs = AtmS_def TopS_def BotS_def NegS_def AndS_def OrS_def
|
|
131
|
+
ImpS_def IffS_def BoxS_def DiaS_def
|
|
132
|
+
lemmas mindefs = AtmM_def TopM_def BotM_def NegM_def AndM_def OrM_def
|
|
133
|
+
ImpM_def IffM_def BoxM_def DiaM_def
|
|
134
|
+
|
|
135
|
+
text \<open>Deep truth coincides pointwise with maximal-shallow truth.\<close>
|
|
136
|
+
theorem faithful1a: "truthD W R V x f = dpToMax f W R V x"
|
|
137
|
+
by (induct f arbitrary: x) (simp_all add: maxdefs)
|
|
138
|
+
|
|
139
|
+
text \<open>Hence deep validity coincides with maximal-shallow validity.\<close>
|
|
140
|
+
theorem faithful1b: "validD f = validS (dpToMax f)"
|
|
141
|
+
by (simp add: validD_def validS_def faithful1a)
|
|
142
|
+
|
|
143
|
+
text \<open>Deep truth in the fixed model coincides with minimal-shallow truth.\<close>
|
|
144
|
+
theorem faithful2: "truthD (\<lambda>_. True) Racc Vval x f = dpToMin f x"
|
|
145
|
+
by (induct f arbitrary: x) (simp_all add: mindefs)
|
|
146
|
+
|
|
147
|
+
text \<open>Maximal- and minimal-shallow truth coincide in that fixed model.\<close>
|
|
148
|
+
theorem faithful3: "dpToMax f (\<lambda>_. True) Racc Vval x = dpToMin f x"
|
|
149
|
+
by (induct f arbitrary: x) (simp_all add: maxdefs mindefs)
|
|
150
|
+
|
|
151
|
+
text \<open>Soundness of the minimal embedding for deep validity.\<close>
|
|
152
|
+
theorem sound_min: "validD f \<Longrightarrow> validM (dpToMin f)"
|
|
153
|
+
proof -
|
|
154
|
+
assume *: "validD f"
|
|
155
|
+
have "truthD (\<lambda>_. True) Racc Vval x f" for x
|
|
156
|
+
using * by (simp add: validD_def)
|
|
157
|
+
then show "validM (dpToMin f)"
|
|
158
|
+
by (simp add: validM_def faithful2)
|
|
159
|
+
qed'''
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
# --------------------------------------------------------------------------- #
|
|
163
|
+
# Encoder: toolkit modal AST -> deep ``pml`` term.
|
|
164
|
+
# --------------------------------------------------------------------------- #
|
|
165
|
+
|
|
166
|
+
# Node type -> (deep constructor, arity). Xor desugars to NegD (IffD ...).
|
|
167
|
+
_CTORS = {
|
|
168
|
+
Not: ("NegD", 1), And: ("AndD", 2), Or: ("OrD", 2),
|
|
169
|
+
Implies: ("ImpD", 2), Iff: ("IffD", 2),
|
|
170
|
+
Box: ("BoxD", 1), Diamond: ("DiaD", 1),
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def modal_to_deep(formula: Node, atoms: AtomConsts) -> str:
|
|
175
|
+
r"""Encode a **propositional** modal formula as a deep ``pml`` term.
|
|
176
|
+
|
|
177
|
+
Each distinct ground atom becomes a propositional symbol constant of type ``s``
|
|
178
|
+
(collected into ``atoms``); connectives map to the ``pml`` constructors and
|
|
179
|
+
``Xor`` desugars to ``NegD (IffD ...)``. Raises :class:`NotImplementedError` if
|
|
180
|
+
the formula is genuinely first-order (contains a quantifier or a variable) — the
|
|
181
|
+
deep embedding is propositional; use :mod:`unicode_logic_kit.hol.isabelle_modal`
|
|
182
|
+
for the quantified fragment.
|
|
183
|
+
"""
|
|
184
|
+
return encode_deep(formula, atoms, _CTORS, logic="modal_to_deep")
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
# --------------------------------------------------------------------------- #
|
|
188
|
+
# Public entry points.
|
|
189
|
+
# --------------------------------------------------------------------------- #
|
|
190
|
+
|
|
191
|
+
def modal_faithfulness_theory(
|
|
192
|
+
theory_name: str = "ModalFaithfulness",
|
|
193
|
+
formula: Optional[Node] = None,
|
|
194
|
+
) -> str:
|
|
195
|
+
r"""Emit the self-contained modal deep/maximal/minimal + faithfulness theory.
|
|
196
|
+
|
|
197
|
+
The returned string is a full ``theory <theory_name> imports Main begin ... end``
|
|
198
|
+
containing the three embeddings and the five faithfulness theorems, each closed
|
|
199
|
+
by Isabelle. With a local Isabelle/HOL it is verified end to end by
|
|
200
|
+
:func:`unicode_logic_kit.hol.isabelle_runner.check_theory`.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
theory_name: the Isabelle theory / file name (a legal identifier).
|
|
204
|
+
formula: an optional **propositional** modal formula. When given, its deep
|
|
205
|
+
encoding is appended as ``definition example :: pml`` (with ``consts`` for
|
|
206
|
+
its atoms), so the certificate is grounded in a concrete formula and the
|
|
207
|
+
faithfulness theorems specialise to it.
|
|
208
|
+
|
|
209
|
+
Returns:
|
|
210
|
+
The theory text (newline-terminated).
|
|
211
|
+
"""
|
|
212
|
+
extra = ""
|
|
213
|
+
if formula is not None:
|
|
214
|
+
atoms = AtomConsts()
|
|
215
|
+
term = modal_to_deep(formula, atoms)
|
|
216
|
+
extra = formula_section(term, atoms, "pml")
|
|
217
|
+
return wrap_theory(theory_name, _MODAL_BODY, extra)
|
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
r"""Deep + maximal-shallow + minimal-shallow embeddings of **quantified** modal logic
|
|
2
|
+
(QML), Tier 2 — scoped to the base frame K, the CONSTANT domain regime only, and
|
|
3
|
+
the alethic ``□``/``◇`` modalities, with machine-checked faithfulness proofs.
|
|
4
|
+
|
|
5
|
+
This is the binder-carrying sibling of :mod:`unicode_logic_kit.hol.deepshallow.modal`:
|
|
6
|
+
where Tier 1 embeds *propositional* logics (no quantifiers, so induction over the
|
|
7
|
+
syntax datatype is the whole story), this module embeds a genuinely *quantified*
|
|
8
|
+
one. Object variables are represented **de Bruijn-indexed** (``obj = BVar nat |
|
|
9
|
+
FVar s``, ``FVar`` naming a rigid object CONSTANT) rather than by name, which is
|
|
10
|
+
what lets ``truthD`` be a plain ``primrec`` with no separate capture-avoiding
|
|
11
|
+
substitution: a bound variable is interpreted by looking up its index in an
|
|
12
|
+
explicit assignment stack ``env = nat ⇒ i``, and going under ``∀``/``∃`` simply
|
|
13
|
+
*prepends* one entry to that stack (``case_nat d e``, Isabelle's standard ``nat``
|
|
14
|
+
case-combinator). Every faithfulness theorem below is still a **one-line
|
|
15
|
+
``induct``** — the "extra step" a binder-carrying structural induction needs,
|
|
16
|
+
beyond Tier 1's ``induct f arbitrary: x``, is generalizing the environment too
|
|
17
|
+
(``induct f arbitrary: e x``), so the induction hypothesis is available at the
|
|
18
|
+
*shifted* environment each quantifier clause recurses into.
|
|
19
|
+
|
|
20
|
+
The domain is a single set ``D :: i ⇒ bool`` shared by every world (the constant-
|
|
21
|
+
domain simplification) rather than a family ``D_w`` indexed by world — this is
|
|
22
|
+
what makes "K + constant domain" a fact about the **types**, not a runtime
|
|
23
|
+
frame/mode parameter to check and possibly reject: there is no way to *ask* this
|
|
24
|
+
module for a varying/increasing/decreasing domain or a T/S4/S5 frame, unlike
|
|
25
|
+
:mod:`unicode_logic_kit.hol.isabelle_modal` (which offers all four domain regimes,
|
|
26
|
+
every named frame, and the whole non-counterfactual modal family). ``R`` is left
|
|
27
|
+
completely arbitrary — as in :mod:`~unicode_logic_kit.hol.deepshallow.modal`, this
|
|
28
|
+
is what makes faithfulness hold for base K (and so, a fortiori, under any *stronger*
|
|
29
|
+
frame conditions one might separately assert on top of it — this module simply
|
|
30
|
+
never does).
|
|
31
|
+
|
|
32
|
+
Deliberately out of scope (raise :class:`NotImplementedError` **naming the
|
|
33
|
+
construct**, not approximated): equality/disequality (``=``/``≠``), function terms
|
|
34
|
+
(only object variables and 0-ary constants are terms here), and every operator
|
|
35
|
+
outside alethic ``□``/``◇`` — epistemic ``K_a``/doxastic ``B_a``/assertive/
|
|
36
|
+
bouletic, deontic ``Ⓞ``/``Ⓟ``, the whole temporal family, hybrid nominals/``@``,
|
|
37
|
+
and many-sorted ``SortedQuantifier``/``SortedConstant``. Use
|
|
38
|
+
:mod:`unicode_logic_kit.hol.isabelle_modal` / :mod:`unicode_logic_kit.hol.thf_modal`
|
|
39
|
+
for any of those — this module trades their breadth for a genuine, machine-checked
|
|
40
|
+
**meta-theorem** relating three embeddings of the fragment it does cover.
|
|
41
|
+
|
|
42
|
+
Public API: :func:`qml_to_deep`, :func:`qml_deep_faithfulness_theory`.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
from typing import List, Optional
|
|
46
|
+
|
|
47
|
+
from unicode_logic_kit.fol.nodes import (
|
|
48
|
+
Node, Atom, Not, And, Or, Implies, Iff, Box, Diamond, Quantifier,
|
|
49
|
+
Variable, Constant,
|
|
50
|
+
)
|
|
51
|
+
from unicode_logic_kit.fol._truth_constants import refuse_truth_constants
|
|
52
|
+
from ._common import AtomConsts, wrap_theory, NO_CONSTANT_WHY
|
|
53
|
+
|
|
54
|
+
# --------------------------------------------------------------------------- #
|
|
55
|
+
# The verified theory body (everything between ``begin`` and ``end``).
|
|
56
|
+
#
|
|
57
|
+
# This text is checked verbatim by the Isabelle-gated tests: exit 0 from
|
|
58
|
+
# ``check_theory`` means Isabelle's kernel discharged all five faithfulness
|
|
59
|
+
# theorems. Do not edit a clause without re-running that check — the ``induct``
|
|
60
|
+
# proofs depend on the exact operator definitions and the ``maxdefs`` / ``mindefs``
|
|
61
|
+
# simp bundles, exactly as in ``modal.py``.
|
|
62
|
+
# --------------------------------------------------------------------------- #
|
|
63
|
+
|
|
64
|
+
_QML_BODY = r'''typedecl w \<comment> \<open>worlds\<close>
|
|
65
|
+
typedecl i \<comment> \<open>individuals: the ONE constant domain shared by every world\<close>
|
|
66
|
+
typedecl s \<comment> \<open>signature: predicate symbols and object-constant symbols\<close>
|
|
67
|
+
type_synonym wset = "w \<Rightarrow> bool" \<comment> \<open>a set of worlds W\<close>
|
|
68
|
+
type_synonym dom = "i \<Rightarrow> bool" \<comment> \<open>the constant domain D\<close>
|
|
69
|
+
type_synonym acc = "w \<Rightarrow> w \<Rightarrow> bool" \<comment> \<open>accessibility relation R\<close>
|
|
70
|
+
type_synonym val = "s \<Rightarrow> i list \<Rightarrow> w \<Rightarrow> bool" \<comment> \<open>valuation V\<close>
|
|
71
|
+
type_synonym cint = "s \<Rightarrow> i" \<comment> \<open>rigid interpretation of object constants\<close>
|
|
72
|
+
type_synonym env = "nat \<Rightarrow> i" \<comment> \<open>de Bruijn assignment stack\<close>
|
|
73
|
+
|
|
74
|
+
section \<open>Object terms: de Bruijn-indexed bound variables plus rigid constants\<close>
|
|
75
|
+
|
|
76
|
+
datatype obj = BVar nat | FVar s
|
|
77
|
+
|
|
78
|
+
primrec objD :: "env \<Rightarrow> cint \<Rightarrow> obj \<Rightarrow> i" where
|
|
79
|
+
"objD e c (BVar n) = e n"
|
|
80
|
+
| "objD e c (FVar a) = c a"
|
|
81
|
+
|
|
82
|
+
section \<open>Deep embedding: object syntax as a datatype + recursive truth\<close>
|
|
83
|
+
|
|
84
|
+
datatype qml =
|
|
85
|
+
Atm s "obj list" | TopD | BotD
|
|
86
|
+
| NegD qml | AndD qml qml | OrD qml qml | ImpD qml qml | IffD qml qml
|
|
87
|
+
| BoxD qml | DiaD qml
|
|
88
|
+
| AllD qml | ExD qml
|
|
89
|
+
|
|
90
|
+
primrec truthD :: "env \<Rightarrow> cint \<Rightarrow> wset \<Rightarrow> acc \<Rightarrow> dom \<Rightarrow> val \<Rightarrow> w \<Rightarrow> qml \<Rightarrow> bool" where
|
|
91
|
+
"truthD e c W R D V x (Atm p args) = V p (map (objD e c) args) x"
|
|
92
|
+
| "truthD e c W R D V x TopD = True"
|
|
93
|
+
| "truthD e c W R D V x BotD = False"
|
|
94
|
+
| "truthD e c W R D V x (NegD f) = (\<not> truthD e c W R D V x f)"
|
|
95
|
+
| "truthD e c W R D V x (AndD f g) = (truthD e c W R D V x f \<and> truthD e c W R D V x g)"
|
|
96
|
+
| "truthD e c W R D V x (OrD f g) = (truthD e c W R D V x f \<or> truthD e c W R D V x g)"
|
|
97
|
+
| "truthD e c W R D V x (ImpD f g) = (truthD e c W R D V x f \<longrightarrow> truthD e c W R D V x g)"
|
|
98
|
+
| "truthD e c W R D V x (IffD f g) = (truthD e c W R D V x f = truthD e c W R D V x g)"
|
|
99
|
+
| "truthD e c W R D V x (BoxD f) = (\<forall>y. R x y \<longrightarrow> truthD e c W R D V y f)"
|
|
100
|
+
| "truthD e c W R D V x (DiaD f) = (\<exists>y. R x y \<and> truthD e c W R D V y f)"
|
|
101
|
+
| "truthD e c W R D V x (AllD f) = (\<forall>d. D d \<longrightarrow> truthD (case_nat d e) c W R D V x f)"
|
|
102
|
+
| "truthD e c W R D V x (ExD f) = (\<exists>d. D d \<and> truthD (case_nat d e) c W R D V x f)"
|
|
103
|
+
|
|
104
|
+
definition validD :: "qml \<Rightarrow> bool" where
|
|
105
|
+
"validD f \<equiv> \<forall>e c W R D V x. W x \<longrightarrow> truthD e c W R D V x f"
|
|
106
|
+
|
|
107
|
+
section \<open>Maximal (heavyweight) shallow embedding: every parameter explicit\<close>
|
|
108
|
+
|
|
109
|
+
type_synonym sigma = "env \<Rightarrow> cint \<Rightarrow> wset \<Rightarrow> acc \<Rightarrow> dom \<Rightarrow> val \<Rightarrow> w \<Rightarrow> bool"
|
|
110
|
+
|
|
111
|
+
definition AtmS :: "s \<Rightarrow> obj list \<Rightarrow> sigma" where
|
|
112
|
+
"AtmS p args \<equiv> \<lambda>e c W R D V x. V p (map (objD e c) args) x"
|
|
113
|
+
definition TopS :: "sigma" where "TopS \<equiv> \<lambda>e c W R D V x. True"
|
|
114
|
+
definition BotS :: "sigma" where "BotS \<equiv> \<lambda>e c W R D V x. False"
|
|
115
|
+
definition NegS :: "sigma \<Rightarrow> sigma" where
|
|
116
|
+
"NegS f \<equiv> \<lambda>e c W R D V x. \<not> f e c W R D V x"
|
|
117
|
+
definition AndS :: "sigma \<Rightarrow> sigma \<Rightarrow> sigma" where
|
|
118
|
+
"AndS f g \<equiv> \<lambda>e c W R D V x. f e c W R D V x \<and> g e c W R D V x"
|
|
119
|
+
definition OrS :: "sigma \<Rightarrow> sigma \<Rightarrow> sigma" where
|
|
120
|
+
"OrS f g \<equiv> \<lambda>e c W R D V x. f e c W R D V x \<or> g e c W R D V x"
|
|
121
|
+
definition ImpS :: "sigma \<Rightarrow> sigma \<Rightarrow> sigma" where
|
|
122
|
+
"ImpS f g \<equiv> \<lambda>e c W R D V x. f e c W R D V x \<longrightarrow> g e c W R D V x"
|
|
123
|
+
definition IffS :: "sigma \<Rightarrow> sigma \<Rightarrow> sigma" where
|
|
124
|
+
"IffS f g \<equiv> \<lambda>e c W R D V x. f e c W R D V x = g e c W R D V x"
|
|
125
|
+
definition BoxS :: "sigma \<Rightarrow> sigma" where
|
|
126
|
+
"BoxS f \<equiv> \<lambda>e c W R D V x. \<forall>y. R x y \<longrightarrow> f e c W R D V y"
|
|
127
|
+
definition DiaS :: "sigma \<Rightarrow> sigma" where
|
|
128
|
+
"DiaS f \<equiv> \<lambda>e c W R D V x. \<exists>y. R x y \<and> f e c W R D V y"
|
|
129
|
+
definition AllS :: "sigma \<Rightarrow> sigma" where
|
|
130
|
+
"AllS f \<equiv> \<lambda>e c W R D V x. \<forall>d. D d \<longrightarrow> f (case_nat d e) c W R D V x"
|
|
131
|
+
definition ExS :: "sigma \<Rightarrow> sigma" where
|
|
132
|
+
"ExS f \<equiv> \<lambda>e c W R D V x. \<exists>d. D d \<and> f (case_nat d e) c W R D V x"
|
|
133
|
+
definition validS :: "sigma \<Rightarrow> bool" where
|
|
134
|
+
"validS f \<equiv> \<forall>e c W R D V x. W x \<longrightarrow> f e c W R D V x"
|
|
135
|
+
|
|
136
|
+
section \<open>Minimal (lightweight) shallow embedding: R, D, V, C fixed as metalogical consts\<close>
|
|
137
|
+
|
|
138
|
+
consts Racc :: "acc"
|
|
139
|
+
consts Dset :: "dom"
|
|
140
|
+
consts Vval :: "val"
|
|
141
|
+
consts Cint :: "cint"
|
|
142
|
+
type_synonym tau = "env \<Rightarrow> w \<Rightarrow> bool"
|
|
143
|
+
|
|
144
|
+
definition AtmM :: "s \<Rightarrow> obj list \<Rightarrow> tau" where
|
|
145
|
+
"AtmM p args \<equiv> \<lambda>e x. Vval p (map (objD e Cint) args) x"
|
|
146
|
+
definition TopM :: "tau" where "TopM \<equiv> \<lambda>e x. True"
|
|
147
|
+
definition BotM :: "tau" where "BotM \<equiv> \<lambda>e x. False"
|
|
148
|
+
definition NegM :: "tau \<Rightarrow> tau" where "NegM f \<equiv> \<lambda>e x. \<not> f e x"
|
|
149
|
+
definition AndM :: "tau \<Rightarrow> tau \<Rightarrow> tau" where "AndM f g \<equiv> \<lambda>e x. f e x \<and> g e x"
|
|
150
|
+
definition OrM :: "tau \<Rightarrow> tau \<Rightarrow> tau" where "OrM f g \<equiv> \<lambda>e x. f e x \<or> g e x"
|
|
151
|
+
definition ImpM :: "tau \<Rightarrow> tau \<Rightarrow> tau" where "ImpM f g \<equiv> \<lambda>e x. f e x \<longrightarrow> g e x"
|
|
152
|
+
definition IffM :: "tau \<Rightarrow> tau \<Rightarrow> tau" where "IffM f g \<equiv> \<lambda>e x. f e x = g e x"
|
|
153
|
+
definition BoxM :: "tau \<Rightarrow> tau" where "BoxM f \<equiv> \<lambda>e x. \<forall>y. Racc x y \<longrightarrow> f e y"
|
|
154
|
+
definition DiaM :: "tau \<Rightarrow> tau" where "DiaM f \<equiv> \<lambda>e x. \<exists>y. Racc x y \<and> f e y"
|
|
155
|
+
definition AllM :: "tau \<Rightarrow> tau" where
|
|
156
|
+
"AllM f \<equiv> \<lambda>e x. \<forall>d. Dset d \<longrightarrow> f (case_nat d e) x"
|
|
157
|
+
definition ExM :: "tau \<Rightarrow> tau" where
|
|
158
|
+
"ExM f \<equiv> \<lambda>e x. \<exists>d. Dset d \<and> f (case_nat d e) x"
|
|
159
|
+
definition validM :: "tau \<Rightarrow> bool" where "validM f \<equiv> \<forall>e x. f e x"
|
|
160
|
+
|
|
161
|
+
section \<open>Mappings between the embeddings\<close>
|
|
162
|
+
|
|
163
|
+
primrec dpToMax :: "qml \<Rightarrow> sigma" where
|
|
164
|
+
"dpToMax (Atm p args) = AtmS p args"
|
|
165
|
+
| "dpToMax TopD = TopS"
|
|
166
|
+
| "dpToMax BotD = BotS"
|
|
167
|
+
| "dpToMax (NegD f) = NegS (dpToMax f)"
|
|
168
|
+
| "dpToMax (AndD f g) = AndS (dpToMax f) (dpToMax g)"
|
|
169
|
+
| "dpToMax (OrD f g) = OrS (dpToMax f) (dpToMax g)"
|
|
170
|
+
| "dpToMax (ImpD f g) = ImpS (dpToMax f) (dpToMax g)"
|
|
171
|
+
| "dpToMax (IffD f g) = IffS (dpToMax f) (dpToMax g)"
|
|
172
|
+
| "dpToMax (BoxD f) = BoxS (dpToMax f)"
|
|
173
|
+
| "dpToMax (DiaD f) = DiaS (dpToMax f)"
|
|
174
|
+
| "dpToMax (AllD f) = AllS (dpToMax f)"
|
|
175
|
+
| "dpToMax (ExD f) = ExS (dpToMax f)"
|
|
176
|
+
|
|
177
|
+
primrec dpToMin :: "qml \<Rightarrow> tau" where
|
|
178
|
+
"dpToMin (Atm p args) = AtmM p args"
|
|
179
|
+
| "dpToMin TopD = TopM"
|
|
180
|
+
| "dpToMin BotD = BotM"
|
|
181
|
+
| "dpToMin (NegD f) = NegM (dpToMin f)"
|
|
182
|
+
| "dpToMin (AndD f g) = AndM (dpToMin f) (dpToMin g)"
|
|
183
|
+
| "dpToMin (OrD f g) = OrM (dpToMin f) (dpToMin g)"
|
|
184
|
+
| "dpToMin (ImpD f g) = ImpM (dpToMin f) (dpToMin g)"
|
|
185
|
+
| "dpToMin (IffD f g) = IffM (dpToMin f) (dpToMin g)"
|
|
186
|
+
| "dpToMin (BoxD f) = BoxM (dpToMin f)"
|
|
187
|
+
| "dpToMin (DiaD f) = DiaM (dpToMin f)"
|
|
188
|
+
| "dpToMin (AllD f) = AllM (dpToMin f)"
|
|
189
|
+
| "dpToMin (ExD f) = ExM (dpToMin f)"
|
|
190
|
+
|
|
191
|
+
section \<open>Faithfulness (machine-checked by Isabelle's kernel)\<close>
|
|
192
|
+
|
|
193
|
+
lemmas maxdefs = AtmS_def TopS_def BotS_def NegS_def AndS_def OrS_def
|
|
194
|
+
ImpS_def IffS_def BoxS_def DiaS_def AllS_def ExS_def
|
|
195
|
+
lemmas mindefs = AtmM_def TopM_def BotM_def NegM_def AndM_def OrM_def
|
|
196
|
+
ImpM_def IffM_def BoxM_def DiaM_def AllM_def ExM_def
|
|
197
|
+
|
|
198
|
+
text \<open>Deep truth coincides pointwise with maximal-shallow truth. The extra
|
|
199
|
+
generalization beyond the propositional Tier 1 proofs (``arbitrary: e`` alongside
|
|
200
|
+
``x``) is exactly the "binder-carrying structural induction" step: it makes the
|
|
201
|
+
induction hypothesis available at the SHIFTED environment ``case_nat d e`` each
|
|
202
|
+
``AllD``/``ExD`` clause recurses into.\<close>
|
|
203
|
+
theorem faithful1a: "truthD e c W R D V x f = dpToMax f e c W R D V x"
|
|
204
|
+
by (induct f arbitrary: e x) (simp_all add: maxdefs)
|
|
205
|
+
|
|
206
|
+
text \<open>Hence deep validity coincides with maximal-shallow validity.\<close>
|
|
207
|
+
theorem faithful1b: "validD f = validS (dpToMax f)"
|
|
208
|
+
by (simp add: validD_def validS_def faithful1a)
|
|
209
|
+
|
|
210
|
+
text \<open>Deep truth in the fixed model coincides with minimal-shallow truth.\<close>
|
|
211
|
+
theorem faithful2: "truthD e Cint (\<lambda>_. True) Racc Dset Vval x f = dpToMin f e x"
|
|
212
|
+
by (induct f arbitrary: e x) (simp_all add: mindefs)
|
|
213
|
+
|
|
214
|
+
text \<open>Maximal- and minimal-shallow truth coincide in that fixed model.\<close>
|
|
215
|
+
theorem faithful3: "dpToMax f e Cint (\<lambda>_. True) Racc Dset Vval x = dpToMin f e x"
|
|
216
|
+
by (induct f arbitrary: e x) (simp_all add: maxdefs mindefs)
|
|
217
|
+
|
|
218
|
+
text \<open>Soundness of the minimal embedding for deep validity.\<close>
|
|
219
|
+
theorem sound_min: "validD f \<Longrightarrow> validM (dpToMin f)"
|
|
220
|
+
proof -
|
|
221
|
+
assume *: "validD f"
|
|
222
|
+
have "truthD e Cint (\<lambda>_. True) Racc Dset Vval x f" for e x
|
|
223
|
+
using * by (simp add: validD_def)
|
|
224
|
+
then show "validM (dpToMin f)"
|
|
225
|
+
by (simp add: validM_def faithful2)
|
|
226
|
+
qed'''
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
# --------------------------------------------------------------------------- #
|
|
230
|
+
# Encoder: toolkit QML AST -> deep ``qml`` term (de Bruijn-indexed).
|
|
231
|
+
# --------------------------------------------------------------------------- #
|
|
232
|
+
|
|
233
|
+
# Node type -> (deep constructor, arity 1 or 2). Quantifiers and Box/Diamond are
|
|
234
|
+
# handled separately below (they thread the bound-variable stack / recurse on
|
|
235
|
+
# ``.formula`` under a differently-named constructor).
|
|
236
|
+
_CONNECTIVES = {
|
|
237
|
+
Not: ("NegD", 1), And: ("AndD", 2), Or: ("OrD", 2),
|
|
238
|
+
Implies: ("ImpD", 2), Iff: ("IffD", 2),
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
_EQUALITY_PREDS = frozenset({"=", "≠"})
|
|
242
|
+
|
|
243
|
+
_UNSUPPORTED_HINT = (
|
|
244
|
+
"this deep embedding is scoped to K + constant domain + alethic □/◇ "
|
|
245
|
+
"only (Tier 2 of hol.deepshallow) — no epistemic/doxastic/assertive/"
|
|
246
|
+
"bouletic, deontic, temporal, hybrid or many-sorted operators, no equality, "
|
|
247
|
+
"no function terms. Use hol.isabelle_modal.to_isabelle_modal / "
|
|
248
|
+
"hol.thf_modal.to_thf_modal_full for the full modal family and the other "
|
|
249
|
+
"three domain regimes."
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def _obj_to_deep(term: Node, bound: List[str], consts: AtomConsts) -> str:
|
|
254
|
+
"""Encode an object TERM as a deep ``obj`` value: ``BVar`` (de Bruijn index
|
|
255
|
+
into ``bound``, innermost binder = index 0) or ``FVar`` (a rigid constant).
|
|
256
|
+
|
|
257
|
+
``bound`` lists the quantifiers currently in scope, outermost first, so a
|
|
258
|
+
shadowed name resolves to the innermost (most recently pushed) binder —
|
|
259
|
+
exactly the de Bruijn convention ``truthD``'s ``AllD``/``ExD`` clauses
|
|
260
|
+
implement via ``case_nat``. A free (unbound) :class:`Variable` is refused:
|
|
261
|
+
this deep embedding requires a closed formula, every object variable bound
|
|
262
|
+
by some ``∀``/``∃`` in the formula itself.
|
|
263
|
+
"""
|
|
264
|
+
if isinstance(term, Variable):
|
|
265
|
+
if term.name not in bound:
|
|
266
|
+
raise NotImplementedError(
|
|
267
|
+
f"qml_to_deep: free variable {term.name!r} is not bound by any "
|
|
268
|
+
"quantifier in the formula — the deep embedding requires a "
|
|
269
|
+
"closed formula (every object variable bound).")
|
|
270
|
+
idx = bound[::-1].index(term.name)
|
|
271
|
+
return f"(BVar {idx})"
|
|
272
|
+
if isinstance(term, Constant):
|
|
273
|
+
return f"(FVar {consts.name(term.name)})"
|
|
274
|
+
raise NotImplementedError(
|
|
275
|
+
f"qml_to_deep: unsupported term {type(term).__name__} — this "
|
|
276
|
+
"fragment has object variables and 0-ary constants only (no function "
|
|
277
|
+
f"terms, no Number literals). {_UNSUPPORTED_HINT}")
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def _encode(node: Node, bound: List[str], atoms: AtomConsts, consts: AtomConsts) -> str:
|
|
281
|
+
"""Encode a **K + constant-domain + alethic** QML formula as a deep ``qml`` term."""
|
|
282
|
+
if isinstance(node, Atom):
|
|
283
|
+
refuse_truth_constants([node], "qml_to_deep", NO_CONSTANT_WHY)
|
|
284
|
+
if node.predicate in _EQUALITY_PREDS:
|
|
285
|
+
raise NotImplementedError(
|
|
286
|
+
f"qml_to_deep: {node.predicate!r} (equality) is outside this "
|
|
287
|
+
f"fragment's scope, refused by name. {_UNSUPPORTED_HINT}")
|
|
288
|
+
objs = ", ".join(_obj_to_deep(a, bound, consts) for a in node.args)
|
|
289
|
+
return f"(Atm {atoms.name(node.predicate)} [{objs}])"
|
|
290
|
+
if isinstance(node, Box):
|
|
291
|
+
return f"(BoxD {_encode(node.formula, bound, atoms, consts)})"
|
|
292
|
+
if isinstance(node, Diamond):
|
|
293
|
+
return f"(DiaD {_encode(node.formula, bound, atoms, consts)})"
|
|
294
|
+
if isinstance(node, Quantifier):
|
|
295
|
+
inner = _encode(node.formula, bound + [node.variable.name], atoms, consts)
|
|
296
|
+
if node.type in ("∀", "forall"):
|
|
297
|
+
return f"(AllD {inner})"
|
|
298
|
+
if node.type in ("∃", "exists"):
|
|
299
|
+
return f"(ExD {inner})"
|
|
300
|
+
raise ValueError(f"qml_to_deep: unknown quantifier type {node.type!r}.")
|
|
301
|
+
spec = _CONNECTIVES.get(type(node))
|
|
302
|
+
if spec is not None:
|
|
303
|
+
name, arity = spec
|
|
304
|
+
if arity == 1:
|
|
305
|
+
return f"({name} {_encode(node.formula, bound, atoms, consts)})"
|
|
306
|
+
left = _encode(node.left, bound, atoms, consts)
|
|
307
|
+
right = _encode(node.right, bound, atoms, consts)
|
|
308
|
+
return f"({name} {left} {right})"
|
|
309
|
+
raise NotImplementedError(
|
|
310
|
+
f"qml_to_deep: unsupported node type {type(node).__name__}. "
|
|
311
|
+
f"{_UNSUPPORTED_HINT}")
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
def qml_to_deep(formula: Node, atoms: AtomConsts, consts: AtomConsts) -> str:
|
|
315
|
+
r"""Encode a **K + constant-domain + alethic □/◇** QML formula as a deep
|
|
316
|
+
``qml`` term (de Bruijn-indexed bound variables, ``FVar`` for constants).
|
|
317
|
+
|
|
318
|
+
``atoms`` collects PREDICATE-symbol constants, exactly like the Tier 1
|
|
319
|
+
encoders (:func:`~unicode_logic_kit.hol.deepshallow.modal.modal_to_deep` and
|
|
320
|
+
siblings). ``consts`` collects OBJECT-constant symbols and is a REQUIRED
|
|
321
|
+
argument, on purpose: a resolver this function created and the caller
|
|
322
|
+
never got back would be a resolver whose declarations a hand-assembled
|
|
323
|
+
theory can silently drop (an earlier version of this function made
|
|
324
|
+
exactly that mistake, defaulting ``consts=None`` and fabricating one
|
|
325
|
+
internally — a caller who then emitted only ``atoms.decls()`` produced an
|
|
326
|
+
ill-typed Isabelle theory with no error raised on the Python side). To
|
|
327
|
+
keep a predicate and a constant that sanitise to the same identifier from
|
|
328
|
+
colliding on the one Isabelle type ``s`` both use, share the
|
|
329
|
+
de-collision pool the way :func:`qml_deep_faithfulness_theory` itself
|
|
330
|
+
does::
|
|
331
|
+
|
|
332
|
+
atoms = AtomConsts()
|
|
333
|
+
consts = AtomConsts()
|
|
334
|
+
consts._used = atoms._used
|
|
335
|
+
term = qml_to_deep(formula, atoms, consts)
|
|
336
|
+
|
|
337
|
+
Any theory built from ``term`` — by hand, or via
|
|
338
|
+
:func:`qml_deep_faithfulness_theory` — must emit BOTH ``atoms.decls()``
|
|
339
|
+
and ``consts.decls()``; omitting either produces an ill-typed theory
|
|
340
|
+
(Isabelle rejects the undeclared name with "Extra variables on rhs").
|
|
341
|
+
|
|
342
|
+
Raises :class:`NotImplementedError` on equality/disequality, a function
|
|
343
|
+
term or a Number literal, a free (unbound) variable, or any operator
|
|
344
|
+
outside alethic ``□``/``◇`` (epistemic/doxastic/deontic/temporal/hybrid/
|
|
345
|
+
many-sorted) — every refusal names the offending construct. There is no
|
|
346
|
+
``frame=``/``mode=`` parameter: this module structurally commits to K
|
|
347
|
+
(``R`` left arbitrary) and the constant domain (one shared ``D``); use
|
|
348
|
+
:mod:`unicode_logic_kit.hol.isabelle_modal` for the other frames/regimes.
|
|
349
|
+
"""
|
|
350
|
+
return _encode(formula, [], atoms, consts)
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
# --------------------------------------------------------------------------- #
|
|
354
|
+
# Public entry points.
|
|
355
|
+
# --------------------------------------------------------------------------- #
|
|
356
|
+
|
|
357
|
+
def _qml_formula_section(term: str, atoms: AtomConsts, consts: AtomConsts) -> str:
|
|
358
|
+
"""The ``consts`` + ``definition example`` block grounding a concrete formula.
|
|
359
|
+
|
|
360
|
+
Like :func:`unicode_logic_kit.hol.deepshallow._common.formula_section`, but
|
|
361
|
+
emitting TWO ``consts`` groups (predicate symbols, then object constants) —
|
|
362
|
+
``qml_to_deep`` needs both namespaces, which ``_common.formula_section``'s
|
|
363
|
+
single-``AtomConsts`` signature cannot express.
|
|
364
|
+
"""
|
|
365
|
+
lines = ["", "section \\<open>A concrete embedded formula\\<close>", ""]
|
|
366
|
+
lines += atoms.decls()
|
|
367
|
+
lines += consts.decls()
|
|
368
|
+
lines.append(f'definition example :: qml where "example = {term}"')
|
|
369
|
+
return "\n".join(lines)
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
def qml_deep_faithfulness_theory(
|
|
373
|
+
theory_name: str = "QmlFaithfulness",
|
|
374
|
+
formula: Optional[Node] = None,
|
|
375
|
+
) -> str:
|
|
376
|
+
r"""Emit the self-contained QML deep/maximal/minimal + faithfulness theory
|
|
377
|
+
(Tier 2: K frame, constant domain, alethic □/◇ only).
|
|
378
|
+
|
|
379
|
+
The returned string is a full ``theory <theory_name> imports Main begin ... end``
|
|
380
|
+
containing the three embeddings and the five faithfulness theorems
|
|
381
|
+
(``faithful1a/1b/2/3``, ``sound_min``), each closed by Isabelle. With a local
|
|
382
|
+
Isabelle/HOL it is verified end to end by
|
|
383
|
+
:func:`unicode_logic_kit.hol.isabelle_runner.check_theory` — exit 0 means
|
|
384
|
+
Isabelle's kernel discharged every one; the theory text itself contains
|
|
385
|
+
neither ``sorry`` nor ``oops``.
|
|
386
|
+
|
|
387
|
+
Args:
|
|
388
|
+
theory_name: the Isabelle theory / file name (a legal identifier).
|
|
389
|
+
formula: an optional QML formula within this fragment. When given, its
|
|
390
|
+
deep encoding is appended as ``definition example :: qml`` (with
|
|
391
|
+
``consts`` for its predicate and object-constant symbols), so the
|
|
392
|
+
certificate is grounded in a concrete formula. Raises
|
|
393
|
+
:class:`NotImplementedError` if ``formula`` uses a construct outside
|
|
394
|
+
K + constant domain + alethic □/◇ (see :func:`qml_to_deep`).
|
|
395
|
+
|
|
396
|
+
Returns:
|
|
397
|
+
The theory text (newline-terminated).
|
|
398
|
+
"""
|
|
399
|
+
extra = ""
|
|
400
|
+
if formula is not None:
|
|
401
|
+
atoms = AtomConsts()
|
|
402
|
+
consts = AtomConsts()
|
|
403
|
+
consts._used = atoms._used
|
|
404
|
+
term = qml_to_deep(formula, atoms, consts)
|
|
405
|
+
extra = _qml_formula_section(term, atoms, consts)
|
|
406
|
+
return wrap_theory(theory_name, _QML_BODY, extra)
|