A Python reimplementation of LogMap — the logic-based ontology matching and alignment-repair system — with a CPython C extension for its performance-critical kernels.
PyLogMap takes two OWL ontologies and produces a set of mappings (an alignment) between their entities, then repairs that alignment so the merged result stays logically coherent. It reproduces LogMap's behavior (verified against the original Java on the OAEI Conference and Anatomy tracks) and adds extensions for multilingual matching, external-oracle (e.g. LLM) mapping decisions, and mediated matching through any bridge ontologies.
- Install · Quick start · Recipes · Configuration · Output files
- Architecture · Verification · Contributors & references
python -m pip install pylogmapRequires Python ≥ 3.10. A C compiler is optional — without one, PyLogMap uses pure-Python kernels (slower, identical results). Optional backends ship as separate extras (see Extensions):
python -m pip install 'pylogmap[multilingual]' # offline label translation
python -m pip install 'pylogmap[bioportal]' # BioPortal mediating-ontology source
python -m pip install 'pylogmap[llm]' # LogMapLLM oracle plugin
python -m pip install 'pylogmap[rag]' # LLM oracle + semantic RAG encoders
python -m pip install 'pylogmap[plugins]' # all optional pluginsFrom a checkout, use python -m pip install -e '.[dev]' (see Verification).
Match two ontologies and write the alignment to a directory:
pylogmap match onto1.owl onto2.owl -o out/out/ now contains the alignment in three formats plus diagnostics and a manifest
(see Output files). The same thing from Python:
import pylogmap
result = pylogmap.match("onto1.owl", "onto2.owl", output_dir="out")
index = result.index
for m in result.mappings.active():
print(index.iri_for_id(m.src), m.direction.name, index.iri_for_id(m.tgt),
round(m.confidence, 3))
print("unsatisfiable classes after repair:", result.manifest["unsatisfiable_classes"])Without output_dir the result stays in memory; write it later with
from pylogmap.io import write_jsonl then
write_jsonl(result.mappings, "alignment.jsonl", result.index).
pylogmap match a.owl b.owl -o out/ runs the faithful LogMap pipeline: it alternates
matching and logical repair per layer (layered mode). This is what you want in most
cases.
The old LogMap Lite was a stripped-down matcher with no logical repair. In PyLogMap that is simply repair turned off — you keep the better lexical matching and just skip the Dowling–Gallier passes:
pylogmap match a.owl b.owl -o out/ --config lite.toml# lite.toml
clean_dg = false # no logical repair (Lite behaviour)
property_matching = false # classes only, like Lite
instance_matching = falseOr in Python: pylogmap.match("a.owl", "b.owl", PyLogMapConfig(clean_dg=False)).
The old LogMap Bio improved biomedical matching by routing through mediating ontologies downloaded from BioPortal. PyLogMap generalizes this to any set of mediating ontologies you provide — no account needed:
pylogmap match a.owl b.owl -o out/ --mediate reference1.owl reference2.owl mediators/It matches a→each mediator and each mediator→b, composes the mappings that agree
through a shared bridge concept, keeps the well-voted ones, and repairs the union.
For the original BioPortal-backed behavior:
export PYLOGMAP_BIOPORTAL_API_KEY=... # needs pip install 'pylogmap[bioportal]'
pylogmap match a.owl b.owl -o out/ --mediate-bioportal --max-mediators 10See mediation.md.
Give PyLogMap two ontologies and an existing alignment (OAEI RDF, TSV, or JSONL); it
removes/weakens the mappings that make the integration incoherent — the standalone
repair facility, equivalent to Java LogMap's LogMap2_RepairFacility:
pylogmap repair a.owl b.owl alignment.rdf -o out/result = pylogmap.repair_alignment("a.owl", "b.owl", "alignment.rdf", output_dir="out")
print("removed:", len(result.report.removed), "weakened:", len(result.report.weakened))Building the joint index dominates runtime on large ontologies. Build it once, match many times:
pylogmap index a.owl b.owl -o pair.plmx
pylogmap match pair.plmx -o out/
pylogmap repair pair.plmx alignment.rdf -o out/Translate labels into a pivot language (offline OPUS-MT models by default) so differently-languaged ontologies match:
pylogmap fetch-translation-models de en # once, needs pip install 'pylogmap[multilingual]'
pylogmap match german.owl english.owl -o out/ --multilingualSee multilingual.md.
Let an oracle answer the mappings LogMap is uncertain about. PyLogMap exports the uncertain candidates with their surrounding context (labels, synonyms, hierarchy, siblings, attributes); the oracle judges them; PyLogMap re-runs with the answers. The harness works with any external annotator via files:
pylogmap match a.owl b.owl -o out/ --emit-questions # writes out/questions.jsonl
# ... annotate questions.jsonl with your tool → answers.csv (uri1,uri2,true|false) ...
pylogmap match a.owl b.owl -o out/ --oracle answers.csvLogMapLLM built in: the LogMapLLM oracle ships as
an optional plugin (pip install 'pylogmap[llm]') that answers the questions with
any OpenAI-compatible endpoint (OpenRouter, vLLM, SGLang), with optional RAG
few-shot retrieval:
export PYLOGMAP_LLM_API_KEY=... # e.g. an OpenRouter key
pylogmap match a.owl b.owl -o out/ --oracle llm # in-process
pylogmap ask-llm out/questions.jsonl -o answers.jsonl # or offline, file-to-file
pylogmap build-rag-corpus a.owl b.owl train.rdf -o corpus.jsonlThe applied decisions are logged to out/oracle_decisions.jsonl for reproducible
replay, and answers are compatible with the Java LogMapLLM format. See
oracle-llm.md (harness) and
llm-oracle.md (plugin).
Every threshold and toggle lives in the frozen PyLogMapConfig dataclass, with the
same defaults as Java LogMap (good_isub_anchors = 0.98, good_confidence = 0.50,
confidence weights 0.5/0.0/0.3/0.2, …). Pass a TOML file or build the dataclass:
pylogmap match a.owl b.owl -o out/ --config pylogmap.toml --mode sequentialfrom pylogmap.config import PyLogMapConfig
cfg = PyLogMapConfig(mode="sequential", use_stemming=True, instance_matching=False)
result = pylogmap.match("a.owl", "b.owl", cfg)Common knobs: mode (layered default, or sequential = match everything then
repair once), clean_dg (logical repair on/off), property_matching /
instance_matching, use_stemming, output_equivalences_only. Extension settings are
nested tables ([tool.pylogmap.oracle], [tool.pylogmap.mediation], …). The full
field table, each default cross-referenced to the Java line it preserves, is in
pipeline-io.md §5; extension config is in
plugins.md §5.
Each match/repair output directory contains:
| File | Contents |
|---|---|
alignment.rdf |
The alignment in OAEI RDF format (interoperable with other matchers) |
alignment.tsv |
The alignment as tab-separated src tgt relation confidence kind |
alignment.jsonl |
Lossless native format (all fields, re-readable by PyLogMap) |
discarded.tsv, hard-discarded.tsv |
Mappings dropped by matching heuristics |
conflictive.tsv, weakened.tsv |
Mappings removed or narrowed by logical repair |
manifest.json |
Config, kernel backend, per-stage timings and counts, final coherence check |
questions.jsonl |
(--emit-questions only) self-contained uncertain mapping contexts |
oracle_decisions.jsonl |
(external-oracle runs only) replayable verdict log |
--mode, output_equivalences_only, and the output_*_mappings flags control what
is written.
PyLogMap is organized around LogMap's three component types, made explicit and decoupled:
- Indexing turns two OWL ontologies into one joint, integer-indexed structure: lexical inverted files, an interval-labelled class hierarchy for fast subsumption/disjointness queries, and a propositional Horn encoding of the told axioms.
- Matching reads that index and produces scored candidate mappings (exact anchors → stemming/weak candidates → ambiguity decisions → properties → instances).
- Repair removes or weakens the mappings that make the merged theory incoherent (Dowling–Gallier Horn-SAT diagnosis).
Matching and repair never import each other — they communicate only through the shared
data contracts, an architecture enforced in CI by
import-linter. A pipeline orchestrator runs
them interleaved per layer (layered, faithful to Java LogMap) or strictly
sequentially (sequential). The hot kernels (ISUB string similarity, postings
intersection, interval-labelling build/query, disjointness queries, Horn-SAT
propagation) are C, each with a bit-identical pure-Python fallback selected
automatically. Optional plugins attach through injected protocols without the core
depending on them.
| Package | Role | Spec |
|---|---|---|
pylogmap.contracts |
Mapping/MappingSet, the joint OntologyIndex + query API, extension protocols, .plmx serialization |
contracts.md, plugins.md §4 |
pylogmap._kernels |
Backend dispatcher, pure-Python kernels, optional C extension | kernels.md |
pylogmap.lexical |
Tokenization, Paice stemming, normalizers, UMLS tables | indexing.md §2–3 |
pylogmap.indexing |
OWL ingestion (py-horned-owl), joint index, interval labelling, overlapping/modules | indexing.md |
pylogmap.matching |
Anchors, candidates, confidence, ambiguity, property/instance stages | matching.md |
pylogmap.repair |
Horn encoding, Dowling–Gallier diagnosis, repair plans, standalone facility | repair.md |
pylogmap.io |
OAEI RDF, TSV, native JSONL; run outputs; P/R evaluation | pipeline-io.md §4 |
pylogmap.pipeline |
Layered/sequential orchestration, oracle harness, mediation engine, match()/repair_alignment() |
pipeline-io.md §1–3 |
pylogmap.plugins |
Optional translation backends + BioPortal mediator source | plugins.md |
The design handout starts at specs/SPEC.md (architecture, import
rules, what was ported vs dropped from the Java tree). Implementation is tracked as
work packages under specs/workpackages/.
The original Java implementation is vendored untouched in
logmap-matcher/ and used as the behavioral reference and parity
oracle.
From a checkout:
python -m pip install -e '.[dev]'
pytest -m 'not parity and not nightly and not external' # unit + property tests
PYLOGMAP_PURE_PYTHON=1 pytest -m 'not parity and not nightly and not external'
ruff check src tests benchmarks && mypy && lint-imports # static gatesThe parity suite compares PyLogMap against the bundled Java reference on the OAEI
Conference track (21 committed oracle bundles under tests/data/oracle/):
python tests/data/fetch_datasets.py conference
(cd logmap-matcher && mvn package -DskipTests)
pytest -m parity tests/parity/test_index_counts.py tests/parity/test_conference.py
pytest -m parity tests/parity/test_repair_facility.pyAnatomy data and its oracle are local/nightly; commands are in
specs/verification.md. Live-backend plugin tests are marked
-m external and run only when the relevant credentials are present.
| Gate | Result |
|---|---|
| P1–P3 Conference (21 ontology pairs) | Pass: 21/21 with C and forced-Python kernels |
| P4 standalone repair | Pass with both kernel backends |
| P5 OAEI RDF interoperability | Pass in both directions on all 21 pairs |
| P6 Anatomy | Pass: anchors within 1.57%; Jaccard 0.9852; F-score delta 0.00124; zero final D&G conflicts |
On the Anatomy pair, layered mode with C kernels takes 10.29 s and 270 MB peak RSS,
versus 11.09 s for Java on the same machine; the pure-Python kernels take 112.34 s and
produce the same alignment. Full numbers in
benchmarks/BASELINE.md.
Contributors: Pedro Giesteira Cotovio, Jon Dilworth, Ernesto Jiménez-Ruiz.
PyLogMap reimplements the algorithms of LogMap, created by Ernesto Jiménez-Ruiz and
Bernardo Cuenca Grau at the University of Oxford and continued at City St George's,
University of London. Citation metadata for this repository is in
CITATION.cff. If you use PyLogMap in academic work, please cite the
original LogMap papers:
-
Ernesto Jiménez-Ruiz, Bernardo Cuenca Grau. LogMap: Logic-based and Scalable Ontology Matching. In: The Semantic Web – ISWC 2011. LNCS 7031, pp. 273–288. Springer, 2011. doi:10.1007/978-3-642-25073-6_18 (PDF)
-
Ernesto Jiménez-Ruiz, Bernardo Cuenca Grau, Yujiao Zhou, Ian Horrocks. Large-scale Interactive Ontology Matching: Algorithms and Implementation. In: ECAI 2012. Frontiers in AI and Applications, vol. 242, pp. 444–449. IOS Press, 2012. doi:10.3233/978-1-61499-098-7-444 (PDF)
-
Sviatoslav Lushnei, Dmytro Shumskyi, Severyn Shykula, Ernesto Jiménez-Ruiz, Artur d’Avila Garcez. Large Language Models as Oracles for Ontology Alignment. In: Proceedings of the 19th Conference of the European Chapter of the Association for Computational Linguistics (Volume 1: Long Papers), pp. 2435–2449. Association for Computational Linguistics, 2026. doi:10.18653/v1/2026.eacl-long.110 (PDF)
The LLM harness follows the LogMapLLM line of work; the mediation and repair components draw on the LogMapBio and conservativity-repair literature listed in the original repository's README.
Apache-2.0. See LICENSE.