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,242 @@
|
|
|
1
|
+
"""Adapter for the Parallel Meaning Bank (PMB): SBN documents, read through
|
|
2
|
+
:mod:`unicode_logic_kit.drt` into gold FOL via :func:`~unicode_logic_kit.drt.parser.parse_sbn`
|
|
3
|
+
and :func:`~unicode_logic_kit.drt.export.drs_to_fol`.
|
|
4
|
+
|
|
5
|
+
Unlike every other adapter in this package, PMB carries no ready-made NL/FOL pair file:
|
|
6
|
+
its unit of data is ONE DIRECTORY PER DOCUMENT (``p<NN>/d<NNNN>/``), holding the DRS in
|
|
7
|
+
SBN notation (``<lang>.drs.sbn``) alongside the raw sentence(s) it annotates
|
|
8
|
+
(``<lang>.raw``) and a few other sibling files this adapter does not read. This module's
|
|
9
|
+
whole job is producing gold FOL from the SBN side; the NL side is carried through
|
|
10
|
+
best-effort, since that is what the sibling file happens to contain.
|
|
11
|
+
|
|
12
|
+
Source, release layout, and license (verified 2026-09-17 against a local pmb-5.1.0
|
|
13
|
+
extraction's own ``licenses/`` directory)
|
|
14
|
+
--------------------------------------------------------------------------------------
|
|
15
|
+
Source: https://pmb.let.rug.nl/data.php (releases, ``pmb-<version>.zip``). Like every
|
|
16
|
+
loader in this package, :func:`load_pmb` reads LOCAL files the caller already obtained —
|
|
17
|
+
nothing here downloads anything.
|
|
18
|
+
|
|
19
|
+
Each PMB release's ``data/<lang>/gold/p<NN>/d<NNNN>/`` directory is one annotated
|
|
20
|
+
document, ``<lang>`` a two-letter code (``en``, ``de``, ``it``, ``nl``, ...). This
|
|
21
|
+
adapter reads whichever ``<lang>.drs.sbn`` files it is given or finds; it does not
|
|
22
|
+
special-case English.
|
|
23
|
+
|
|
24
|
+
**License is TWO-LAYERED, and the two layers are NOT the same license** (the raw
|
|
25
|
+
proposal that motivated this module conflated them — corrected here):
|
|
26
|
+
|
|
27
|
+
* The PMB **annotations** (the DRS/SBN layer this module actually parses) are
|
|
28
|
+
Open Data Commons Attribution License v1.0 (ODC-BY —
|
|
29
|
+
https://opendatacommons.org/licenses/by/1.0/), stated plainly in the release's own
|
|
30
|
+
``licenses/PMB_LICENSE.txt``: share/create/adapt freely, attribution required.
|
|
31
|
+
* The **raw texts** (``<lang>.raw``, what :func:`load_pmb` puts in ``nl_conclusion``)
|
|
32
|
+
are explicitly NOT covered by ODC-BY: the same ``PMB_LICENSE.txt`` says each is
|
|
33
|
+
"published under their respective license terms, as noted in their accompanying .met
|
|
34
|
+
files" — but in the actual pmb-5.1.0 release, a document's ``.met`` file records only
|
|
35
|
+
a ``subcorpus:`` label (``Tatoeba``, ``SICK``, ``RTE``, ``TREC2002``/``TREC2003``,
|
|
36
|
+
``INTERSECT``, ``GMB``, ...) and a ``source:`` URL, never an explicit license string —
|
|
37
|
+
so a caller who wants to REDISTRIBUTE ``nl_conclusion`` text must trace that source
|
|
38
|
+
themselves (the release's ``licenses/*-README.txt`` files document several of the
|
|
39
|
+
subcorpora's own terms, e.g. ``SICK-README.txt``, ``Tatoeba_LICENSE.txt``). This
|
|
40
|
+
adapter reads a document's ``.met`` file for neither field (out of scope: neither the
|
|
41
|
+
DRS nor the label this module produces depends on it) and copies no PMB file into this
|
|
42
|
+
repository — a caller redistributing what :func:`load_pmb` yields is bound by the same
|
|
43
|
+
two-layer license above, not a blanket statement this module could truthfully make.
|
|
44
|
+
|
|
45
|
+
How much of the SBN release does :func:`parse_sbn` actually accept? — measured, not
|
|
46
|
+
guessed
|
|
47
|
+
------------------------------------------------------------------------------------
|
|
48
|
+
Run against pmb-5.1.0's complete English gold release, all 12053
|
|
49
|
+
``data/en/gold/p*/d*/en.drs.sbn`` files (2026-09-17): **9624 / 12053 (79.8%) parse AND
|
|
50
|
+
round-trip** (``drs_to_fol(parse_sbn(text)[0]).to_unicode_str()`` re-parses via
|
|
51
|
+
:func:`unicode_logic_kit.api.parse_any` to the byte-identical string). Every one of the
|
|
52
|
+
remaining 2429 raises :class:`~unicode_logic_kit.drt.parser.SBNSyntaxError` naming an
|
|
53
|
+
out-of-scope construct — NONE raises anything else (no crash). By construct:
|
|
54
|
+
|
|
55
|
+
* 1123 — a WILDCARD role target (``?``, ``+``, or bare ``-``): boxer's own placeholder
|
|
56
|
+
for a wh-question's unresolved filler ("which singer" -> ``Name ?``) or a vague
|
|
57
|
+
comparative degree ("long hair" -> ``Value +``). Neither has a determinate DRS reading.
|
|
58
|
+
* 953 — a box-operator this subset does not support: the SDRT discourse relations
|
|
59
|
+
(``CONTINUATION`` 448, ``CONTRAST`` 91, ``CONJUNCTION`` 78, ``CONSEQUENCE`` 50,
|
|
60
|
+
``EXPLANATION`` 42, ``CONDITION`` 5, ``PRECONDITION`` 4, ``RESULT`` 4,
|
|
61
|
+
``ALTERNATION`` 2, ``COMMENTARY`` 1, ``ELABORATION`` 1) and the two modal operators
|
|
62
|
+
(``POSSIBILITY`` 174, ``NECESSITY`` 53) — this kit's DRS conditions have no
|
|
63
|
+
discourse-relation or modal-box reading.
|
|
64
|
+
* 162 — a clock-time constant (``ClockTime 14:30``): a genuine PMB constant kind this
|
|
65
|
+
subset's bare-constant widening (deictic words, integers) does not cover.
|
|
66
|
+
* 116 — a sense token not of the WordNet form ``lemma.pos.NN`` (this subset's
|
|
67
|
+
``LEMMA`` is ``[a-z][a-z_]*``, see :mod:`unicode_logic_kit.drt.parser`'s module
|
|
68
|
+
docstring), split three ways: 95 with a hyphen inside the lemma (``ping-pong.n.01``,
|
|
69
|
+
``t-shirt.n.01``, ``well-known.a.01``, ...) — a real WordNet compounding convention
|
|
70
|
+
this module does not widen ``LEMMA`` for, unlike the (deliberately narrower) role-name
|
|
71
|
+
hyphen it does accept; 19 with an apostrophe/possessive inside the lemma
|
|
72
|
+
(``parkinson's_disease.n.01``, ``ladies'_room.n.01``, ``alzheimer's.n.01``,
|
|
73
|
+
``old_wives'_tale.n.01``, ...) — a DIFFERENT WordNet convention from hyphenation, not
|
|
74
|
+
a subcase of it; and 2 with a digit inside the lemma (``co2.n.01``, ``fiat_500.n.01``).
|
|
75
|
+
* a long tail (75) of one-off constants this subset does not parse: 10 ``YearOfCentury``
|
|
76
|
+
decade constants (``'198X'``), 21 sports-score values (``6-2``), 16 day-of-week names
|
|
77
|
+
(``monday``), 12 decimal and 4 fraction ``Quantity`` values (``3.4``, ``3/4``), 10
|
|
78
|
+
single-letter grade values, one role-hook offset that points outside its document, and
|
|
79
|
+
one DRS accessibility violation (:meth:`~unicode_logic_kit.drt.nodes.DRS.validate`
|
|
80
|
+
refusing a role target that escapes its own negation scope).
|
|
81
|
+
|
|
82
|
+
This is a ROBUSTNESS/coverage measurement, not a translation-ACCURACY one: PMB ships no
|
|
83
|
+
independent gold FOL to compare the 9624 successes against, so "correct" here means
|
|
84
|
+
"parses under this subset's own documented grammar and round-trips through this kit's
|
|
85
|
+
FOL printer/parser" — see ``tests/test_datasets_pmb.py`` for the differential this
|
|
86
|
+
number comes from, gated behind the ``UFK_PMB_SBN_DIR`` environment variable so it never
|
|
87
|
+
runs without a real, locally-extracted release.
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
from pathlib import Path
|
|
91
|
+
from typing import FrozenSet, Iterable, Iterator, Optional, Tuple, Union
|
|
92
|
+
|
|
93
|
+
from ._base import DatasetExample, _register_dataset_info
|
|
94
|
+
from ...drt.export import drs_to_fol
|
|
95
|
+
from ...drt.parser import SBNSyntaxError, parse_sbn
|
|
96
|
+
|
|
97
|
+
__all__ = ["load_pmb"]
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
_register_dataset_info(
|
|
101
|
+
"pmb",
|
|
102
|
+
license=(
|
|
103
|
+
"TWO layers, not one (see the module docstring for the full derivation): the "
|
|
104
|
+
"PMB ANNOTATIONS (the DRS/SBN layer this loader parses) are ODC-BY 1.0 "
|
|
105
|
+
"(https://opendatacommons.org/licenses/by/1.0/, attribution required) per the "
|
|
106
|
+
"release's own licenses/PMB_LICENSE.txt (verified 2026-09-17); the RAW TEXTS "
|
|
107
|
+
"(nl_conclusion) are explicitly NOT ODC-BY -- PMB_LICENSE.txt defers to each "
|
|
108
|
+
"document's own .met file, which in practice records only a subcorpus label "
|
|
109
|
+
"and a source URL, never an explicit license string, so redistributing raw "
|
|
110
|
+
"sentence text requires tracing that source yourself."
|
|
111
|
+
),
|
|
112
|
+
source_url="https://pmb.let.rug.nl/data.php",
|
|
113
|
+
citation_hint=(
|
|
114
|
+
'Abzianidze et al., "The Parallel Meaning Bank: Towards a Multilingual Corpus '
|
|
115
|
+
'of Translations Annotated with Compositional Meaning Representations", '
|
|
116
|
+
"EACL 2017."
|
|
117
|
+
),
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def _iter_sbn_paths(paths: Union[str, Path, Iterable[Union[str, Path]]]) -> Iterator[Path]:
|
|
122
|
+
"""Normalize ``paths`` (see :func:`load_pmb`) into a sorted stream of ``.drs.sbn``
|
|
123
|
+
file paths: a single directory is WALKED for PMB's own release layout
|
|
124
|
+
(``p<NN>/d<NNNN>/<lang>.drs.sbn``, any depth/part/language); anything else is
|
|
125
|
+
treated as an iterable of file paths the caller already obtained."""
|
|
126
|
+
if isinstance(paths, (str, Path)):
|
|
127
|
+
root = Path(paths)
|
|
128
|
+
if not root.is_dir():
|
|
129
|
+
raise ValueError(
|
|
130
|
+
f"pmb: {root} is not a directory to walk — pass an iterable of "
|
|
131
|
+
f".drs.sbn file paths instead, or a real PMB release directory")
|
|
132
|
+
yield from sorted(root.rglob("*.drs.sbn"))
|
|
133
|
+
return
|
|
134
|
+
for p in paths:
|
|
135
|
+
yield Path(p)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def _doc_id(path: Path) -> Tuple[str, str, str]:
|
|
139
|
+
"""PMB's own ``p<NN>/d<NNNN>`` document identifier, read off ``path``'s two parent
|
|
140
|
+
directories (the DOCUMENT directory, then the PART directory it sits in) — the
|
|
141
|
+
release's own addressing scheme, not a positional fallback."""
|
|
142
|
+
doc_dir = path.parent.name
|
|
143
|
+
part_dir = path.parent.parent.name
|
|
144
|
+
return f"{part_dir}/{doc_dir}", part_dir, doc_dir
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def _sibling_raw_text(sbn_path: Path) -> Optional[str]:
|
|
148
|
+
"""The sentence(s) ``sbn_path`` annotates, read from the sibling ``<lang>.raw``
|
|
149
|
+
file PMB ships alongside every ``<lang>.drs.sbn`` — BEST-EFFORT: ``None`` if that
|
|
150
|
+
file is missing or empty (never raised; a missing raw sibling says nothing about
|
|
151
|
+
whether the SBN itself, which is what this adapter is really reading, is usable)."""
|
|
152
|
+
name = sbn_path.name
|
|
153
|
+
if not name.endswith(".drs.sbn"):
|
|
154
|
+
return None
|
|
155
|
+
lang = name[: -len(".drs.sbn")]
|
|
156
|
+
raw_path = sbn_path.with_name(f"{lang}.raw")
|
|
157
|
+
if not raw_path.is_file():
|
|
158
|
+
return None
|
|
159
|
+
text = raw_path.read_text(encoding="utf-8").strip()
|
|
160
|
+
return text or None
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def load_pmb(paths: Union[str, Path, Iterable[Union[str, Path]]], *,
|
|
164
|
+
known_bad_ids: Optional[FrozenSet[str]] = None,
|
|
165
|
+
) -> Iterator[DatasetExample]:
|
|
166
|
+
"""Read PMB SBN documents into :class:`DatasetExample` objects, one per document.
|
|
167
|
+
|
|
168
|
+
Field mapping: ``id`` = the ``p<NN>/d<NNNN>`` fragment PMB itself addresses the
|
|
169
|
+
document by; ``nl_premises``/``fol_premises`` are always ``()`` (PMB annotates
|
|
170
|
+
single documents, not premise/conclusion pairs); ``nl_conclusion`` = the sibling
|
|
171
|
+
``<lang>.raw`` text (best-effort — see :func:`_sibling_raw_text` — ``None`` if
|
|
172
|
+
absent); ``fol_conclusion`` = ``drs_to_fol(parse_sbn(text)[0]).to_unicode_str()``;
|
|
173
|
+
``label`` is always ``None`` (PMB carries no entailment/classification label).
|
|
174
|
+
|
|
175
|
+
A document whose ``parse_sbn`` call raises
|
|
176
|
+
:class:`~unicode_logic_kit.drt.parser.SBNSyntaxError` (see the module docstring for
|
|
177
|
+
how common this is, and why) is NEVER silently dropped: it still yields a
|
|
178
|
+
:class:`DatasetExample`, with ``fol_conclusion=None`` (the same "nothing to check"
|
|
179
|
+
convention :mod:`~unicode_logic_kit.eval.datasets.fracas` uses for its four
|
|
180
|
+
question-less problems) and the refusal's message recorded verbatim in
|
|
181
|
+
``meta["parse_error"]`` — the SAME "refuse loudly, never approximate" contract
|
|
182
|
+
``parse_sbn`` itself follows, carried one level up instead of raised out of this
|
|
183
|
+
generator (which would abort the whole iteration on the FIRST bad document, useless
|
|
184
|
+
for a corpus of thousands).
|
|
185
|
+
|
|
186
|
+
``meta`` also carries ``part``/``doc`` (the two path components ``id`` is built
|
|
187
|
+
from), ``lang`` (the language code ``<lang>.drs.sbn`` was read from), and, on a
|
|
188
|
+
successful parse, ``sbn_mapping`` (:meth:`~unicode_logic_kit.drt.parser.SBNMapping.to_dict`
|
|
189
|
+
— the sense-token/quoted-constant sanitization :func:`parse_sbn` applied, ``None``
|
|
190
|
+
when parsing failed).
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
paths: EITHER a single local directory to WALK for PMB's own release layout
|
|
194
|
+
(``p<NN>/d<NNNN>/<lang>.drs.sbn``, any language/part, any depth), OR an
|
|
195
|
+
iterable of local ``.drs.sbn`` file paths the caller already obtained.
|
|
196
|
+
Nothing here downloads anything, matching every other adapter in this
|
|
197
|
+
package.
|
|
198
|
+
known_bad_ids: ids (in the ``"pNN/dNNNN"`` form) to flag as ``known_bad`` — the
|
|
199
|
+
same caller-curated mechanic every adapter has; independent of, and not
|
|
200
|
+
inferred from, a document's own ``parse_error``.
|
|
201
|
+
|
|
202
|
+
Raises:
|
|
203
|
+
ValueError: ``paths`` is a single path that is not a directory, or the same
|
|
204
|
+
document id is produced twice (a caller data-integrity problem — e.g. two
|
|
205
|
+
different release trees passed together — named rather than silently
|
|
206
|
+
merged).
|
|
207
|
+
"""
|
|
208
|
+
known_bad = frozenset(known_bad_ids) if known_bad_ids else frozenset()
|
|
209
|
+
seen: set = set()
|
|
210
|
+
|
|
211
|
+
for sbn_path in _iter_sbn_paths(paths):
|
|
212
|
+
example_id, part, doc = _doc_id(sbn_path)
|
|
213
|
+
if example_id in seen:
|
|
214
|
+
raise ValueError(
|
|
215
|
+
f"pmb: duplicate document id {example_id!r} (from {sbn_path}) — "
|
|
216
|
+
f"the same p<NN>/d<NNNN> was produced twice")
|
|
217
|
+
seen.add(example_id)
|
|
218
|
+
|
|
219
|
+
lang = sbn_path.name[: -len(".drs.sbn")] if sbn_path.name.endswith(".drs.sbn") else None
|
|
220
|
+
text = sbn_path.read_text(encoding="utf-8")
|
|
221
|
+
nl_conclusion = _sibling_raw_text(sbn_path)
|
|
222
|
+
|
|
223
|
+
meta: dict = {"part": part, "doc": doc, "lang": lang,
|
|
224
|
+
"sbn_mapping": None, "parse_error": None}
|
|
225
|
+
fol_conclusion: Optional[str] = None
|
|
226
|
+
try:
|
|
227
|
+
drs, mapping = parse_sbn(text)
|
|
228
|
+
fol_conclusion = drs_to_fol(drs).to_unicode_str()
|
|
229
|
+
meta["sbn_mapping"] = mapping.to_dict()
|
|
230
|
+
except SBNSyntaxError as e:
|
|
231
|
+
meta["parse_error"] = str(e)
|
|
232
|
+
|
|
233
|
+
yield DatasetExample(
|
|
234
|
+
id=example_id,
|
|
235
|
+
nl_premises=(),
|
|
236
|
+
fol_premises=(),
|
|
237
|
+
nl_conclusion=nl_conclusion,
|
|
238
|
+
fol_conclusion=fol_conclusion,
|
|
239
|
+
label=None,
|
|
240
|
+
known_bad=example_id in known_bad,
|
|
241
|
+
meta=meta,
|
|
242
|
+
)
|