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,303 @@
|
|
|
1
|
+
"""Adapter for LogicNLI (Tian, Li, Chen, Xiao, He, and Jin, "Diagnosing the
|
|
2
|
+
First-Order Logical Reasoning Ability Through LogicNLI", EMNLP 2021) — local
|
|
3
|
+
JSONL only, no network access.
|
|
4
|
+
|
|
5
|
+
Two sources were checked, not assumed
|
|
6
|
+
--------------------------------------
|
|
7
|
+
The task brief for this adapter asked specifically whether the Hugging Face
|
|
8
|
+
mirror carries the same first-order structure as the GitHub original. It
|
|
9
|
+
does not, and the difference drives every design choice below.
|
|
10
|
+
|
|
11
|
+
**Hugging Face mirror** — https://huggingface.co/datasets/tasksource/LogicNLI
|
|
12
|
+
(unauthenticated; verified 2026-08-12 via the ``datasets-server``
|
|
13
|
+
``/splits`` and ``/first-rows`` APIs). Three splits under config
|
|
14
|
+
``"default"``: ``train`` (16000 rows), ``validation`` (2000 rows), ``test``
|
|
15
|
+
(2000 rows) — 20000 rows total. Every row is a flat object with EXACTLY
|
|
16
|
+
three keys, all ``dtype: string``:
|
|
17
|
+
|
|
18
|
+
* ``"premise"`` — ONE string: every fact sentence, ``"\\n"``-joined,
|
|
19
|
+
directly followed by every rule sentence, also ``"\\n"``-joined, but with
|
|
20
|
+
**no separator at all between the last fact and the first rule** (verified
|
|
21
|
+
directly in the fetched sample: ``"...Nathalie is not accurate.If there is
|
|
22
|
+
someone..."`` — the period is followed immediately by ``"If"``, no space or
|
|
23
|
+
newline). This is a lossy blob: individual premise sentences cannot be
|
|
24
|
+
recovered from it without a fact/rule-boundary heuristic this adapter
|
|
25
|
+
declines to guess.
|
|
26
|
+
* ``"hypothesis"`` — ``str``, the statement being judged.
|
|
27
|
+
* ``"label"`` — ``str``. The **verified label vocabulary**, read
|
|
28
|
+
directly off real rows (not the paper's prose), is exactly four values:
|
|
29
|
+
``"entailment"``, ``"contradiction"``, ``"neutral"``, ``"self_contradiction"``.
|
|
30
|
+
Note this explicitly: the fourth class is **not** called ``"paradox"``
|
|
31
|
+
anywhere in the data — that was only ever an informal guess.
|
|
32
|
+
|
|
33
|
+
There is NO first-order-logic column of any kind on the HF mirror — no field
|
|
34
|
+
resembling FOLIO's ``premises-FOL``/``conclusion-FOL`` exists here at all.
|
|
35
|
+
|
|
36
|
+
**GitHub original** — https://github.com/omnilabNLP/LogicNLI (verified
|
|
37
|
+
2026-08-12 via the GitHub Contents API and by downloading and unzipping the
|
|
38
|
+
repo's one data artifact, ``dataset/LogicNLI_sim.zip``, 856136 bytes per the
|
|
39
|
+
Contents API). The archive contains six files, ``{train,dev,test}_language.json``
|
|
40
|
+
and ``{train,dev,test}_logic.json``, each a JSON object keyed by a "story id"
|
|
41
|
+
string. Counts were verified exhaustively (every story in every split, not a
|
|
42
|
+
sample): every single story has EXACTLY 12 facts, 12 rules, and 20 statements
|
|
43
|
+
— 800 stories in ``train`` (16000 statements), 100 in ``dev`` (2000), 100 in
|
|
44
|
+
``test`` (2000). These totals match the HF mirror's split sizes exactly
|
|
45
|
+
(16000/2000/2000), confirming both are the same underlying benchmark (``dev``
|
|
46
|
+
here vs. ``validation`` there is just a naming difference) — though row order
|
|
47
|
+
does not obviously align 1:1 (HF row 0 uses different character names than
|
|
48
|
+
GitHub story ``"0"``), so treat them as two independently-obtained copies,
|
|
49
|
+
not index-aligned mirrors of each other.
|
|
50
|
+
|
|
51
|
+
Critically, ``*_logic.json`` DOES carry a logical annotation the HF mirror
|
|
52
|
+
lacks — but it is a bespoke STRUCTURED SYMBOLIC form, not an FOL formula
|
|
53
|
+
string of the kind FOLIO's ``premises-FOL`` provides. Confirmed directly by
|
|
54
|
+
loading and inspecting real story records (``dev_logic.json``/
|
|
55
|
+
``dev_language.json``, stories ``"0"`` and ``"1"``, cross-checked sentence by
|
|
56
|
+
sentence against the paired ``*_language.json`` English text):
|
|
57
|
+
|
|
58
|
+
* A **fact** is a 4-element list ``[subject, attribute, polarity, tag]``,
|
|
59
|
+
e.g. ``["Eli", "soft", "-", "fact 0"]`` for "Eli is not soft." — always a
|
|
60
|
+
NAMED entity (``subject`` is never a quantifier marker; verified over all
|
|
61
|
+
12000 facts across all three splits: 100% ``const``-subject).
|
|
62
|
+
``polarity`` is ``"+"`` (asserted) or ``"-"`` (negated).
|
|
63
|
+
A **statement** (the hypothesis being labelled) has the same 4-element
|
|
64
|
+
shape and the same 100%-named-subject property (verified over all 20000
|
|
65
|
+
statements), plus a fourth element that is a human-unreadable PROVENANCE
|
|
66
|
+
trace of which facts/rules the label was derived from (e.g.
|
|
67
|
+
``"[[fact 2-->6]-->3]"``), not a sentence.
|
|
68
|
+
* A **rule** is ``{"p": {"fact": [...], "conj": ...}, "q": {"fact": [...],
|
|
69
|
+
"conj": ...}, "type": "imp"|"equ", "reasoning": <code>, "class": <int>}``.
|
|
70
|
+
``p``/``q`` are the antecedent/consequent, each a list of 1-2 fact-triples
|
|
71
|
+
``[subject_or_quantifier, attribute, polarity]`` (no tag) combined by
|
|
72
|
+
``conj`` (``"none"`` for a singleton, else ``"and"``/``"or"``); ``type``
|
|
73
|
+
is ``"imp"`` (material implication, p occurring first) or ``"equ"``
|
|
74
|
+
(biconditional). ``subject_or_quantifier`` is one of a NAMED entity,
|
|
75
|
+
``"all"``, or ``"exist"`` — verified EXHAUSTIVELY over all 12000 rules
|
|
76
|
+
across all three splits that within one ``p``/``q`` group the subject kind
|
|
77
|
+
is always homogeneous (never a named entity mixed with a quantifier
|
|
78
|
+
marker in the same group), and that only four ``(p_kind, q_kind)``
|
|
79
|
+
combinations ever occur: ``(all, all)`` — 4980, ``(const, const)`` — 3890,
|
|
80
|
+
``(exist, const)`` — 2783, ``(all, const)`` — 347 (of which ALL 347 are
|
|
81
|
+
``"imp"``, never ``"equ"``). No ``(exist, exist)``, ``(exist, all)``, or
|
|
82
|
+
``(const, *quantifier*)`` combination occurs at all. ``"reasoning"``/
|
|
83
|
+
``"class"`` are the paper's own internal category codes for its
|
|
84
|
+
robustness/traceability evaluation; this adapter does not interpret them.
|
|
85
|
+
|
|
86
|
+
What this adapter deliberately does NOT do
|
|
87
|
+
-------------------------------------------
|
|
88
|
+
Turning the structured ``rules`` annotation above into an actual FOL formula
|
|
89
|
+
string is possible in principle (the exhaustive combo analysis above is
|
|
90
|
+
enough to fix a translation scheme unambiguously) but it is a NEW,
|
|
91
|
+
kit-authored INTERPRETATION of the data, not something the dataset's authors
|
|
92
|
+
themselves published as a formula — the closest they publish is the
|
|
93
|
+
human-readable ``*_language.json`` sentence. Shipping a from-scratch compiler
|
|
94
|
+
here would (a) silently present an unreviewed, unverified rendering as if it
|
|
95
|
+
were "the dataset's FOL", which is exactly the kind of quiet reshaping this
|
|
96
|
+
adapter subpackage's docstrings elsewhere warn against, and (b) make
|
|
97
|
+
:func:`~unicode_logic_kit.eval.datasets.audit_examples` report on formulas THIS
|
|
98
|
+
adapter invented rather than ones the dataset ships — a meaningless "clean"
|
|
99
|
+
signal. So, per this task's own documented fallback: **``fol_premises`` is
|
|
100
|
+
always ``()`` and ``fol_conclusion`` is always ``None`` for every LogicNLI
|
|
101
|
+
example.** The raw structured annotation is not discarded, though — it is
|
|
102
|
+
preserved VERBATIM in ``meta["premises_logic"]`` / ``meta["hypothesis_logic"]``
|
|
103
|
+
(see the loader schema below) for any downstream user who wants to write
|
|
104
|
+
their own translation.
|
|
105
|
+
|
|
106
|
+
This adapter's own JSONL schema (NOT a verbatim upstream format)
|
|
107
|
+
------------------------------------------------------------------
|
|
108
|
+
Neither upstream source is naturally "one JSON object per example": the HF
|
|
109
|
+
mirror gives ONE flat row per example but with the two fatal issues above
|
|
110
|
+
(no split-out premise sentences, no logic annotation at all); the GitHub
|
|
111
|
+
original groups 20 examples under one shared story (12 facts + 12 rules) and
|
|
112
|
+
splits that across TWO separate files (language / logic) that must be joined
|
|
113
|
+
by story id. So, exactly like :mod:`~unicode_logic_kit.eval.datasets.malls`
|
|
114
|
+
asks the caller to convert an upstream JSON array to JSONL first, this loader
|
|
115
|
+
defines its OWN per-example JSONL row shape and expects the caller to
|
|
116
|
+
produce it from the GitHub archive (a story's facts+rules is repeated
|
|
117
|
+
verbatim across every example/line drawn from that story — the same "several
|
|
118
|
+
consecutive rows share identical premises" situation FOLIO's docstring
|
|
119
|
+
already documents for its own story grouping):
|
|
120
|
+
|
|
121
|
+
* ``"premises_nl"`` — ``list[str]``: that story's ``facts`` (language)
|
|
122
|
+
followed by its ``rules`` (language), in source order.
|
|
123
|
+
* ``"premises_logic"`` — ``list``, the SAME length/order as ``premises_nl``:
|
|
124
|
+
each fact position holds its raw ``[subject, attribute, polarity, tag]``
|
|
125
|
+
list, each rule position holds its raw ``{"p": ..., "q": ..., "type":
|
|
126
|
+
..., "conj": ..., "reasoning": ..., "class": ...}`` dict (see above) —
|
|
127
|
+
copied verbatim from ``*_logic.json``, uninterpreted.
|
|
128
|
+
* ``"hypothesis_nl"`` — ``str``, the statement's language text.
|
|
129
|
+
* ``"hypothesis_logic"`` — the statement's raw ``[subject, attribute,
|
|
130
|
+
polarity, provenance]`` list, copied verbatim.
|
|
131
|
+
* ``"label"`` — ``str``, one of the four verified values above.
|
|
132
|
+
* ``"story_id"`` / ``"statement_id"`` / ``"split"`` — optional provenance
|
|
133
|
+
strings (the upstream story key, the upstream per-statement key within
|
|
134
|
+
that story, and which of ``train``/``dev``/``test`` it came from) used for
|
|
135
|
+
id construction when present (see :func:`_resolve_id`); a caller merging
|
|
136
|
+
multiple splits into one file should keep ``"split"`` so ids stay unique
|
|
137
|
+
across splits sharing the same numeric ``story_id``.
|
|
138
|
+
* ``"id"`` — optional explicit override, honoured before any of
|
|
139
|
+
the above (same defensive stance as every other adapter in this
|
|
140
|
+
subpackage).
|
|
141
|
+
|
|
142
|
+
A short recipe to produce this from the downloaded GitHub archive (adjust
|
|
143
|
+
paths/split as needed)::
|
|
144
|
+
|
|
145
|
+
import json
|
|
146
|
+
with open("dev_language.json", encoding="utf-8") as f: lang = json.load(f)
|
|
147
|
+
with open("dev_logic.json", encoding="utf-8") as f: logic = json.load(f)
|
|
148
|
+
with open("logicnli_dev.jsonl", "w", encoding="utf-8") as out:
|
|
149
|
+
for story_id, story in logic.items():
|
|
150
|
+
slang = lang[story_id]
|
|
151
|
+
premises_nl = list(slang["facts"]) + list(slang["rules"])
|
|
152
|
+
premises_logic = ([story["facts"][str(i)] for i in range(len(slang["facts"]))]
|
|
153
|
+
+ [story["rules"][str(i)] for i in range(len(slang["rules"]))])
|
|
154
|
+
for sid, label in story["labels"].items():
|
|
155
|
+
row = {
|
|
156
|
+
"story_id": story_id, "statement_id": sid, "split": "dev",
|
|
157
|
+
"premises_nl": premises_nl, "premises_logic": premises_logic,
|
|
158
|
+
"hypothesis_nl": slang["statements"][int(sid)],
|
|
159
|
+
"hypothesis_logic": story["statements"][sid],
|
|
160
|
+
"label": label,
|
|
161
|
+
}
|
|
162
|
+
out.write(json.dumps(row, ensure_ascii=False) + "\\n")
|
|
163
|
+
|
|
164
|
+
License — not stated by the authors, flagged rather than guessed
|
|
165
|
+
-------------------------------------------------------------------
|
|
166
|
+
Neither source declares a machine-readable license (verified 2026-08-12): the
|
|
167
|
+
GitHub repository has no ``LICENSE`` file (the GitHub Licenses API returns
|
|
168
|
+
404 for it) and no license section in its ``README.md``; the Hugging Face
|
|
169
|
+
dataset card's metadata (fetched via the HF datasets API and the raw
|
|
170
|
+
``README.md``) carries no ``license`` tag and no licensing prose — only the
|
|
171
|
+
paper's BibTeX entry. :data:`DATASET_INFO`'s ``license`` field for
|
|
172
|
+
``"logicnli"`` records exactly this absence rather than guessing a permissive
|
|
173
|
+
or restrictive default; confirm terms with the authors before redistributing.
|
|
174
|
+
|
|
175
|
+
This module never downloads anything — obtain and convert the data yourself
|
|
176
|
+
(see the recipe above) and pass its local JSONL path to :func:`load_logicnli`.
|
|
177
|
+
"""
|
|
178
|
+
|
|
179
|
+
import json
|
|
180
|
+
from pathlib import Path
|
|
181
|
+
from typing import FrozenSet, Iterator, Union
|
|
182
|
+
|
|
183
|
+
from ._base import DatasetExample, _register_dataset_info
|
|
184
|
+
|
|
185
|
+
__all__ = ["load_logicnli"]
|
|
186
|
+
|
|
187
|
+
_register_dataset_info(
|
|
188
|
+
"logicnli",
|
|
189
|
+
license=(
|
|
190
|
+
"Not stated by the authors as of verification (2026-08-12): the "
|
|
191
|
+
"GitHub repository (omnilabNLP/LogicNLI) has no LICENSE file (GitHub "
|
|
192
|
+
"Licenses API returns 404) and no licensing section in its README; "
|
|
193
|
+
"the Hugging Face mirror (tasksource/LogicNLI) has no license tag or "
|
|
194
|
+
"licensing prose on its dataset card either. Confirm terms with the "
|
|
195
|
+
"authors before redistributing."
|
|
196
|
+
),
|
|
197
|
+
source_url="https://github.com/omnilabNLP/LogicNLI",
|
|
198
|
+
citation_hint=(
|
|
199
|
+
"Tian, Jidong, et al. \"Diagnosing the First-Order Logical Reasoning "
|
|
200
|
+
"Ability Through LogicNLI.\" Proceedings of the 2021 Conference on "
|
|
201
|
+
"Empirical Methods in Natural Language Processing (EMNLP 2021), "
|
|
202
|
+
"pages 3738-3747. https://doi.org/10.18653/v1/2021.emnlp-main.303"
|
|
203
|
+
),
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
_RECORD_KEYS = (
|
|
207
|
+
"premises_nl", "premises_logic", "hypothesis_nl", "hypothesis_logic",
|
|
208
|
+
"label", "story_id", "statement_id", "split", "id",
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def _resolve_id(record: dict, line_no: int) -> str:
|
|
213
|
+
"""An explicit ``"id"`` if present; else a story/statement-derived id
|
|
214
|
+
(optionally split-qualified) built from ``"story_id"``/``"statement_id"``
|
|
215
|
+
(present in this adapter's own JSONL schema, see module docstring); else
|
|
216
|
+
a positional fallback — every example is addressable either way.
|
|
217
|
+
"""
|
|
218
|
+
explicit = record.get("id")
|
|
219
|
+
if explicit is not None:
|
|
220
|
+
return str(explicit)
|
|
221
|
+
|
|
222
|
+
story_id = record.get("story_id")
|
|
223
|
+
statement_id = record.get("statement_id")
|
|
224
|
+
if story_id is not None and statement_id is not None:
|
|
225
|
+
split = record.get("split")
|
|
226
|
+
if split is not None:
|
|
227
|
+
return f"logicnli:{split}:{story_id}:{statement_id}"
|
|
228
|
+
return f"logicnli:{story_id}:{statement_id}"
|
|
229
|
+
|
|
230
|
+
return f"logicnli:{line_no}"
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def _example_from_record(record: dict, line_no: int,
|
|
234
|
+
known_bad_ids: FrozenSet[str]) -> DatasetExample:
|
|
235
|
+
premises_nl = tuple(record.get("premises_nl") or ())
|
|
236
|
+
hypothesis_nl = record.get("hypothesis_nl")
|
|
237
|
+
label = record.get("label")
|
|
238
|
+
example_id = _resolve_id(record, line_no)
|
|
239
|
+
|
|
240
|
+
meta = {k: v for k, v in record.items() if k not in _RECORD_KEYS}
|
|
241
|
+
meta["premises_logic"] = record.get("premises_logic")
|
|
242
|
+
meta["hypothesis_logic"] = record.get("hypothesis_logic")
|
|
243
|
+
meta["story_id"] = record.get("story_id")
|
|
244
|
+
meta["statement_id"] = record.get("statement_id")
|
|
245
|
+
meta["split"] = record.get("split")
|
|
246
|
+
meta["line_no"] = line_no
|
|
247
|
+
|
|
248
|
+
return DatasetExample(
|
|
249
|
+
id=example_id,
|
|
250
|
+
nl_premises=premises_nl,
|
|
251
|
+
fol_premises=(), # see module docstring: never compiled
|
|
252
|
+
nl_conclusion=hypothesis_nl,
|
|
253
|
+
fol_conclusion=None, # see module docstring: never compiled
|
|
254
|
+
label=label,
|
|
255
|
+
known_bad=example_id in known_bad_ids,
|
|
256
|
+
meta=meta,
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def load_logicnli(path: Union[str, Path], *,
|
|
261
|
+
known_bad_ids: FrozenSet[str] = frozenset()) -> Iterator[DatasetExample]:
|
|
262
|
+
"""Stream :class:`~unicode_logic_kit.eval.datasets.DatasetExample` from a
|
|
263
|
+
local LogicNLI JSONL file in THIS ADAPTER's OWN schema (see module
|
|
264
|
+
docstring for the field list and the recipe to produce it from the
|
|
265
|
+
downloaded GitHub original).
|
|
266
|
+
|
|
267
|
+
Args:
|
|
268
|
+
path: path to a local ``.jsonl`` file — one row per LogicNLI
|
|
269
|
+
statement/hypothesis, in this adapter's own schema (module
|
|
270
|
+
docstring). NEVER downloaded by this function; obtain and
|
|
271
|
+
convert the data yourself from
|
|
272
|
+
https://github.com/omnilabNLP/LogicNLI.
|
|
273
|
+
known_bad_ids: ids (see :func:`_resolve_id`) whose annotation is
|
|
274
|
+
known to be broken. Every yielded example with a matching id
|
|
275
|
+
gets ``known_bad=True``; everything else gets ``known_bad=False``.
|
|
276
|
+
Defaults to an empty set.
|
|
277
|
+
|
|
278
|
+
Yields:
|
|
279
|
+
One :class:`~unicode_logic_kit.eval.datasets.DatasetExample` per
|
|
280
|
+
non-blank JSONL line, in file order. ``fol_premises`` is always
|
|
281
|
+
``()`` and ``fol_conclusion`` is always ``None`` — this dataset has
|
|
282
|
+
no ready-made FOL formula strings, only a structured symbolic
|
|
283
|
+
annotation this adapter deliberately does not compile into one (see
|
|
284
|
+
module docstring); that raw annotation survives, uninterpreted, in
|
|
285
|
+
``meta["premises_logic"]``/``meta["hypothesis_logic"]``. A record
|
|
286
|
+
missing an expected key yields ``None``/``()`` for that field rather
|
|
287
|
+
than raising — the same "missing key -> default, not exception"
|
|
288
|
+
convention :func:`~unicode_logic_kit.eval.datasets.folio.load_folio`
|
|
289
|
+
documents.
|
|
290
|
+
|
|
291
|
+
Raises:
|
|
292
|
+
FileNotFoundError: ``path`` does not exist.
|
|
293
|
+
json.JSONDecodeError: a non-blank line is not valid JSON — raised,
|
|
294
|
+
not swallowed (a malformed dataset file must fail loudly).
|
|
295
|
+
"""
|
|
296
|
+
path = Path(path)
|
|
297
|
+
with path.open("r", encoding="utf-8") as fh:
|
|
298
|
+
for line_no, raw_line in enumerate(fh):
|
|
299
|
+
line = raw_line.strip()
|
|
300
|
+
if not line:
|
|
301
|
+
continue
|
|
302
|
+
record = json.loads(line)
|
|
303
|
+
yield _example_from_record(record, line_no, known_bad_ids)
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"""Adapter for the MALLS dataset (Yang et al., "Harnessing the Power of Large
|
|
2
|
+
Language Models for Natural Language to First-Order Logic Translation") —
|
|
3
|
+
local JSONL only, no network access.
|
|
4
|
+
|
|
5
|
+
Source and verified schema
|
|
6
|
+
---------------------------
|
|
7
|
+
Source: https://huggingface.co/datasets/yuan-yang/MALLS-v0 (unauthenticated;
|
|
8
|
+
verified directly via the Hugging Face datasets-server rows API). Each record
|
|
9
|
+
is a flat JSON object with exactly two keys:
|
|
10
|
+
|
|
11
|
+
* ``"NL"`` — ``str``, one natural-language statement.
|
|
12
|
+
* ``"FOL"`` — ``str``, its FOL translation (GPT-4-generated, then a subset
|
|
13
|
+
auto/human-verified — see the paper for the verification pipeline; MALLS
|
|
14
|
+
is a straight NL-to-FOL TRANSLATION pair, not a premise/conclusion
|
|
15
|
+
entailment example the way FOLIO is).
|
|
16
|
+
|
|
17
|
+
MALLS has NO id field, NO premises/conclusion structure, and NO entailment
|
|
18
|
+
label — it is a flat bag of (statement, formula) pairs. This adapter maps
|
|
19
|
+
that onto :class:`~unicode_logic_kit.eval.datasets.DatasetExample` as follows,
|
|
20
|
+
a deliberate design choice (not something verified from the source, since
|
|
21
|
+
the source has no such structure to verify against):
|
|
22
|
+
|
|
23
|
+
* ``nl_conclusion`` / ``fol_conclusion`` carry the ``"NL"`` / ``"FOL"``
|
|
24
|
+
values — "conclusion" here means "the target formula the translation task
|
|
25
|
+
is producing", which is the natural reading for a single-sentence
|
|
26
|
+
translation pair (as opposed to ``nl_premises``/``fol_premises``, which
|
|
27
|
+
would imply an entailment structure MALLS does not have).
|
|
28
|
+
* ``nl_premises`` / ``fol_premises`` are always ``()`` (empty tuples).
|
|
29
|
+
* ``label`` is always ``None`` (MALLS carries no entailment label).
|
|
30
|
+
|
|
31
|
+
Upstream MALLS is distributed as JSON ARRAY files (e.g.
|
|
32
|
+
``MALLS-v0.1-train.json``, ``MALLS-v0.json`` — one big ``[...]`` list), NOT
|
|
33
|
+
as JSONL. This loader, like :func:`~unicode_logic_kit.eval.datasets.folio.load_folio`,
|
|
34
|
+
reads local JSONL (one JSON object per line) for a uniform, streaming-friendly
|
|
35
|
+
adapter surface across both datasets in this subpackage — convert an upstream
|
|
36
|
+
MALLS file to JSONL first (e.g. ``jq -c '.[]' MALLS-v0.1-train.json >
|
|
37
|
+
malls.jsonl``) before calling :func:`load_malls`.
|
|
38
|
+
|
|
39
|
+
License: **CC-BY-NC-4.0** (non-commercial), per the dataset card. Because the
|
|
40
|
+
FOL annotations were generated with GPT-4, the dataset card also states it
|
|
41
|
+
"abides by the policy of OpenAI" (https://openai.com/policies/terms-of-use)
|
|
42
|
+
— both the license's non-commercial clause and that usage-policy pointer
|
|
43
|
+
apply to any use of the actual MALLS data (this loader itself has no
|
|
44
|
+
license implications beyond reading a local file the caller already
|
|
45
|
+
obtained; it never downloads or redistributes MALLS data).
|
|
46
|
+
|
|
47
|
+
This module never downloads anything — obtain and convert the data yourself
|
|
48
|
+
and pass its local JSONL path to :func:`load_malls`.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
import json
|
|
52
|
+
from pathlib import Path
|
|
53
|
+
from typing import FrozenSet, Iterator, Union
|
|
54
|
+
|
|
55
|
+
from ._base import DatasetExample, _register_dataset_info
|
|
56
|
+
|
|
57
|
+
__all__ = ["load_malls"]
|
|
58
|
+
|
|
59
|
+
_register_dataset_info(
|
|
60
|
+
"malls",
|
|
61
|
+
license=(
|
|
62
|
+
"CC-BY-NC-4.0 (non-commercial); data is GPT-4-generated, so usage is "
|
|
63
|
+
"additionally subject to OpenAI's usage policies, "
|
|
64
|
+
"https://openai.com/policies/terms-of-use"
|
|
65
|
+
),
|
|
66
|
+
source_url="https://huggingface.co/datasets/yuan-yang/MALLS-v0",
|
|
67
|
+
citation_hint=(
|
|
68
|
+
"Yang, Yuan, et al. \"Harnessing the Power of Large Language Models "
|
|
69
|
+
"for Natural Language to First-Order Logic Translation.\" "
|
|
70
|
+
"arXiv:2305.15541."
|
|
71
|
+
),
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _example_from_record(record: dict, line_no: int,
|
|
76
|
+
known_bad_ids: FrozenSet[str]) -> DatasetExample:
|
|
77
|
+
nl = record.get("NL")
|
|
78
|
+
fol = record.get("FOL")
|
|
79
|
+
# MALLS has no native id field (see module docstring); some downstream
|
|
80
|
+
# re-exports might add one, so honour it opportunistically before
|
|
81
|
+
# falling back to a positional id.
|
|
82
|
+
raw_id = record.get("id")
|
|
83
|
+
example_id = str(raw_id) if raw_id is not None else f"malls:{line_no}"
|
|
84
|
+
|
|
85
|
+
meta = {k: v for k, v in record.items() if k not in ("NL", "FOL", "id")}
|
|
86
|
+
meta["line_no"] = line_no
|
|
87
|
+
|
|
88
|
+
return DatasetExample(
|
|
89
|
+
id=example_id,
|
|
90
|
+
nl_premises=(),
|
|
91
|
+
fol_premises=(),
|
|
92
|
+
nl_conclusion=nl,
|
|
93
|
+
fol_conclusion=fol,
|
|
94
|
+
label=None,
|
|
95
|
+
known_bad=example_id in known_bad_ids,
|
|
96
|
+
meta=meta,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def load_malls(path: Union[str, Path], *,
|
|
101
|
+
known_bad_ids: FrozenSet[str] = frozenset()) -> Iterator[DatasetExample]:
|
|
102
|
+
"""Stream :class:`~unicode_logic_kit.eval.datasets.DatasetExample` from a
|
|
103
|
+
local MALLS JSONL file.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
path: path to a local ``.jsonl`` file — one ``{"NL": ..., "FOL": ...}``
|
|
107
|
+
object per non-blank line (see module docstring for converting
|
|
108
|
+
the upstream JSON-array distribution to this format). NEVER
|
|
109
|
+
downloaded by this function.
|
|
110
|
+
known_bad_ids: ids (the record's own ``"id"`` if present, else the
|
|
111
|
+
positional fallback ``f"malls:{line_no}"``) whose ``"FOL"``
|
|
112
|
+
translation is known to be broken. Every yielded example with a
|
|
113
|
+
matching id gets ``known_bad=True``. Defaults to an empty set.
|
|
114
|
+
|
|
115
|
+
Yields:
|
|
116
|
+
One :class:`~unicode_logic_kit.eval.datasets.DatasetExample` per
|
|
117
|
+
non-blank JSONL line, in file order, with ``nl_conclusion``/
|
|
118
|
+
``fol_conclusion`` set from ``"NL"``/``"FOL"`` and
|
|
119
|
+
``nl_premises``/``fol_premises`` empty (see module docstring for why).
|
|
120
|
+
|
|
121
|
+
Raises:
|
|
122
|
+
FileNotFoundError: ``path`` does not exist.
|
|
123
|
+
json.JSONDecodeError: a non-blank line is not valid JSON — raised,
|
|
124
|
+
not swallowed (a malformed dataset file must fail loudly).
|
|
125
|
+
"""
|
|
126
|
+
path = Path(path)
|
|
127
|
+
with path.open("r", encoding="utf-8") as fh:
|
|
128
|
+
for line_no, raw_line in enumerate(fh):
|
|
129
|
+
line = raw_line.strip()
|
|
130
|
+
if not line:
|
|
131
|
+
continue
|
|
132
|
+
record = json.loads(line)
|
|
133
|
+
yield _example_from_record(record, line_no, known_bad_ids)
|