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,306 @@
1
+ """Well-formedness / validity report for (LLM-generated) FOL formulas.
2
+
3
+ This module provides lightweight, purely structural checks that flag the
4
+ defects most commonly seen in machine-produced first-order formulas:
5
+
6
+ * the formula is not a closed sentence (it has free logical variables);
7
+ * a predicate or function symbol is applied with inconsistent arities;
8
+ * leftover lambda machinery (Lambda / Application / LambdaVar) that should
9
+ have been eliminated before the formula was considered final;
10
+ * (via ``validate_text``) the raw model output does not even parse.
11
+
12
+ The entry points are:
13
+
14
+ * ``validate(node)`` — inspect an already-parsed AST.
15
+ * ``is_wellformed(node)`` — the headline boolean.
16
+ * ``validate_text(text)`` — parse raw text first, capturing parse failures.
17
+
18
+ Nothing here mutates its input; every traversal is read-only.
19
+ """
20
+
21
+ from dataclasses import dataclass, field
22
+ from typing import Dict, Optional, Tuple
23
+
24
+ from unicode_logic_kit.fol.nodes import (
25
+ Node,
26
+ Variable,
27
+ Constant,
28
+ Function,
29
+ Atom,
30
+ Lambda,
31
+ Application,
32
+ LambdaVar,
33
+ SortedConstant,
34
+ free_variables,
35
+ )
36
+ # The node types that carry a sort name (SortedQuantifier, SortedConstant,
37
+ # SortedCount, SortedCardinality): one definition, shared with the reduction to
38
+ # plain FOL, so a sorted node added there is read here too.
39
+ from unicode_logic_kit.fol._msfl_nodes import _SORTED_NODE_TYPES
40
+ # The two truth constants are the logical constants true and false, not predicates
41
+ # of the user's: one definition, shared with every route that reads them.
42
+ from unicode_logic_kit.fol._truth_constants import is_truth_constant
43
+
44
+
45
+ # ---------------------------------------------------------------------------
46
+ # Report dataclass
47
+ # ---------------------------------------------------------------------------
48
+
49
+ @dataclass(frozen=True)
50
+ class ValidationReport:
51
+ """An immutable summary of the well-formedness checks run on a formula.
52
+
53
+ Namespacing of ``arity_conflicts``: predicate and function symbols live in
54
+ SEPARATE namespaces, so a key is a 2-tuple ``("pred", name)`` or
55
+ ``("func", name)``. This keeps a predicate ``P`` used as ``P/1`` from
56
+ falsely conflicting with an unrelated function ``p`` used as ``p/2``.
57
+
58
+ Fields:
59
+
60
+ ``is_closed``
61
+ True iff the formula has no free logical variables (it is a
62
+ sentence). Free occurrences of both ``Variable`` and ``LambdaVar``
63
+ count against closedness.
64
+ ``free_variable_names``
65
+ sorted, de-duplicated names of the free Variable/LambdaVar
66
+ occurrences.
67
+ ``arity_consistent``
68
+ True iff every predicate symbol is used with a single arity and
69
+ likewise every function symbol.
70
+ ``arity_conflicts``
71
+ maps a namespaced symbol key ``("pred"|"func", name)`` to the sorted
72
+ tuple of the distinct arities observed; only symbols with more than
73
+ one distinct arity appear.
74
+ ``has_lambdas``
75
+ True iff any Lambda / Application / LambdaVar remains.
76
+ ``predicates`` / ``functions`` / ``constants``
77
+ sorted ``name/arity`` (predicates, functions) or ``name`` (constants)
78
+ inventories for quick inspection. The comparison atoms, the arithmetic
79
+ functions and the two truth constants (``⊤`` / ``$true``, ``⊥`` /
80
+ ``$false``) are built in and are not listed.
81
+ ``sorts_used``
82
+ sorted sort names from every node that carries one: SortedQuantifier,
83
+ SortedConstant, SortedCount and SortedCardinality.
84
+ ``parseable``
85
+ True for ``validate(node)``; ``validate_text`` sets it False on a
86
+ parse failure.
87
+ ``error``
88
+ the parse-error message when ``parseable`` is False, else None.
89
+ """
90
+
91
+ is_closed: bool
92
+ free_variable_names: Tuple[str, ...]
93
+ arity_consistent: bool
94
+ arity_conflicts: Dict[Tuple[str, str], Tuple[int, ...]]
95
+ has_lambdas: bool
96
+ predicates: Tuple[str, ...]
97
+ functions: Tuple[str, ...]
98
+ constants: Tuple[str, ...]
99
+ sorts_used: Tuple[str, ...]
100
+ parseable: bool = True
101
+ error: Optional[str] = None
102
+
103
+ def __str__(self) -> str:
104
+ """Render a compact, human-readable multi-line summary."""
105
+ if not self.parseable:
106
+ return f"ValidationReport(parseable=False, error={self.error!r})"
107
+ lines = [
108
+ "ValidationReport(",
109
+ f" parseable = {self.parseable}",
110
+ f" is_closed = {self.is_closed}",
111
+ f" free_variables = {', '.join(self.free_variable_names) or '-'}",
112
+ f" arity_consistent = {self.arity_consistent}",
113
+ f" arity_conflicts = {dict(self.arity_conflicts) or '-'}",
114
+ f" has_lambdas = {self.has_lambdas}",
115
+ f" predicates = {', '.join(self.predicates) or '-'}",
116
+ f" functions = {', '.join(self.functions) or '-'}",
117
+ f" constants = {', '.join(self.constants) or '-'}",
118
+ f" sorts_used = {', '.join(self.sorts_used) or '-'}",
119
+ ")",
120
+ ]
121
+ return "\n".join(lines)
122
+
123
+
124
+ # ---------------------------------------------------------------------------
125
+ # Internal inventory collection
126
+ # ---------------------------------------------------------------------------
127
+
128
+ @dataclass
129
+ class _Inventory:
130
+ """Mutable scratch collector populated by a single pre-order walk.
131
+
132
+ Kept private and never returned; ``validate`` freezes the results into the
133
+ immutable ``ValidationReport``. Arities are accumulated per namespaced
134
+ symbol so that conflicts can be detected afterwards.
135
+ """
136
+
137
+ pred_arities: Dict[str, set] = field(default_factory=dict)
138
+ func_arities: Dict[str, set] = field(default_factory=dict)
139
+ constants: set = field(default_factory=set)
140
+ sorts: set = field(default_factory=set)
141
+ has_lambdas: bool = False
142
+
143
+
144
+ # Comparison atoms (=, ≠, <, >, ≤, ≥) and arithmetic functions (+, -, *, /) are
145
+ # built-in operators, not user predicate/function symbols, so they are excluded
146
+ # from the inventories and from arity-consistency checking. So are the two truth
147
+ # constants (the nullary atoms ``$true`` / ``⊤`` and ``$false`` / ``⊥``): a
148
+ # formula that mentions ``⊥`` uses no predicate named ``$false``, and the
149
+ # nullary constant never conflicts with a user predicate spelled like it that
150
+ # takes arguments.
151
+ _BUILTIN_PREDS = frozenset({"=", "≠", "<", ">", "≤", "≥"})
152
+ _BUILTIN_FUNCS = frozenset({"+", "-", "*", "/"})
153
+
154
+
155
+ def _collect(node: Node, inv: _Inventory) -> None:
156
+ """Walk ``node`` in pre-order, recording every symbol into ``inv``.
157
+
158
+ Uses ``node.walk()`` (the shared pre-order traversal) so that any future
159
+ structural node type is covered without changes here. Each occurrence is
160
+ classified purely by node type; nothing is mutated on the input.
161
+ """
162
+ for n in node.walk():
163
+ if isinstance(n, (Lambda, Application, LambdaVar)):
164
+ inv.has_lambdas = True
165
+
166
+ if isinstance(n, Atom):
167
+ if n.predicate not in _BUILTIN_PREDS and not is_truth_constant(n):
168
+ inv.pred_arities.setdefault(n.predicate, set()).add(len(n.args))
169
+ elif isinstance(n, Function):
170
+ if n.name not in _BUILTIN_FUNCS:
171
+ inv.func_arities.setdefault(n.name, set()).add(len(n.args))
172
+ elif isinstance(n, Constant):
173
+ inv.constants.add(n.name)
174
+ elif isinstance(n, SortedConstant):
175
+ inv.constants.add(n.name)
176
+ inv.sorts.add(n.sort)
177
+ elif isinstance(n, _SORTED_NODE_TYPES):
178
+ # SortedQuantifier, and the sorted counting quantifier and cardinality
179
+ # term: a sort that occurs only in one of the last two is a sort used.
180
+ inv.sorts.add(n.sort)
181
+
182
+
183
+ def _arity_conflicts(inv: _Inventory) -> Dict[Tuple[str, str], Tuple[int, ...]]:
184
+ """Return namespaced symbols seen with more than one arity.
185
+
186
+ Keys are ``("pred", name)`` / ``("func", name)``; values are the sorted
187
+ tuple of distinct arities. Symbols with a single consistent arity are
188
+ omitted, so an empty dict means full arity consistency.
189
+ """
190
+ conflicts: Dict[Tuple[str, str], Tuple[int, ...]] = {}
191
+ for name, arities in inv.pred_arities.items():
192
+ if len(arities) > 1:
193
+ conflicts[("pred", name)] = tuple(sorted(arities))
194
+ for name, arities in inv.func_arities.items():
195
+ if len(arities) > 1:
196
+ conflicts[("func", name)] = tuple(sorted(arities))
197
+ return conflicts
198
+
199
+
200
+ def _inventory_strings(arities: Dict[str, set]) -> Tuple[str, ...]:
201
+ """Render a name->arities map as a sorted tuple of ``name/arity`` strings.
202
+
203
+ A symbol with conflicting arities yields one entry per distinct arity (e.g.
204
+ ``P/1`` and ``P/2``), so the inventory faithfully shows every form seen.
205
+ """
206
+ entries = []
207
+ for name, arity_set in arities.items():
208
+ for arity in sorted(arity_set):
209
+ entries.append(f"{name}/{arity}")
210
+ return tuple(sorted(entries))
211
+
212
+
213
+ # ---------------------------------------------------------------------------
214
+ # Public API
215
+ # ---------------------------------------------------------------------------
216
+
217
+ def validate(node: Node) -> ValidationReport:
218
+ """Run all well-formedness checks on an already-parsed AST.
219
+
220
+ The returned report always has ``parseable=True`` (the node was, by
221
+ definition, parsed to exist). ``validate_text`` is the entry point that can
222
+ report a parse failure.
223
+
224
+ Args:
225
+ node: any FOL/MSFL ``Node``.
226
+
227
+ Returns:
228
+ A frozen ``ValidationReport`` describing closedness, arity consistency,
229
+ residual lambda machinery, and symbol inventories.
230
+ """
231
+ free = free_variables(node)
232
+ free_names = tuple(sorted({v.name for v in free}))
233
+
234
+ inv = _Inventory()
235
+ _collect(node, inv)
236
+
237
+ conflicts = _arity_conflicts(inv)
238
+
239
+ return ValidationReport(
240
+ is_closed=not free,
241
+ free_variable_names=free_names,
242
+ arity_consistent=not conflicts,
243
+ arity_conflicts=conflicts,
244
+ has_lambdas=inv.has_lambdas,
245
+ predicates=_inventory_strings(inv.pred_arities),
246
+ functions=_inventory_strings(inv.func_arities),
247
+ constants=tuple(sorted(inv.constants)),
248
+ sorts_used=tuple(sorted(inv.sorts)),
249
+ parseable=True,
250
+ error=None,
251
+ )
252
+
253
+
254
+ def is_wellformed(node: Node) -> bool:
255
+ """Convenience headline check on an already-parsed AST.
256
+
257
+ A node is well-formed iff it is a closed sentence, every symbol is used
258
+ with a single arity, and no lambda machinery remains.
259
+ """
260
+ report = validate(node)
261
+ return report.is_closed and report.arity_consistent and not report.has_lambdas
262
+
263
+
264
+ def validate_text(text: str, parser=None) -> ValidationReport:
265
+ """Parse ``text`` then validate it, capturing syntactic failures.
266
+
267
+ This is the entry point for raw model output: a parse failure
268
+ (``NamingError`` / ``ParsingError``) yields a report with
269
+ ``parseable=False`` and the error message in ``error`` rather than raising.
270
+
271
+ Args:
272
+ text: the raw formula string.
273
+ parser: an ``MSFLParser`` instance (or anything with a compatible
274
+ ``.parse``). Defaults to a fresh ``MSFLParser()`` (classical FOL
275
+ mode). Pass ``MSFLParser(many_sorted=True)`` etc. for other modes.
276
+
277
+ Returns:
278
+ On success, a report with ``parseable=True`` plus the ``validate(node)``
279
+ fields. On a parse failure, a report with ``parseable=False``, the
280
+ error message in ``error``, and conservative empty/false field values.
281
+ """
282
+ # Imported lazily so the AST-only checks (validate / is_wellformed) do not
283
+ # pull in the parser stack, and to mirror the package's import boundaries.
284
+ from unicode_logic_kit import MSFLParser, NamingError, ParsingError
285
+
286
+ if parser is None:
287
+ parser = MSFLParser()
288
+
289
+ try:
290
+ node = parser.parse(text)
291
+ except (NamingError, ParsingError) as exc:
292
+ return ValidationReport(
293
+ is_closed=False,
294
+ free_variable_names=(),
295
+ arity_consistent=False,
296
+ arity_conflicts={},
297
+ has_lambdas=False,
298
+ predicates=(),
299
+ functions=(),
300
+ constants=(),
301
+ sorts_used=(),
302
+ parseable=False,
303
+ error=str(exc),
304
+ )
305
+
306
+ return validate(node)
@@ -0,0 +1,177 @@
1
+ from .msflparser import MSFLParser
2
+ from .nodes import (
3
+ Node, Variable, Constant, Number, Function,
4
+ Atom, Not, And, Or, Xor, Implies, Iff, Quantifier,
5
+ Count, Measure, Cardinality, Contrast,
6
+ Z3Env,
7
+ node_at, replace_at,
8
+ SortedQuantifier, SortedConstant,
9
+ SortedCount, SortedCardinality,
10
+ Nominal, At, Down,
11
+ Dependence, SlashedExists,
12
+ Tensor, With, OPlus, LinearImplies, OfCourse, One, Top, Zero,
13
+ Product, Under, Over,
14
+ WeakConjunction, WeakDisjunction,
15
+ StrongConjunction, StrongDisjunction,
16
+ LukNegation, LukImplication, LukEquivalence,
17
+ LambdaVar, Lambda, Application,
18
+ Box, Diamond, Knows, Believes, Says, Wants,
19
+ EverybodyKnows, DistributedKnowledge, CommonKnowledge,
20
+ Always, Eventually, Next, Until,
21
+ Historically, Once, Previous, Since,
22
+ Obligatory, Permitted,
23
+ Would, Might,
24
+ Announce, AnnounceDiamond,
25
+ SecondOrderQuantifier,
26
+ PredicateTerm, Signatures, analyse_signatures, MixedSlotError, NestedPropertySlotError,
27
+ free_variables,
28
+ substitute, beta_reduce, ReductionLimitError,
29
+ eta_reduce, beta_eta_normalize,
30
+ resolve_lambda_scope,
31
+ to_fol,
32
+ nonempty_sort_axioms,
33
+ sort_membership_axioms,
34
+ sort_axioms,
35
+ subsort_axioms,
36
+ signature_axioms,
37
+ )
38
+ from .normalforms import to_nnf, to_pnf, to_cnf, to_dnf, to_tseitin_cnf, skolemize, is_horn
39
+ from .lambda_tools import has_lambdas, eliminate_lambdas, beta_reduce_step, reduce_trace
40
+ from .unification import unify, apply_subst
41
+ from .modal_translation import standard_translation, hybrid_is_valid, down_is_valid
42
+ from .pal import reduce_announcements
43
+ from .latex_input import latex_to_unicode, parse_latex
44
+ from .tptp_input import (
45
+ parse_tptp, parse_tptp_formula, load_tptp, TptpFormula,
46
+ parse_tptp_problem, load_tptp_problem, TptpProblem, TptpHeader,
47
+ parse_tff_problem, load_tff_problem,
48
+ )
49
+ from .qmltp_input import (
50
+ parse_qmltp_formula, parse_qmltp, load_qmltp,
51
+ QmltpFormula, QmltpHeader, QmltpStatus, QmltpProblem,
52
+ )
53
+ from .prover9_input import (
54
+ parse_prover9, parse_prover9_problem, load_prover9, Prover9Formula,
55
+ )
56
+ from .prolog_input import (
57
+ parse_prolog_clause, parse_prolog_program, load_prolog, PrologParsingError,
58
+ )
59
+ from .prolog_export import (
60
+ formula_to_prolog_clause, formula_to_prolog_program, PrologExportError,
61
+ )
62
+ from .sanitize import sanitize_names, sanitize_all, NameMapping
63
+ from .verbalize import to_english
64
+ from .derivation import CCGDerivation, reduction_derivation
65
+ from .frames import (
66
+ AXIOM_ALIASES, FRAMES, FRAME_CONDITIONS, MODAL_AXIOMS,
67
+ UnsupportedFrameCondition, resolve_frame, geach_axiom,
68
+ holds_on_finite_frame, modal_axiom, unguarded_frame_axiom,
69
+ )
70
+ from .qml import (
71
+ qml_translate, qml_axioms, qml_is_valid, qml_equivalent, qml_validity_formula,
72
+ to_thf_modal, to_isabelle_modal, BARCAN, CONVERSE_BARCAN, QML_BRIDGES,
73
+ )
74
+ from .naming import NamingError, ParsingError
75
+ from .spans import (
76
+ Span, UNKNOWN, NodeSpans, Path, SpanMap, SpannedFormula,
77
+ traverse, build_span_map, project_spans,
78
+ )
79
+ from .serialize import SCHEMA_VERSION, serialize, deserialize
80
+ from .casl_export import to_casl_spec, formula_to_casl
81
+ from .casl_import import parse_casl_spec, CaslSpec, CaslImportError
82
+ from .tptp_repair import (
83
+ repair_tptp_formula, repair_tptp_problem, RepairResult, Issue,
84
+ ProblemRepairEntry, ProblemRepairResult, TptpRepairError,
85
+ )
86
+ from .dialect_repair import repair_formula, DialectRepairResult
87
+ from .simplify_check import (
88
+ simplify_for_checking, SimplifyResult,
89
+ count_from_existential_chain, expand_count,
90
+ )
91
+ from .dialect_detect import detect_dialects
92
+ from .signature import (
93
+ Signature, PredicateDecl, FunctionDecl, ConstantDecl, inventory_of,
94
+ )
95
+ from ._identifiers import is_variable_name, is_bare_constant, constant_text
96
+ from ._atom_keys import atom_key
97
+
98
+ __all__ = [
99
+ # The shared modal frame registry — one table for every modal route.
100
+ "FRAMES", "FRAME_CONDITIONS", "MODAL_AXIOMS", "AXIOM_ALIASES",
101
+ "modal_axiom", "resolve_frame", "geach_axiom",
102
+ "holds_on_finite_frame", "unguarded_frame_axiom",
103
+ "UnsupportedFrameCondition",
104
+ "MSFLParser",
105
+ "Node", "Variable", "Constant", "Number", "Function",
106
+ "Atom", "Not", "And", "Or", "Xor", "Implies", "Iff", "Quantifier",
107
+ "Count", "Measure", "Cardinality", "Contrast",
108
+ "Z3Env",
109
+ "node_at", "replace_at",
110
+ "NamingError", "ParsingError",
111
+ "Span", "UNKNOWN", "NodeSpans", "Path", "SpanMap", "SpannedFormula",
112
+ "traverse", "build_span_map", "project_spans",
113
+ "SCHEMA_VERSION", "serialize", "deserialize",
114
+ "to_casl_spec", "formula_to_casl",
115
+ "parse_casl_spec", "CaslSpec", "CaslImportError",
116
+ "repair_tptp_formula", "repair_tptp_problem", "RepairResult", "Issue",
117
+ "ProblemRepairEntry", "ProblemRepairResult", "TptpRepairError",
118
+ "repair_formula", "DialectRepairResult",
119
+ "parse_prolog_clause", "parse_prolog_program", "load_prolog",
120
+ "PrologParsingError",
121
+ "formula_to_prolog_clause", "formula_to_prolog_program",
122
+ "PrologExportError",
123
+ "simplify_for_checking", "SimplifyResult",
124
+ "count_from_existential_chain", "expand_count",
125
+ "detect_dialects",
126
+ "is_variable_name", "is_bare_constant", "constant_text", "atom_key",
127
+ "Signature", "PredicateDecl", "FunctionDecl", "ConstantDecl",
128
+ "inventory_of",
129
+ "SortedQuantifier", "SortedConstant",
130
+ "SortedCount", "SortedCardinality",
131
+ "Nominal", "At", "Down",
132
+ "Dependence", "SlashedExists",
133
+ "Tensor", "With", "OPlus", "LinearImplies", "OfCourse", "One", "Top", "Zero",
134
+ "Product", "Under", "Over",
135
+ "WeakConjunction", "WeakDisjunction",
136
+ "StrongConjunction", "StrongDisjunction",
137
+ "LukNegation", "LukImplication", "LukEquivalence",
138
+ "LambdaVar", "Lambda", "Application",
139
+ "Box", "Diamond", "Knows", "Believes", "Says", "Wants",
140
+ "EverybodyKnows", "DistributedKnowledge", "CommonKnowledge",
141
+ "Always", "Eventually", "Next", "Until",
142
+ "Historically", "Once", "Previous", "Since",
143
+ "Obligatory", "Permitted",
144
+ "Would", "Might",
145
+ "Announce", "AnnounceDiamond",
146
+ "SecondOrderQuantifier",
147
+ "PredicateTerm", "Signatures", "analyse_signatures", "MixedSlotError", "NestedPropertySlotError",
148
+ "free_variables",
149
+ "substitute", "beta_reduce", "ReductionLimitError",
150
+ "eta_reduce", "beta_eta_normalize",
151
+ "resolve_lambda_scope",
152
+ "to_fol",
153
+ "nonempty_sort_axioms",
154
+ "sort_membership_axioms",
155
+ "sort_axioms",
156
+ "subsort_axioms",
157
+ "signature_axioms",
158
+ "to_nnf", "to_pnf", "to_cnf", "to_dnf", "to_tseitin_cnf", "skolemize", "is_horn",
159
+ "has_lambdas", "eliminate_lambdas", "beta_reduce_step", "reduce_trace",
160
+ "unify", "apply_subst",
161
+ "standard_translation", "hybrid_is_valid", "down_is_valid",
162
+ "reduce_announcements",
163
+ "latex_to_unicode", "parse_latex",
164
+ "parse_tptp", "parse_tptp_formula", "load_tptp", "TptpFormula",
165
+ "parse_tptp_problem", "load_tptp_problem", "TptpProblem", "TptpHeader",
166
+ "parse_tff_problem", "load_tff_problem",
167
+ "parse_prover9", "parse_prover9_problem", "load_prover9", "Prover9Formula",
168
+ "sanitize_names", "sanitize_all", "NameMapping",
169
+ "to_english",
170
+ "CCGDerivation", "reduction_derivation",
171
+ "qml_translate", "qml_axioms", "qml_is_valid", "qml_equivalent",
172
+ "qml_validity_formula",
173
+ "to_thf_modal", "to_isabelle_modal", "BARCAN", "CONVERSE_BARCAN",
174
+ "QML_BRIDGES",
175
+ "parse_qmltp_formula", "parse_qmltp", "load_qmltp",
176
+ "QmltpFormula", "QmltpHeader", "QmltpStatus", "QmltpProblem",
177
+ ]