rustdl 0.3.16__tar.gz → 0.3.18__tar.gz
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.
- {rustdl-0.3.16 → rustdl-0.3.18}/Cargo.lock +10 -10
- {rustdl-0.3.16 → rustdl-0.3.18}/Cargo.toml +1 -1
- {rustdl-0.3.16 → rustdl-0.3.18}/PKG-INFO +1 -1
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-core/README.md +9 -5
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-datatypes/README.md +9 -5
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-py/src/classify.rs +35 -13
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/README.md +9 -5
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/src/abox_saturation.rs +11 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/src/classify.rs +24 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/src/lib.rs +2 -2
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/property_assertions.rs +75 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-saturation/README.md +9 -5
- rustdl-0.3.18/crates/owl-dl-tableau/README.md +161 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/python/rustdl/__init__.py +29 -20
- {rustdl-0.3.16 → rustdl-0.3.18}/python/rustdl/__init__.pyi +18 -3
- rustdl-0.3.16/crates/owl-dl-tableau/README.md +0 -157
- {rustdl-0.3.16 → rustdl-0.3.18}/README.md +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-core/Cargo.toml +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-core/src/absorb.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-core/src/approx_saturation.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-core/src/clause.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-core/src/convert.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-core/src/convert_back.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-core/src/data_axioms.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-core/src/definitions.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-core/src/disjunction_existential.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-core/src/ir.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-core/src/lib.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-core/src/locality.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-core/src/normalize.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-core/src/ontology.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-core/src/residual_trigger.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-core/src/role_hierarchy.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-core/src/told.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-core/src/transform.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-core/src/vocab.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-core/tests/concept_pool_proptest.proptest-regressions +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-core/tests/concept_pool_proptest.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-core/tests/convert_round_trip_proptest.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-core/tests/role_hierarchy_proptest.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-datatypes/Cargo.toml +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-datatypes/src/lib.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-py/.gitignore +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-py/Cargo.toml +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-py/README.md +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-py/src/errors.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-py/src/explain.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-py/src/lib.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-py/src/load.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-py/src/materialize.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-py/src/queries.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-py/tests/python/conftest.py +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-py/tests/python/test_classify.py +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-py/tests/python/test_examples.py +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-py/tests/python/test_explain.py +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-py/tests/python/test_manchester.py +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-py/tests/python/test_materialize.py +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-py/tests/python/test_queries.py +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-py/tests/python/test_results.py +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-py/tests/python/test_smoke.py +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-py/tests/python/test_soundness.py +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-py/tests/python/test_stubs.py +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-py/tests/python/test_tutorial.py +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/Cargo.toml +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/examples/embed_classify.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/src/abox_check.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/src/diagnose.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/src/justify.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/src/laconic.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/src/model_cache.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/src/realize.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/src/repair.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/src/union_find.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/abox_consistency.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/abox_sat_fp_probe.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/abox_saturation.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/adaptive_budget.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/anon349_diagnostic.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/approx_saturation_forced_disjunct.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/blocked_disjunction_soundness.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/blocked_disjunction_termination.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/classify_concrete_domain.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/classify_inverse_domain.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/concrete_domain_clash.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/data_properties.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/data_property_assertions.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/datatype_completeness.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/datatype_inconsistency.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/datatype_value_membership.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/decide_pair_probe.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/diagnose_partition.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/disjunctive_existential_marker_fp.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/domain_gci_completeness.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/existential_successors.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/abox/p1_direct_bot.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/abox/p1_no_bot.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/abox/p2_disjoint_different_individuals.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/abox/p2_disjoint_types.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/abox/p3_neg_opa.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/abox/p3_neg_opa_no_clash.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/abox/p3_role_hierarchy_neg_consistent.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/abox/p3_role_hierarchy_neg_inconsistent.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/abox/p4_same_different.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/abox/p4_same_without_different.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/abox/p5_functional_diff.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/abox/p5_functional_same_target.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/abox/p6_asymmetric.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/abox/p6_asymmetric_one_way.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/abox/p6_irreflexive.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/abox/p6_irreflexive_distinct.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/abox/p7_range_compatible.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/abox/p7_range_disjoint.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/datatype/data_cardinality_disjoint.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/datatype/data_property_domain-classified.owx +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/datatype/data_property_domain.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/datatype/datatype_definition-classified.owx +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/datatype/datatype_definition.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/datatype/datatype_facet.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/datatype/functional_data_property.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/datatype/sub_data_property-classified.owx +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/datatype/sub_data_property.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/functional-equiv-some-bug.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/named-pizza-country-bug.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/p2b0-terms-01.txt +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/p2b0-terms-02.txt +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/p2b0-terms-03.txt +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/p2b0-terms-04.txt +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/p2b0-terms-05.txt +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/p2b0-terms-06.txt +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/p2b0-terms-07.txt +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/p2b0-terms-08.txt +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_01.hermit.owx +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_01.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_01.owx +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_02.hermit.owx +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_02.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_02.owx +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_03.hermit.owx +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_03.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_03.owx +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_04.hermit.owx +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_04.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_04.owx +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_05.hermit.owx +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_05.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_05.owx +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_06.hermit.owx +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_06.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_06.owx +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_07.hermit.owx +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_07.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_07.owx +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_08.hermit.owx +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_08.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_08.owx +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/fixtures/phase2b/phase2b-verdicts.log +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/functional_enforcement.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/inverse_cardinality_soundness.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/inverse_symmetric_domain.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/justification.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/konclude_closure_diff.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/label_heuristic_canary.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/laconic_justification.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/object_has_self_domain.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/phase2c_pair_06_canary.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/precompletion_probe_gate.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/real_ontology_corpus.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/repair_suggestions.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/sat_lookahead_gate.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/seed_probe_gate.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/shadow_dep_gate.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/snapshot_phase0_canary.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/subproperty_axioms.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/tautology_skip_canary.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/value_type_disjoint_canary.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/value_type_disjoint_probe.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-reasoner/tests/wedge_consistency.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-saturation/Cargo.toml +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-saturation/src/lib.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-saturation/src/proof.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-saturation/src/seed_sat.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-saturation/tests/fixtures/phase2a_functional_role_canary.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-saturation/tests/fixtures/phase2b_compound_existential_canary.ofn +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-tableau/Cargo.toml +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-tableau/src/counters.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-tableau/src/deps.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-tableau/src/graph.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-tableau/src/hyper.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-tableau/src/lib.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-tableau/src/replay.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-tableau/src/rules.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-tableau/src/saturate.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-tableau/src/search.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-tableau/src/shadow_measures.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-tableau/src/snapshot.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-tableau/src/trail.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-tableau/tests/backprop_risk.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-tableau/tests/replay_driver.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-tableau/tests/replay_roundtrip.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-tableau/tests/sat_lookahead_drop.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-tableau/tests/shadow_dep_probe.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/crates/owl-dl-tableau/tests/snapshot_capture.rs +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/pyproject.toml +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/python/rustdl/_results.py +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/python/rustdl/data/pizza.owl.gz +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/python/rustdl/data/sio.owl.gz +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/python/rustdl/data/sulo.owl.gz +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/python/rustdl/examples.py +0 -0
- {rustdl-0.3.16 → rustdl-0.3.18}/python/rustdl/py.typed +0 -0
|
@@ -1018,7 +1018,7 @@ checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
|
|
|
1018
1018
|
|
|
1019
1019
|
[[package]]
|
|
1020
1020
|
name = "owl-dl-bench"
|
|
1021
|
-
version = "0.3.
|
|
1021
|
+
version = "0.3.18"
|
|
1022
1022
|
dependencies = [
|
|
1023
1023
|
"anyhow",
|
|
1024
1024
|
"clap",
|
|
@@ -1037,7 +1037,7 @@ dependencies = [
|
|
|
1037
1037
|
|
|
1038
1038
|
[[package]]
|
|
1039
1039
|
name = "owl-dl-cb"
|
|
1040
|
-
version = "0.3.
|
|
1040
|
+
version = "0.3.18"
|
|
1041
1041
|
dependencies = [
|
|
1042
1042
|
"hashbrown 0.15.5",
|
|
1043
1043
|
"owl-dl-core",
|
|
@@ -1045,7 +1045,7 @@ dependencies = [
|
|
|
1045
1045
|
|
|
1046
1046
|
[[package]]
|
|
1047
1047
|
name = "owl-dl-cli"
|
|
1048
|
-
version = "0.3.
|
|
1048
|
+
version = "0.3.18"
|
|
1049
1049
|
dependencies = [
|
|
1050
1050
|
"anyhow",
|
|
1051
1051
|
"clap",
|
|
@@ -1058,7 +1058,7 @@ dependencies = [
|
|
|
1058
1058
|
|
|
1059
1059
|
[[package]]
|
|
1060
1060
|
name = "owl-dl-core"
|
|
1061
|
-
version = "0.3.
|
|
1061
|
+
version = "0.3.18"
|
|
1062
1062
|
dependencies = [
|
|
1063
1063
|
"bitvec",
|
|
1064
1064
|
"bumpalo",
|
|
@@ -1072,7 +1072,7 @@ dependencies = [
|
|
|
1072
1072
|
|
|
1073
1073
|
[[package]]
|
|
1074
1074
|
name = "owl-dl-datatypes"
|
|
1075
|
-
version = "0.3.
|
|
1075
|
+
version = "0.3.18"
|
|
1076
1076
|
dependencies = [
|
|
1077
1077
|
"owl-dl-core",
|
|
1078
1078
|
"proptest",
|
|
@@ -1082,7 +1082,7 @@ dependencies = [
|
|
|
1082
1082
|
|
|
1083
1083
|
[[package]]
|
|
1084
1084
|
name = "owl-dl-py"
|
|
1085
|
-
version = "0.3.
|
|
1085
|
+
version = "0.3.18"
|
|
1086
1086
|
dependencies = [
|
|
1087
1087
|
"horned-owl",
|
|
1088
1088
|
"owl-dl-core",
|
|
@@ -1093,7 +1093,7 @@ dependencies = [
|
|
|
1093
1093
|
|
|
1094
1094
|
[[package]]
|
|
1095
1095
|
name = "owl-dl-reasoner"
|
|
1096
|
-
version = "0.3.
|
|
1096
|
+
version = "0.3.18"
|
|
1097
1097
|
dependencies = [
|
|
1098
1098
|
"dashmap",
|
|
1099
1099
|
"fixedbitset",
|
|
@@ -1110,7 +1110,7 @@ dependencies = [
|
|
|
1110
1110
|
|
|
1111
1111
|
[[package]]
|
|
1112
1112
|
name = "owl-dl-saturation"
|
|
1113
|
-
version = "0.3.
|
|
1113
|
+
version = "0.3.18"
|
|
1114
1114
|
dependencies = [
|
|
1115
1115
|
"dashmap",
|
|
1116
1116
|
"fixedbitset",
|
|
@@ -1126,7 +1126,7 @@ dependencies = [
|
|
|
1126
1126
|
|
|
1127
1127
|
[[package]]
|
|
1128
1128
|
name = "owl-dl-tableau"
|
|
1129
|
-
version = "0.3.
|
|
1129
|
+
version = "0.3.18"
|
|
1130
1130
|
dependencies = [
|
|
1131
1131
|
"bitvec",
|
|
1132
1132
|
"bumpalo",
|
|
@@ -2552,7 +2552,7 @@ dependencies = [
|
|
|
2552
2552
|
|
|
2553
2553
|
[[package]]
|
|
2554
2554
|
name = "xtask"
|
|
2555
|
-
version = "0.3.
|
|
2555
|
+
version = "0.3.18"
|
|
2556
2556
|
dependencies = [
|
|
2557
2557
|
"anyhow",
|
|
2558
2558
|
"clap",
|
|
@@ -3,7 +3,7 @@ resolver = "2"
|
|
|
3
3
|
members = ["crates/owl-dl-core", "crates/owl-dl-saturation", "crates/owl-dl-tableau", "crates/owl-dl-datatypes", "crates/owl-dl-reasoner", "crates/owl-dl-py"]
|
|
4
4
|
|
|
5
5
|
[workspace.package]
|
|
6
|
-
version = "0.3.
|
|
6
|
+
version = "0.3.18"
|
|
7
7
|
edition = "2024"
|
|
8
8
|
rust-version = "1.88"
|
|
9
9
|
license = "Apache-2.0 OR MIT"
|
|
@@ -6,7 +6,7 @@ consequence-based **saturation** engine handles the EL-ish fragment, a
|
|
|
6
6
|
orchestrator picks per query. Parsing and the OWL model come from
|
|
7
7
|
[`horned-owl`](https://github.com/phillord/horned-owl).
|
|
8
8
|
|
|
9
|
-
## Status (v0.3.
|
|
9
|
+
## Status (v0.3.16)
|
|
10
10
|
|
|
11
11
|
A working classifier, consistency checker, and instance reasoner for SROIQ(D)
|
|
12
12
|
with first-class data properties. The defining property is **soundness**: every
|
|
@@ -17,10 +17,13 @@ reported subsumption is a genuine entailment.
|
|
|
17
17
|
nothing that neither complete reasoner does.
|
|
18
18
|
- **Fastest on EL.** rustdl's saturation kernel beats whelk-rs (1.4–1.9×) and ELK
|
|
19
19
|
(4.5×) on galen/notgalen, deriving a sound *superset* of their closures.
|
|
20
|
-
- **Competitive on DL, not the speed leader.**
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
- **Competitive on DL, not the speed leader.** Most DL ontologies classify
|
|
21
|
+
within ~10–50× of Konclude (the mature C++ tableau, which wins on speed);
|
|
22
|
+
HermiT is slower still and itself DNFs on a hard tail. **wine — once rustdl's
|
|
23
|
+
one DNF (combinatorial nominal+disjunction) — now classifies soundly in ~1.6 s**
|
|
24
|
+
(a ~30× reduction from the coupled-saturation ∃-seed plus wedge search-ordering
|
|
25
|
+
work; see the [v0.3.16 snapshot](docs/perf-2026-06-27-bench-snapshot.md)). A
|
|
26
|
+
residual of ~9 idiosyncratic ORE-pilot ontologies stays hard.
|
|
24
27
|
- Detects the **family** inconsistency (a consequence-based ABox-saturation
|
|
25
28
|
pre-check) that the per-pair tableau alone misses.
|
|
26
29
|
- **Explains *and* debugs — a full suite.** Built-in CLI commands turn rustdl into
|
|
@@ -150,6 +153,7 @@ license; no separate CLA.
|
|
|
150
153
|
|
|
151
154
|
## More
|
|
152
155
|
|
|
156
|
+
- Latest benchmark snapshot: [`docs/perf-2026-06-27-bench-snapshot.md`](docs/perf-2026-06-27-bench-snapshot.md)
|
|
153
157
|
- Reasoner comparison: [`docs/reasoner-comparison-2026-06-21.md`](docs/reasoner-comparison-2026-06-21.md)
|
|
154
158
|
- Perf vs Konclude/HermiT: [`docs/perf-2026-06-08-konclude-vs-rustdl.md`](docs/perf-2026-06-08-konclude-vs-rustdl.md)
|
|
155
159
|
- Completeness envelope: [`docs/fragment-completeness.md`](docs/fragment-completeness.md)
|
|
@@ -6,7 +6,7 @@ consequence-based **saturation** engine handles the EL-ish fragment, a
|
|
|
6
6
|
orchestrator picks per query. Parsing and the OWL model come from
|
|
7
7
|
[`horned-owl`](https://github.com/phillord/horned-owl).
|
|
8
8
|
|
|
9
|
-
## Status (v0.3.
|
|
9
|
+
## Status (v0.3.16)
|
|
10
10
|
|
|
11
11
|
A working classifier, consistency checker, and instance reasoner for SROIQ(D)
|
|
12
12
|
with first-class data properties. The defining property is **soundness**: every
|
|
@@ -17,10 +17,13 @@ reported subsumption is a genuine entailment.
|
|
|
17
17
|
nothing that neither complete reasoner does.
|
|
18
18
|
- **Fastest on EL.** rustdl's saturation kernel beats whelk-rs (1.4–1.9×) and ELK
|
|
19
19
|
(4.5×) on galen/notgalen, deriving a sound *superset* of their closures.
|
|
20
|
-
- **Competitive on DL, not the speed leader.**
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
- **Competitive on DL, not the speed leader.** Most DL ontologies classify
|
|
21
|
+
within ~10–50× of Konclude (the mature C++ tableau, which wins on speed);
|
|
22
|
+
HermiT is slower still and itself DNFs on a hard tail. **wine — once rustdl's
|
|
23
|
+
one DNF (combinatorial nominal+disjunction) — now classifies soundly in ~1.6 s**
|
|
24
|
+
(a ~30× reduction from the coupled-saturation ∃-seed plus wedge search-ordering
|
|
25
|
+
work; see the [v0.3.16 snapshot](docs/perf-2026-06-27-bench-snapshot.md)). A
|
|
26
|
+
residual of ~9 idiosyncratic ORE-pilot ontologies stays hard.
|
|
24
27
|
- Detects the **family** inconsistency (a consequence-based ABox-saturation
|
|
25
28
|
pre-check) that the per-pair tableau alone misses.
|
|
26
29
|
- **Explains *and* debugs — a full suite.** Built-in CLI commands turn rustdl into
|
|
@@ -150,6 +153,7 @@ license; no separate CLA.
|
|
|
150
153
|
|
|
151
154
|
## More
|
|
152
155
|
|
|
156
|
+
- Latest benchmark snapshot: [`docs/perf-2026-06-27-bench-snapshot.md`](docs/perf-2026-06-27-bench-snapshot.md)
|
|
153
157
|
- Reasoner comparison: [`docs/reasoner-comparison-2026-06-21.md`](docs/reasoner-comparison-2026-06-21.md)
|
|
154
158
|
- Perf vs Konclude/HermiT: [`docs/perf-2026-06-08-konclude-vs-rustdl.md`](docs/perf-2026-06-08-konclude-vs-rustdl.md)
|
|
155
159
|
- Completeness envelope: [`docs/fragment-completeness.md`](docs/fragment-completeness.md)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
//! `classify` / `classify_bytes` top-level functions + the
|
|
2
2
|
//! `Classification` `PyO3` class that wraps `owl_dl_reasoner::Classification`.
|
|
3
3
|
|
|
4
|
-
use owl_dl_reasoner::
|
|
4
|
+
use owl_dl_reasoner::Classification as RsClassification;
|
|
5
5
|
use pyo3::prelude::*;
|
|
6
6
|
|
|
7
7
|
use crate::errors::reason_error_to_py;
|
|
@@ -51,7 +51,8 @@ impl PyClassification {
|
|
|
51
51
|
/// True iff classification ran to completion — no pair hit the
|
|
52
52
|
/// timeout. When `False`, the hierarchy may be missing real
|
|
53
53
|
/// subsumptions (see `timed_out_pairs`); re-classify with
|
|
54
|
-
/// `per_pair_timeout_ms=0` for the complete
|
|
54
|
+
/// `per_pair_timeout_ms=0, global_deadline_ms=0` for the complete
|
|
55
|
+
/// (unbounded) result.
|
|
55
56
|
#[getter]
|
|
56
57
|
fn complete(&self) -> bool {
|
|
57
58
|
self.inner.stats().timed_out_pairs == 0
|
|
@@ -94,46 +95,67 @@ impl PyClassification {
|
|
|
94
95
|
/// Format auto-detected from the file extension
|
|
95
96
|
/// (`.ofn` | `.owx` | `.owl` | `.rdf` | `.omn`).
|
|
96
97
|
#[pyfunction]
|
|
97
|
-
#[pyo3(signature = (path, *, per_pair_timeout_ms=
|
|
98
|
+
#[pyo3(signature = (path, *, per_pair_timeout_ms=100, global_deadline_ms=60000, saturation_only=false))]
|
|
98
99
|
pub(crate) fn classify(
|
|
99
100
|
path: &str,
|
|
100
101
|
per_pair_timeout_ms: Option<u64>,
|
|
102
|
+
global_deadline_ms: Option<u64>,
|
|
101
103
|
saturation_only: bool,
|
|
102
104
|
) -> PyResult<PyClassification> {
|
|
103
105
|
let ontology = load::load_path(path)?;
|
|
104
|
-
do_classify(
|
|
106
|
+
do_classify(
|
|
107
|
+
&ontology,
|
|
108
|
+
per_pair_timeout_ms,
|
|
109
|
+
global_deadline_ms,
|
|
110
|
+
saturation_only,
|
|
111
|
+
)
|
|
105
112
|
}
|
|
106
113
|
|
|
107
114
|
/// `rustdl.classify_bytes(data, format="ofn")` — same but from bytes.
|
|
108
115
|
/// `format` is one of `"ofn"`, `"owx"`, `"rdf-xml"`, `"omn"`.
|
|
109
116
|
#[pyfunction]
|
|
110
|
-
#[pyo3(signature = (data, *, format, per_pair_timeout_ms=
|
|
117
|
+
#[pyo3(signature = (data, *, format, per_pair_timeout_ms=100, global_deadline_ms=60000, saturation_only=false))]
|
|
111
118
|
pub(crate) fn classify_bytes(
|
|
112
119
|
data: &[u8],
|
|
113
120
|
format: &str,
|
|
114
121
|
per_pair_timeout_ms: Option<u64>,
|
|
122
|
+
global_deadline_ms: Option<u64>,
|
|
115
123
|
saturation_only: bool,
|
|
116
124
|
) -> PyResult<PyClassification> {
|
|
117
125
|
let ontology = load::load_bytes(data, format)?;
|
|
118
|
-
do_classify(
|
|
126
|
+
do_classify(
|
|
127
|
+
&ontology,
|
|
128
|
+
per_pair_timeout_ms,
|
|
129
|
+
global_deadline_ms,
|
|
130
|
+
saturation_only,
|
|
131
|
+
)
|
|
119
132
|
}
|
|
120
133
|
|
|
121
134
|
fn do_classify(
|
|
122
135
|
ontology: &horned_owl::ontology::set::SetOntology<horned_owl::model::RcStr>,
|
|
123
136
|
per_pair_timeout_ms: Option<u64>,
|
|
137
|
+
global_deadline_ms: Option<u64>,
|
|
124
138
|
saturation_only: bool,
|
|
125
139
|
) -> PyResult<PyClassification> {
|
|
126
140
|
use std::time::Duration;
|
|
127
|
-
//
|
|
128
|
-
//
|
|
129
|
-
|
|
141
|
+
// Two independent bounds (`0`/`None` disables that one): `per_pair`
|
|
142
|
+
// bounds any single `sub ⊓ ¬sup` pair; the global wall-budget bounds the
|
|
143
|
+
// TOTAL run so it can't grow with the pair count (the backstop against
|
|
144
|
+
// wine-class hangs). Each probe is cut at min(per_pair, remaining global).
|
|
145
|
+
// Cutting is a SOUND under-approximation — no false subsumptions; real
|
|
146
|
+
// ones may be missing (check `.complete` / `.timed_out_pairs`). Both
|
|
147
|
+
// disabled ⇒ unbounded/complete.
|
|
148
|
+
let per_pair = per_pair_timeout_ms
|
|
149
|
+
.filter(|&ms| ms > 0)
|
|
150
|
+
.map(Duration::from_millis);
|
|
151
|
+
let global = global_deadline_ms
|
|
152
|
+
.filter(|&ms| ms > 0)
|
|
153
|
+
.map(Duration::from_millis);
|
|
130
154
|
let inner = if saturation_only {
|
|
131
155
|
owl_dl_reasoner::classify_saturation_only(ontology).map_err(reason_error_to_py)?
|
|
132
|
-
} else if let Some(ms) = bounded {
|
|
133
|
-
owl_dl_reasoner::classify_top_down_with_timeout(ontology, Duration::from_millis(ms))
|
|
134
|
-
.map_err(reason_error_to_py)?
|
|
135
156
|
} else {
|
|
136
|
-
|
|
157
|
+
owl_dl_reasoner::classify_with_budget(ontology, per_pair, global)
|
|
158
|
+
.map_err(reason_error_to_py)?
|
|
137
159
|
};
|
|
138
160
|
Ok(PyClassification { inner })
|
|
139
161
|
}
|
|
@@ -6,7 +6,7 @@ consequence-based **saturation** engine handles the EL-ish fragment, a
|
|
|
6
6
|
orchestrator picks per query. Parsing and the OWL model come from
|
|
7
7
|
[`horned-owl`](https://github.com/phillord/horned-owl).
|
|
8
8
|
|
|
9
|
-
## Status (v0.3.
|
|
9
|
+
## Status (v0.3.16)
|
|
10
10
|
|
|
11
11
|
A working classifier, consistency checker, and instance reasoner for SROIQ(D)
|
|
12
12
|
with first-class data properties. The defining property is **soundness**: every
|
|
@@ -17,10 +17,13 @@ reported subsumption is a genuine entailment.
|
|
|
17
17
|
nothing that neither complete reasoner does.
|
|
18
18
|
- **Fastest on EL.** rustdl's saturation kernel beats whelk-rs (1.4–1.9×) and ELK
|
|
19
19
|
(4.5×) on galen/notgalen, deriving a sound *superset* of their closures.
|
|
20
|
-
- **Competitive on DL, not the speed leader.**
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
- **Competitive on DL, not the speed leader.** Most DL ontologies classify
|
|
21
|
+
within ~10–50× of Konclude (the mature C++ tableau, which wins on speed);
|
|
22
|
+
HermiT is slower still and itself DNFs on a hard tail. **wine — once rustdl's
|
|
23
|
+
one DNF (combinatorial nominal+disjunction) — now classifies soundly in ~1.6 s**
|
|
24
|
+
(a ~30× reduction from the coupled-saturation ∃-seed plus wedge search-ordering
|
|
25
|
+
work; see the [v0.3.16 snapshot](docs/perf-2026-06-27-bench-snapshot.md)). A
|
|
26
|
+
residual of ~9 idiosyncratic ORE-pilot ontologies stays hard.
|
|
24
27
|
- Detects the **family** inconsistency (a consequence-based ABox-saturation
|
|
25
28
|
pre-check) that the per-pair tableau alone misses.
|
|
26
29
|
- **Explains *and* debugs — a full suite.** Built-in CLI commands turn rustdl into
|
|
@@ -150,6 +153,7 @@ license; no separate CLA.
|
|
|
150
153
|
|
|
151
154
|
## More
|
|
152
155
|
|
|
156
|
+
- Latest benchmark snapshot: [`docs/perf-2026-06-27-bench-snapshot.md`](docs/perf-2026-06-27-bench-snapshot.md)
|
|
153
157
|
- Reasoner comparison: [`docs/reasoner-comparison-2026-06-21.md`](docs/reasoner-comparison-2026-06-21.md)
|
|
154
158
|
- Perf vs Konclude/HermiT: [`docs/perf-2026-06-08-konclude-vs-rustdl.md`](docs/perf-2026-06-08-konclude-vs-rustdl.md)
|
|
155
159
|
- Completeness envelope: [`docs/fragment-completeness.md`](docs/fragment-completeness.md)
|
|
@@ -318,6 +318,17 @@ pub fn saturate_abox_consistency(internal: &InternalOntology) -> SaturationResul
|
|
|
318
318
|
}
|
|
319
319
|
}
|
|
320
320
|
}
|
|
321
|
+
Axiom::TransitiveRole(r) => {
|
|
322
|
+
// Transitivity is the self-chain `R ∘ R ⊑ R`; registering it as a
|
|
323
|
+
// length-2 chain lets the Rule-4 fixpoint close the full transitive
|
|
324
|
+
// closure of `R`-edges — jointly with the role hierarchy, inverse
|
|
325
|
+
// materialization, and declared chains (a transitive edge can feed
|
|
326
|
+
// a sub-property/chain rule and vice-versa). The inverse of a
|
|
327
|
+
// transitive role is transitive too, and is covered by inverse
|
|
328
|
+
// materialization re-running over the closed forward edges.
|
|
329
|
+
let k = role_key(*r);
|
|
330
|
+
chains2.push((k, k, k));
|
|
331
|
+
}
|
|
321
332
|
Axiom::ObjectPropertyDomain { role, domain } => {
|
|
322
333
|
if let Some(d) = atomic_class(*domain) {
|
|
323
334
|
domains.entry(role_key(*role)).or_default().push(d);
|
|
@@ -438,6 +438,30 @@ pub fn classify_with_global_deadline<A: ForIRI>(
|
|
|
438
438
|
classify_top_down_internal(&internal, None, Some(deadline))
|
|
439
439
|
}
|
|
440
440
|
|
|
441
|
+
/// Classify with BOTH a per-pair tableau deadline and a global wall-clock
|
|
442
|
+
/// budget — the recommended bounded entry point. Each probe is cut at
|
|
443
|
+
/// `min(per_pair, remaining global)` (see [`effective_deadline`]); `per_pair`
|
|
444
|
+
/// bounds any single pair, `global_budget` bounds the total wall so the run
|
|
445
|
+
/// can't grow with the pair count. Either may be `None` (that bound absent;
|
|
446
|
+
/// both `None` ⇒ the unbounded top-down classify).
|
|
447
|
+
///
|
|
448
|
+
/// **Sound** at every setting: a cut probe defaults to "not subsumed"
|
|
449
|
+
/// (FP=0; the hierarchy may MISS a real subsumption — inspect
|
|
450
|
+
/// [`ClassificationStats`]`::complete` / `timed_out_pairs`).
|
|
451
|
+
///
|
|
452
|
+
/// # Errors
|
|
453
|
+
///
|
|
454
|
+
/// See [`ReasonError`].
|
|
455
|
+
pub fn classify_with_budget<A: ForIRI>(
|
|
456
|
+
ontology: &SetOntology<A>,
|
|
457
|
+
per_pair_timeout: Option<std::time::Duration>,
|
|
458
|
+
global_budget: Option<std::time::Duration>,
|
|
459
|
+
) -> Result<Classification, ReasonError> {
|
|
460
|
+
let internal = convert_ontology(ontology)?;
|
|
461
|
+
let global_deadline = global_budget.map(|b| Instant::now() + b);
|
|
462
|
+
classify_top_down_internal(&internal, per_pair_timeout, global_deadline)
|
|
463
|
+
}
|
|
464
|
+
|
|
441
465
|
/// Naive `n²` pair-sweep classifier. Kept for benchmarking and
|
|
442
466
|
/// regression cross-checks against [`classify`]. On real workloads
|
|
443
467
|
/// it is consistently 2× slower than the default top-down path; new
|
|
@@ -54,8 +54,8 @@ mod union_find;
|
|
|
54
54
|
pub use classify::{
|
|
55
55
|
Classification, ClassificationStats, FragmentClassification, analyze_fragment, classify,
|
|
56
56
|
classify_internal, classify_n2, classify_n2_with_timeout, classify_saturation_only,
|
|
57
|
-
classify_top_down, classify_top_down_with_timeout,
|
|
58
|
-
classify_with_timeout,
|
|
57
|
+
classify_top_down, classify_top_down_with_timeout, classify_with_budget,
|
|
58
|
+
classify_with_global_deadline, classify_with_timeout,
|
|
59
59
|
};
|
|
60
60
|
pub use diagnose::{DerivedClass, Diagnosis, diagnose};
|
|
61
61
|
pub use laconic::{find_all_laconic_justifications, find_laconic_justification};
|
|
@@ -51,6 +51,81 @@ fn subproperty_entailed_assertions() {
|
|
|
51
51
|
assert!(!got.contains(&triple("urn:a", "urn:hasAncestor", "urn:a")));
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
/// Issue #26: a `TransitiveObjectProperty` must materialize the full transitive
|
|
55
|
+
/// closure of its asserted edges, not just the one-step edges.
|
|
56
|
+
#[test]
|
|
57
|
+
fn transitive_closure_materialized() {
|
|
58
|
+
let b = Build::new_rc();
|
|
59
|
+
let mut o = SetOntology::new();
|
|
60
|
+
o.insert(DeclareObjectProperty(b.object_property("urn:ancestorOf")));
|
|
61
|
+
o.insert(horned_owl::model::TransitiveObjectProperty(
|
|
62
|
+
ObjectPropertyExpression::ObjectProperty(b.object_property("urn:ancestorOf")),
|
|
63
|
+
));
|
|
64
|
+
for i in ["urn:a", "urn:b", "urn:c", "urn:d"] {
|
|
65
|
+
o.insert(horned_owl::model::DeclareNamedIndividual(
|
|
66
|
+
b.named_individual(i),
|
|
67
|
+
));
|
|
68
|
+
}
|
|
69
|
+
o.insert(opa(&b, "urn:ancestorOf", "urn:a", "urn:b"));
|
|
70
|
+
o.insert(opa(&b, "urn:ancestorOf", "urn:b", "urn:c"));
|
|
71
|
+
o.insert(opa(&b, "urn:ancestorOf", "urn:c", "urn:d"));
|
|
72
|
+
|
|
73
|
+
let got = materialize_object_property_assertions(&o).expect("materialize");
|
|
74
|
+
let t = |s: &str, x: &str| (s.to_string(), "urn:ancestorOf".to_string(), x.to_string());
|
|
75
|
+
// one-step (already worked)
|
|
76
|
+
assert!(got.contains(&t("urn:a", "urn:b")), "got: {got:?}");
|
|
77
|
+
assert!(got.contains(&t("urn:b", "urn:c")), "got: {got:?}");
|
|
78
|
+
assert!(got.contains(&t("urn:c", "urn:d")), "got: {got:?}");
|
|
79
|
+
// transitive closure (the regression)
|
|
80
|
+
assert!(got.contains(&t("urn:a", "urn:c")), "a⊑c missing: {got:?}");
|
|
81
|
+
assert!(got.contains(&t("urn:b", "urn:d")), "b⊑d missing: {got:?}");
|
|
82
|
+
assert!(got.contains(&t("urn:a", "urn:d")), "a⊑d missing: {got:?}");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/// Issue #26 larger case: sub-property + inverse + transitivity compose, so the
|
|
86
|
+
/// transitive edge through the sub-property/inverse rewrites is materialized.
|
|
87
|
+
#[test]
|
|
88
|
+
fn transitive_with_subproperty_and_inverse() {
|
|
89
|
+
let b = Build::new_rc();
|
|
90
|
+
let mut o = SetOntology::new();
|
|
91
|
+
for p in ["urn:hasParent", "urn:hasChild", "urn:hasAncestor"] {
|
|
92
|
+
o.insert(DeclareObjectProperty(b.object_property(p)));
|
|
93
|
+
}
|
|
94
|
+
for i in ["urn:alice", "urn:mary", "urn:john"] {
|
|
95
|
+
o.insert(horned_owl::model::DeclareNamedIndividual(
|
|
96
|
+
b.named_individual(i),
|
|
97
|
+
));
|
|
98
|
+
}
|
|
99
|
+
// hasParent ⊑ hasAncestor ; hasAncestor transitive ; hasChild ≡ hasParent⁻
|
|
100
|
+
o.insert(SubObjectPropertyOf {
|
|
101
|
+
sub: SubObjectPropertyExpression::ObjectPropertyExpression(
|
|
102
|
+
ObjectPropertyExpression::ObjectProperty(b.object_property("urn:hasParent")),
|
|
103
|
+
),
|
|
104
|
+
sup: ObjectPropertyExpression::ObjectProperty(b.object_property("urn:hasAncestor")),
|
|
105
|
+
});
|
|
106
|
+
o.insert(horned_owl::model::TransitiveObjectProperty(
|
|
107
|
+
ObjectPropertyExpression::ObjectProperty(b.object_property("urn:hasAncestor")),
|
|
108
|
+
));
|
|
109
|
+
o.insert(horned_owl::model::InverseObjectProperties(
|
|
110
|
+
b.object_property("urn:hasChild"),
|
|
111
|
+
b.object_property("urn:hasParent"),
|
|
112
|
+
));
|
|
113
|
+
o.insert(opa(&b, "urn:hasChild", "urn:mary", "urn:alice")); // mary hasChild alice
|
|
114
|
+
o.insert(opa(&b, "urn:hasParent", "urn:mary", "urn:john")); // mary hasParent john
|
|
115
|
+
|
|
116
|
+
let got = materialize_object_property_assertions(&o).expect("materialize");
|
|
117
|
+
let anc = |s: &str, x: &str| (s.to_string(), "urn:hasAncestor".to_string(), x.to_string());
|
|
118
|
+
// alice hasParent mary (inverse) ⟹ alice hasAncestor mary (sub-property)
|
|
119
|
+
assert!(got.contains(&anc("urn:alice", "urn:mary")), "got: {got:?}");
|
|
120
|
+
// mary hasAncestor john (sub-property)
|
|
121
|
+
assert!(got.contains(&anc("urn:mary", "urn:john")), "got: {got:?}");
|
|
122
|
+
// the composed edge (the regression): alice hasAncestor john
|
|
123
|
+
assert!(
|
|
124
|
+
got.contains(&anc("urn:alice", "urn:john")),
|
|
125
|
+
"composed alice⊑john missing: {got:?}"
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
54
129
|
use owl_dl_reasoner::justify::{Entailment, entails};
|
|
55
130
|
|
|
56
131
|
#[test]
|
|
@@ -6,7 +6,7 @@ consequence-based **saturation** engine handles the EL-ish fragment, a
|
|
|
6
6
|
orchestrator picks per query. Parsing and the OWL model come from
|
|
7
7
|
[`horned-owl`](https://github.com/phillord/horned-owl).
|
|
8
8
|
|
|
9
|
-
## Status (v0.3.
|
|
9
|
+
## Status (v0.3.16)
|
|
10
10
|
|
|
11
11
|
A working classifier, consistency checker, and instance reasoner for SROIQ(D)
|
|
12
12
|
with first-class data properties. The defining property is **soundness**: every
|
|
@@ -17,10 +17,13 @@ reported subsumption is a genuine entailment.
|
|
|
17
17
|
nothing that neither complete reasoner does.
|
|
18
18
|
- **Fastest on EL.** rustdl's saturation kernel beats whelk-rs (1.4–1.9×) and ELK
|
|
19
19
|
(4.5×) on galen/notgalen, deriving a sound *superset* of their closures.
|
|
20
|
-
- **Competitive on DL, not the speed leader.**
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
- **Competitive on DL, not the speed leader.** Most DL ontologies classify
|
|
21
|
+
within ~10–50× of Konclude (the mature C++ tableau, which wins on speed);
|
|
22
|
+
HermiT is slower still and itself DNFs on a hard tail. **wine — once rustdl's
|
|
23
|
+
one DNF (combinatorial nominal+disjunction) — now classifies soundly in ~1.6 s**
|
|
24
|
+
(a ~30× reduction from the coupled-saturation ∃-seed plus wedge search-ordering
|
|
25
|
+
work; see the [v0.3.16 snapshot](docs/perf-2026-06-27-bench-snapshot.md)). A
|
|
26
|
+
residual of ~9 idiosyncratic ORE-pilot ontologies stays hard.
|
|
24
27
|
- Detects the **family** inconsistency (a consequence-based ABox-saturation
|
|
25
28
|
pre-check) that the per-pair tableau alone misses.
|
|
26
29
|
- **Explains *and* debugs — a full suite.** Built-in CLI commands turn rustdl into
|
|
@@ -150,6 +153,7 @@ license; no separate CLA.
|
|
|
150
153
|
|
|
151
154
|
## More
|
|
152
155
|
|
|
156
|
+
- Latest benchmark snapshot: [`docs/perf-2026-06-27-bench-snapshot.md`](docs/perf-2026-06-27-bench-snapshot.md)
|
|
153
157
|
- Reasoner comparison: [`docs/reasoner-comparison-2026-06-21.md`](docs/reasoner-comparison-2026-06-21.md)
|
|
154
158
|
- Perf vs Konclude/HermiT: [`docs/perf-2026-06-08-konclude-vs-rustdl.md`](docs/perf-2026-06-08-konclude-vs-rustdl.md)
|
|
155
159
|
- Completeness envelope: [`docs/fragment-completeness.md`](docs/fragment-completeness.md)
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# rustdl
|
|
2
|
+
|
|
3
|
+
A **sound** OWL 2 DL (SROIQ) reasoner in Rust. Konclude-style hybrid: a
|
|
4
|
+
consequence-based **saturation** engine handles the EL-ish fragment, a
|
|
5
|
+
**tableau** + hypertableau **wedge** handles the rest of SROIQ, and an
|
|
6
|
+
orchestrator picks per query. Parsing and the OWL model come from
|
|
7
|
+
[`horned-owl`](https://github.com/phillord/horned-owl).
|
|
8
|
+
|
|
9
|
+
## Status (v0.3.16)
|
|
10
|
+
|
|
11
|
+
A working classifier, consistency checker, and instance reasoner for SROIQ(D)
|
|
12
|
+
with first-class data properties. The defining property is **soundness**: every
|
|
13
|
+
reported subsumption is a genuine entailment.
|
|
14
|
+
|
|
15
|
+
- **FP = 0 at scale.** Verified against the Konclude ∩ HermiT oracle across all
|
|
16
|
+
201 diffed ORE-2015 pilot ontologies *and* the curated corpus — rustdl asserts
|
|
17
|
+
nothing that neither complete reasoner does.
|
|
18
|
+
- **Fastest on EL.** rustdl's saturation kernel beats whelk-rs (1.4–1.9×) and ELK
|
|
19
|
+
(4.5×) on galen/notgalen, deriving a sound *superset* of their closures.
|
|
20
|
+
- **Competitive on DL, not the speed leader.** Most DL ontologies classify
|
|
21
|
+
within ~10–50× of Konclude (the mature C++ tableau, which wins on speed);
|
|
22
|
+
HermiT is slower still and itself DNFs on a hard tail. **wine — once rustdl's
|
|
23
|
+
one DNF (combinatorial nominal+disjunction) — now classifies soundly in ~1.6 s**
|
|
24
|
+
(a ~30× reduction from the coupled-saturation ∃-seed plus wedge search-ordering
|
|
25
|
+
work; see the [v0.3.16 snapshot](docs/perf-2026-06-27-bench-snapshot.md)). A
|
|
26
|
+
residual of ~9 idiosyncratic ORE-pilot ontologies stays hard.
|
|
27
|
+
- Detects the **family** inconsistency (a consequence-based ABox-saturation
|
|
28
|
+
pre-check) that the per-pair tableau alone misses.
|
|
29
|
+
- **Explains *and* debugs — a full suite.** Built-in CLI commands turn rustdl into
|
|
30
|
+
an ontology-debugging tool, not just a classifier:
|
|
31
|
+
- `justify` — a minimal responsible-axiom set for any entailment (`--laconic`
|
|
32
|
+
weakens each axiom to its responsible *fragment*).
|
|
33
|
+
- `prove` — a step-level proof tree.
|
|
34
|
+
- `diagnose` — partitions unsatisfiable classes into **root** causes vs **derived**
|
|
35
|
+
collateral ("where to start fixing").
|
|
36
|
+
- `repair` — minimal axiom-removal sets to *break* an unwanted entailment, each
|
|
37
|
+
verified.
|
|
38
|
+
- `report` — a self-contained HTML debugging report combining all of the above.
|
|
39
|
+
|
|
40
|
+
Every result is **sound by construction** (justifications and repairs are verified
|
|
41
|
+
against the reasoner). **Konclude** (the DL speed leader) has **no built-in
|
|
42
|
+
justification or explanation facility** at all (its interface is classification /
|
|
43
|
+
consistency / realization / SPARQL only) — so the fastest reasoner tells you *that*
|
|
44
|
+
a subsumption holds but not *why*, or *how to fix* a broken ontology. rustdl does.
|
|
45
|
+
|
|
46
|
+
Full head-to-head (5 reasoners × 2 corpora):
|
|
47
|
+
[`docs/reasoner-comparison-2026-06-21.md`](docs/reasoner-comparison-2026-06-21.md).
|
|
48
|
+
|
|
49
|
+
**Completeness is partial** — the default classifier is empirically near-complete
|
|
50
|
+
across the measured corpus but not *provably* complete in general (it trusts the
|
|
51
|
+
wedge's `Sat` verdicts; see the soundness contract in `CLAUDE.md` and
|
|
52
|
+
[`docs/fragment-completeness.md`](docs/fragment-completeness.md)). The hard residual
|
|
53
|
+
is the engineering-maturity gap to Konclude's optimized tableau, not a missing
|
|
54
|
+
technique.
|
|
55
|
+
|
|
56
|
+
## Coverage
|
|
57
|
+
|
|
58
|
+
**Supported (sound; complete on the fragment, oracle-validated):**
|
|
59
|
+
|
|
60
|
+
- SROIQ object-property reasoning — role hierarchies; transitive, symmetric,
|
|
61
|
+
asymmetric, irreflexive, functional, inverse-functional; inverse roles; role
|
|
62
|
+
chains (longer chains decomposed to 2-leg cascades).
|
|
63
|
+
- Class expressions — intersection, union, complement, nominals (`{a}`),
|
|
64
|
+
existential / universal restrictions, qualified cardinality (`≥n R.C`, `≤n R.C`).
|
|
65
|
+
- `DisjointClasses`, `EquivalentClasses`, `DisjointUnion`.
|
|
66
|
+
- ABox — `ClassAssertion`, `ObjectPropertyAssertion`,
|
|
67
|
+
`NegativeObjectPropertyAssertion`, `SameIndividual`, `DifferentIndividuals`;
|
|
68
|
+
consistency via an ABox-saturation pre-check + clash-pattern checks.
|
|
69
|
+
- **Data properties are first-class** (default-on) — data-property axioms lower to
|
|
70
|
+
the object fragment; concrete domains cover integer / float / decimal / date /
|
|
71
|
+
dateTime / string value-membership, faceted ranges, `DataOneOf`, and bounded
|
|
72
|
+
data cardinality.
|
|
73
|
+
|
|
74
|
+
**Sound under-approximation (silently dropped, never an error):** data ranges /
|
|
75
|
+
nested composites outside the recognized set; positives depending on them may be
|
|
76
|
+
missed, never falsely asserted.
|
|
77
|
+
|
|
78
|
+
**Unsupported (errors):** `HasKey`. SWRL rules are skipped (see `convert.rs`).
|
|
79
|
+
|
|
80
|
+
## Crates
|
|
81
|
+
|
|
82
|
+
`owl-dl-core` (IR + normalization), `owl-dl-saturation` (EL closure),
|
|
83
|
+
`owl-dl-tableau` (SROIQ tableau + hypertableau wedge), `owl-dl-datatypes`
|
|
84
|
+
(concrete domains), `owl-dl-reasoner` (orchestrator + public API), `owl-dl-cli`
|
|
85
|
+
(`rustdl` binary), `owl-dl-bench` (corpus/benchmark harness), `owl-dl-py` (Python
|
|
86
|
+
bindings). `xtask` holds build automation.
|
|
87
|
+
|
|
88
|
+
## Install
|
|
89
|
+
|
|
90
|
+
```sh
|
|
91
|
+
cargo add owl-dl-reasoner # library
|
|
92
|
+
cargo install --git https://github.com/MaastrichtU-IDS/rustdl owl-dl-cli # CLI
|
|
93
|
+
pip install rustdl # Python 3.10+ (ABI3)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
import rustdl
|
|
98
|
+
result = rustdl.classify("ontology.ofn") # OFN / OWX / RDF-XML / Manchester (.omn) — auto-detected
|
|
99
|
+
print(f"{len(result.classes)} classes; {len(result.unsatisfiable)} unsat")
|
|
100
|
+
print(result.is_subclass("http://ex.org/Sub", "http://ex.org/Sup"))
|
|
101
|
+
ok = rustdl.is_consistent("ontology.ofn")
|
|
102
|
+
edges = rustdl.materialize_inferred_property_assertions("ontology.ofn") # inferred object property assertions
|
|
103
|
+
data_edges = rustdl.materialize_inferred_data_property_assertions("ontology.ofn") # inferred data property assertions
|
|
104
|
+
sub_obj = rustdl.materialize_inferred_subobjectproperty_axioms("ontology.ofn") # object property hierarchy
|
|
105
|
+
sub_dat = rustdl.materialize_inferred_subdataproperty_axioms("ontology.ofn") # data property hierarchy
|
|
106
|
+
succ = rustdl.materialize_existential_successors("ontology.ofn") # entailed exists-successors (blank-node witnesses)
|
|
107
|
+
report = rustdl.debug("ontology.ofn") # consistency + root/derived unsat + justifications + repairs
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
New to the Python API? Walk through
|
|
111
|
+
[**Debugging an ontology with rustdl**](docs/python-ontology-qa.md) — an end-to-end
|
|
112
|
+
QA tutorial (classify → `debug()` → justify/repair → fix → read inferred facts).
|
|
113
|
+
|
|
114
|
+
## Build & test
|
|
115
|
+
|
|
116
|
+
```sh
|
|
117
|
+
cargo build --workspace --release # Rust 1.88+, edition 2024
|
|
118
|
+
cargo fmt --all -- --check
|
|
119
|
+
cargo clippy --workspace --all-targets --all-features -- -D warnings
|
|
120
|
+
cargo test --workspace
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## CLI
|
|
124
|
+
|
|
125
|
+
```sh
|
|
126
|
+
rustdl classify ontology.ofn # full class hierarchy (default)
|
|
127
|
+
rustdl consistent ontology.ofn
|
|
128
|
+
rustdl subclass ontology.ofn <sub> <sup>
|
|
129
|
+
rustdl instances ontology.ofn <class>
|
|
130
|
+
rustdl realize ontology.ofn [--properties] # per-individual types (+ inferred object & data property assertions)
|
|
131
|
+
rustdl justify ontology.ofn <query…> # minimal responsible-axiom set (why it holds)
|
|
132
|
+
rustdl justify --laconic ontology.ofn <query…> # pinpoint the responsible PART of each axiom
|
|
133
|
+
rustdl repair ontology.ofn <query…> # minimal axiom removals to break an entailment
|
|
134
|
+
rustdl prove ontology.ofn <sub> <sup> # step-level DL proof tree
|
|
135
|
+
rustdl diagnose ontology.ofn # root vs derived unsatisfiable classes (where to start fixing)
|
|
136
|
+
rustdl report ontology.ofn -o report.html # self-contained HTML debugging report
|
|
137
|
+
rustdl explain ontology.ofn <sub> <sup> # which engine answered (saturation vs tableau)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Sound under-approximation modes (every reported subsumption still holds; positives
|
|
141
|
+
may be missed): `--saturation-only` (skip the tableau, EL-closure only) and
|
|
142
|
+
`--pair-timeout-ms N` (per-pair tableau deadline; cut pairs default to "not
|
|
143
|
+
subsumed" — robust on pathological SROIQ inputs). Diagnostics: `RUSTDL_TRACE=1`
|
|
144
|
+
(one stderr line per search/branch decision); `RUSTDL_COUNTERS=1` with
|
|
145
|
+
`--features counters` (per-rule call counts).
|
|
146
|
+
|
|
147
|
+
## Licensing
|
|
148
|
+
|
|
149
|
+
Dual-licensed [Apache-2.0](LICENSE-APACHE) **OR** [MIT](LICENSE-MIT). `horned-owl`
|
|
150
|
+
is LGPL-3.0; binaries that statically link it inherit LGPL-3.0 obligations for that
|
|
151
|
+
portion (see [`NOTICE`](NOTICE)). Contributions are accepted under the same dual
|
|
152
|
+
license; no separate CLA.
|
|
153
|
+
|
|
154
|
+
## More
|
|
155
|
+
|
|
156
|
+
- Latest benchmark snapshot: [`docs/perf-2026-06-27-bench-snapshot.md`](docs/perf-2026-06-27-bench-snapshot.md)
|
|
157
|
+
- Reasoner comparison: [`docs/reasoner-comparison-2026-06-21.md`](docs/reasoner-comparison-2026-06-21.md)
|
|
158
|
+
- Perf vs Konclude/HermiT: [`docs/perf-2026-06-08-konclude-vs-rustdl.md`](docs/perf-2026-06-08-konclude-vs-rustdl.md)
|
|
159
|
+
- Completeness envelope: [`docs/fragment-completeness.md`](docs/fragment-completeness.md)
|
|
160
|
+
- Strategy: [`docs/owl-dl-reasoner-rust-strategy-v2.md`](docs/owl-dl-reasoner-rust-strategy-v2.md)
|
|
161
|
+
- Engineering notes & soundness contract: [`CLAUDE.md`](CLAUDE.md)
|