rustdl 0.3.4__tar.gz → 0.3.6__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.4 → rustdl-0.3.6}/Cargo.lock +9 -9
- {rustdl-0.3.4 → rustdl-0.3.6}/Cargo.toml +6 -6
- {rustdl-0.3.4 → rustdl-0.3.6}/PKG-INFO +1 -1
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/src/classify.rs +233 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/src/lib.rs +26 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/konclude_closure_diff.rs +5 -1
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-saturation/src/lib.rs +410 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-tableau/src/hyper.rs +207 -4
- {rustdl-0.3.4 → rustdl-0.3.6}/README.md +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-core/Cargo.toml +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-core/README.md +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-core/src/absorb.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-core/src/clause.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-core/src/convert.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-core/src/convert_back.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-core/src/data_axioms.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-core/src/definitions.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-core/src/disjunction_existential.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-core/src/ir.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-core/src/lib.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-core/src/locality.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-core/src/normalize.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-core/src/ontology.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-core/src/residual_trigger.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-core/src/role_hierarchy.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-core/src/told.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-core/src/transform.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-core/src/vocab.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-core/tests/concept_pool_proptest.proptest-regressions +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-core/tests/concept_pool_proptest.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-core/tests/convert_round_trip_proptest.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-core/tests/role_hierarchy_proptest.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-datatypes/Cargo.toml +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-datatypes/README.md +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-datatypes/src/lib.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-py/.gitignore +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-py/Cargo.toml +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-py/README.md +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-py/src/classify.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-py/src/errors.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-py/src/lib.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-py/src/load.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-py/src/materialize.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-py/src/queries.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-py/tests/python/conftest.py +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-py/tests/python/test_classify.py +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-py/tests/python/test_examples.py +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-py/tests/python/test_materialize.py +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-py/tests/python/test_queries.py +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-py/tests/python/test_smoke.py +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-py/tests/python/test_soundness.py +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/Cargo.toml +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/README.md +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/src/abox_check.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/src/model_cache.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/src/realize.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/src/union_find.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/abox_consistency.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/anon349_diagnostic.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/datatype_completeness.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/abox/p1_direct_bot.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/abox/p1_no_bot.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/abox/p2_disjoint_different_individuals.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/abox/p2_disjoint_types.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/abox/p3_neg_opa.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/abox/p3_neg_opa_no_clash.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/abox/p3_role_hierarchy_neg_consistent.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/abox/p3_role_hierarchy_neg_inconsistent.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/abox/p4_same_different.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/abox/p4_same_without_different.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/abox/p5_functional_diff.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/abox/p5_functional_same_target.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/abox/p6_asymmetric.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/abox/p6_asymmetric_one_way.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/abox/p6_irreflexive.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/abox/p6_irreflexive_distinct.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/abox/p7_range_compatible.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/abox/p7_range_disjoint.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/datatype/data_cardinality_disjoint.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/datatype/data_property_domain-classified.owx +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/datatype/data_property_domain.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/datatype/datatype_definition-classified.owx +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/datatype/datatype_definition.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/datatype/datatype_facet.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/datatype/functional_data_property.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/datatype/sub_data_property-classified.owx +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/datatype/sub_data_property.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/functional-equiv-some-bug.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/named-pizza-country-bug.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/p2b0-terms-01.txt +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/p2b0-terms-02.txt +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/p2b0-terms-03.txt +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/p2b0-terms-04.txt +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/p2b0-terms-05.txt +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/p2b0-terms-06.txt +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/p2b0-terms-07.txt +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/p2b0-terms-08.txt +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_01.hermit.owx +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_01.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_01.owx +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_02.hermit.owx +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_02.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_02.owx +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_03.hermit.owx +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_03.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_03.owx +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_04.hermit.owx +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_04.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_04.owx +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_05.hermit.owx +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_05.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_05.owx +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_06.hermit.owx +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_06.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_06.owx +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_07.hermit.owx +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_07.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_07.owx +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_08.hermit.owx +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_08.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_08.owx +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/fixtures/phase2b/phase2b-verdicts.log +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/label_heuristic_canary.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/phase2c_pair_06_canary.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/real_ontology_corpus.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-reasoner/tests/snapshot_phase0_canary.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-saturation/Cargo.toml +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-saturation/README.md +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-saturation/tests/fixtures/phase2a_functional_role_canary.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-saturation/tests/fixtures/phase2b_compound_existential_canary.ofn +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-tableau/Cargo.toml +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-tableau/README.md +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-tableau/src/counters.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-tableau/src/deps.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-tableau/src/graph.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-tableau/src/lib.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-tableau/src/replay.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-tableau/src/rules.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-tableau/src/saturate.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-tableau/src/search.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-tableau/src/snapshot.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-tableau/src/trail.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-tableau/tests/backprop_risk.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-tableau/tests/replay_driver.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-tableau/tests/replay_roundtrip.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/crates/owl-dl-tableau/tests/snapshot_capture.rs +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/pyproject.toml +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/python/rustdl/__init__.py +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/python/rustdl/data/pizza.owl.gz +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/python/rustdl/data/sio.owl.gz +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/python/rustdl/data/sulo.owl.gz +0 -0
- {rustdl-0.3.4 → rustdl-0.3.6}/python/rustdl/examples.py +0 -0
|
@@ -1037,7 +1037,7 @@ checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
|
|
|
1037
1037
|
|
|
1038
1038
|
[[package]]
|
|
1039
1039
|
name = "owl-dl-bench"
|
|
1040
|
-
version = "0.3.
|
|
1040
|
+
version = "0.3.6"
|
|
1041
1041
|
dependencies = [
|
|
1042
1042
|
"anyhow",
|
|
1043
1043
|
"clap",
|
|
@@ -1054,7 +1054,7 @@ dependencies = [
|
|
|
1054
1054
|
|
|
1055
1055
|
[[package]]
|
|
1056
1056
|
name = "owl-dl-cli"
|
|
1057
|
-
version = "0.3.
|
|
1057
|
+
version = "0.3.6"
|
|
1058
1058
|
dependencies = [
|
|
1059
1059
|
"anyhow",
|
|
1060
1060
|
"clap",
|
|
@@ -1066,7 +1066,7 @@ dependencies = [
|
|
|
1066
1066
|
|
|
1067
1067
|
[[package]]
|
|
1068
1068
|
name = "owl-dl-core"
|
|
1069
|
-
version = "0.3.
|
|
1069
|
+
version = "0.3.6"
|
|
1070
1070
|
dependencies = [
|
|
1071
1071
|
"bitvec",
|
|
1072
1072
|
"bumpalo",
|
|
@@ -1080,7 +1080,7 @@ dependencies = [
|
|
|
1080
1080
|
|
|
1081
1081
|
[[package]]
|
|
1082
1082
|
name = "owl-dl-datatypes"
|
|
1083
|
-
version = "0.3.
|
|
1083
|
+
version = "0.3.6"
|
|
1084
1084
|
dependencies = [
|
|
1085
1085
|
"owl-dl-core",
|
|
1086
1086
|
"proptest",
|
|
@@ -1090,7 +1090,7 @@ dependencies = [
|
|
|
1090
1090
|
|
|
1091
1091
|
[[package]]
|
|
1092
1092
|
name = "owl-dl-py"
|
|
1093
|
-
version = "0.3.
|
|
1093
|
+
version = "0.3.6"
|
|
1094
1094
|
dependencies = [
|
|
1095
1095
|
"horned-owl",
|
|
1096
1096
|
"owl-dl-core",
|
|
@@ -1101,7 +1101,7 @@ dependencies = [
|
|
|
1101
1101
|
|
|
1102
1102
|
[[package]]
|
|
1103
1103
|
name = "owl-dl-reasoner"
|
|
1104
|
-
version = "0.3.
|
|
1104
|
+
version = "0.3.6"
|
|
1105
1105
|
dependencies = [
|
|
1106
1106
|
"dashmap",
|
|
1107
1107
|
"horned-owl",
|
|
@@ -1117,7 +1117,7 @@ dependencies = [
|
|
|
1117
1117
|
|
|
1118
1118
|
[[package]]
|
|
1119
1119
|
name = "owl-dl-saturation"
|
|
1120
|
-
version = "0.3.
|
|
1120
|
+
version = "0.3.6"
|
|
1121
1121
|
dependencies = [
|
|
1122
1122
|
"dashmap",
|
|
1123
1123
|
"fixedbitset",
|
|
@@ -1133,7 +1133,7 @@ dependencies = [
|
|
|
1133
1133
|
|
|
1134
1134
|
[[package]]
|
|
1135
1135
|
name = "owl-dl-tableau"
|
|
1136
|
-
version = "0.3.
|
|
1136
|
+
version = "0.3.6"
|
|
1137
1137
|
dependencies = [
|
|
1138
1138
|
"bitvec",
|
|
1139
1139
|
"bumpalo",
|
|
@@ -2569,7 +2569,7 @@ dependencies = [
|
|
|
2569
2569
|
|
|
2570
2570
|
[[package]]
|
|
2571
2571
|
name = "xtask"
|
|
2572
|
-
version = "0.3.
|
|
2572
|
+
version = "0.3.6"
|
|
2573
2573
|
dependencies = [
|
|
2574
2574
|
"anyhow",
|
|
2575
2575
|
"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.6"
|
|
7
7
|
edition = "2024"
|
|
8
8
|
rust-version = "1.88"
|
|
9
9
|
license = "Apache-2.0 OR MIT"
|
|
@@ -15,11 +15,11 @@ keywords = ["owl", "ontology", "reasoner", "description-logic", "semantic-web"]
|
|
|
15
15
|
categories = ["science", "data-structures"]
|
|
16
16
|
|
|
17
17
|
[workspace.dependencies]
|
|
18
|
-
owl-dl-core = { path = "crates/owl-dl-core", version = "0.3.
|
|
19
|
-
owl-dl-saturation = { path = "crates/owl-dl-saturation", version = "0.3.
|
|
20
|
-
owl-dl-tableau = { path = "crates/owl-dl-tableau", version = "0.3.
|
|
21
|
-
owl-dl-datatypes = { path = "crates/owl-dl-datatypes", version = "0.3.
|
|
22
|
-
owl-dl-reasoner = { path = "crates/owl-dl-reasoner", version = "0.3.
|
|
18
|
+
owl-dl-core = { path = "crates/owl-dl-core", version = "0.3.6" }
|
|
19
|
+
owl-dl-saturation = { path = "crates/owl-dl-saturation", version = "0.3.6" }
|
|
20
|
+
owl-dl-tableau = { path = "crates/owl-dl-tableau", version = "0.3.6" }
|
|
21
|
+
owl-dl-datatypes = { path = "crates/owl-dl-datatypes", version = "0.3.6" }
|
|
22
|
+
owl-dl-reasoner = { path = "crates/owl-dl-reasoner", version = "0.3.6" }
|
|
23
23
|
|
|
24
24
|
horned-owl = { version = "1.4", default-features = false }
|
|
25
25
|
|
|
@@ -138,6 +138,10 @@ pub struct ClassificationStats {
|
|
|
138
138
|
/// entailment matrix — sound (never reports a false positive),
|
|
139
139
|
/// but may under-report subsumption.
|
|
140
140
|
pub timed_out_pairs: usize,
|
|
141
|
+
/// Subsumptions recovered by the defined-SUB sweep: a union-defined
|
|
142
|
+
/// `C ≡ D₁ ⊔ … ⊔ Dₙ` ⊑ a primitive sup `X` where every `Dᵢ ⊑ X` holds
|
|
143
|
+
/// in the EL closure (sound by construction). Added directly, no tableau.
|
|
144
|
+
pub defined_sub_sweep_recovered: usize,
|
|
141
145
|
/// Pairs proved subsumed by the H4 hypertableau wedge (sound
|
|
142
146
|
/// `Unsat`), skipping the tableau. Zero unless the wedge is
|
|
143
147
|
/// enabled (`RUSTDL_HYPERTABLEAU`).
|
|
@@ -1262,6 +1266,84 @@ pub(crate) fn classify_top_down_internal(
|
|
|
1262
1266
|
}
|
|
1263
1267
|
}
|
|
1264
1268
|
|
|
1269
|
+
// Defined-SUB sweep (cluster A; wine residual-31, 2026-06-07). The
|
|
1270
|
+
// defined-sup sweep above only tests pairs whose SUP is a defined class.
|
|
1271
|
+
// A union/covering-defined SUB `C ≡ D₁ ⊔ … ⊔ Dₙ` ⊑ a *primitive* sup X
|
|
1272
|
+
// (e.g. `Fruit ≡ NonSweetFruit ⊔ SweetFruit ⊑ EdibleThing`, where
|
|
1273
|
+
// `EdibleThing` is `SubClassOf`-only) is missed by BOTH the tier-walk (the
|
|
1274
|
+
// covering subsumption isn't in the EL closure) AND the defined-sup sweep
|
|
1275
|
+
// (X is primitive). Recover it soundly *by construction*: if the sound EL
|
|
1276
|
+
// closure has `Dᵢ ⊑ X` for EVERY disjunct, then `C ⊑ ⊔Dᵢ ⊑ X`. So the
|
|
1277
|
+
// candidate sups are exactly the common closure-supersumers of the
|
|
1278
|
+
// disjuncts (`∩ᵢ subsumers(Dᵢ)`); each is a genuine entailment — added
|
|
1279
|
+
// directly, no tableau/wedge call (hence no per-pair-budget timeout risk).
|
|
1280
|
+
// See docs/classify-recovery-scope-2026-06-07.md.
|
|
1281
|
+
for ax in &internal.axioms {
|
|
1282
|
+
let owl_dl_core::ontology::Axiom::EquivalentClasses(ids) = ax else {
|
|
1283
|
+
continue;
|
|
1284
|
+
};
|
|
1285
|
+
// Identify the named class `C` (an Atomic operand) and a union
|
|
1286
|
+
// operand whose disjuncts are all atomic.
|
|
1287
|
+
let mut name: Option<usize> = None;
|
|
1288
|
+
let mut disjuncts: Option<Vec<usize>> = None;
|
|
1289
|
+
for cid in ids {
|
|
1290
|
+
match internal.concepts.get(*cid) {
|
|
1291
|
+
owl_dl_core::ir::ConceptExpr::Atomic(cls) => name = Some(cls.index() as usize),
|
|
1292
|
+
owl_dl_core::ir::ConceptExpr::Or(ds) => {
|
|
1293
|
+
let atoms: Option<Vec<usize>> = ds
|
|
1294
|
+
.iter()
|
|
1295
|
+
.map(|d| match internal.concepts.get(*d) {
|
|
1296
|
+
owl_dl_core::ir::ConceptExpr::Atomic(dc) => Some(dc.index() as usize),
|
|
1297
|
+
_ => None,
|
|
1298
|
+
})
|
|
1299
|
+
.collect();
|
|
1300
|
+
if let Some(a) = atoms {
|
|
1301
|
+
disjuncts = Some(a);
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
_ => {}
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
let (Some(c), Some(ds)) = (name, disjuncts) else {
|
|
1308
|
+
continue;
|
|
1309
|
+
};
|
|
1310
|
+
if c >= n || ds.is_empty() || unsatisfiable_idxs.contains(&c) {
|
|
1311
|
+
continue;
|
|
1312
|
+
}
|
|
1313
|
+
// Candidate sups = intersection of the disjuncts' closure-subsumers.
|
|
1314
|
+
let mut cand: Option<std::collections::HashSet<usize>> = None;
|
|
1315
|
+
for &d in &ds {
|
|
1316
|
+
let d_id =
|
|
1317
|
+
owl_dl_core::ClassId::new(u32::try_from(d).expect("class index fits in u32"));
|
|
1318
|
+
let subs: std::collections::HashSet<usize> = closure
|
|
1319
|
+
.subsumers_of(d_id)
|
|
1320
|
+
.into_iter()
|
|
1321
|
+
.map(|s| s.index() as usize)
|
|
1322
|
+
.filter(|&j| j < n)
|
|
1323
|
+
.collect();
|
|
1324
|
+
cand = Some(match cand {
|
|
1325
|
+
None => subs,
|
|
1326
|
+
Some(prev) => prev.intersection(&subs).copied().collect(),
|
|
1327
|
+
});
|
|
1328
|
+
}
|
|
1329
|
+
let c_id = owl_dl_core::ClassId::new(u32::try_from(c).expect("class index fits in u32"));
|
|
1330
|
+
for x in cand.unwrap_or_default() {
|
|
1331
|
+
if x == c || unsatisfiable_idxs.contains(&x) {
|
|
1332
|
+
continue;
|
|
1333
|
+
}
|
|
1334
|
+
let x_id =
|
|
1335
|
+
owl_dl_core::ClassId::new(u32::try_from(x).expect("class index fits in u32"));
|
|
1336
|
+
// Skip subsumptions already on `C`'s closure ray (the entailment
|
|
1337
|
+
// matrix seeds those) or already recorded.
|
|
1338
|
+
if closure.contains(c_id, x_id) || direct_supers[c].contains(&x) {
|
|
1339
|
+
continue;
|
|
1340
|
+
}
|
|
1341
|
+
stats.defined_sub_sweep_recovered += 1;
|
|
1342
|
+
direct_supers[c].push(x);
|
|
1343
|
+
direct_children[x].push(c);
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1265
1347
|
// Build the full entailment matrix. Three sources contribute:
|
|
1266
1348
|
//
|
|
1267
1349
|
// 1. **Closure seed.** Every saturation-derived subsumption is
|
|
@@ -1625,6 +1707,122 @@ mod tests {
|
|
|
1625
1707
|
ontology
|
|
1626
1708
|
}
|
|
1627
1709
|
|
|
1710
|
+
/// Diagnostic probe (wine residual-31, cluster A): why does classify miss
|
|
1711
|
+
/// `food#Fruit ⊑ food#EdibleThing` when `is_subclass_of` proves it in 0.01s?
|
|
1712
|
+
/// Compares the fresh tableau (`is_subclass_of_internal`) against the
|
|
1713
|
+
/// classify-path `PreparedOntology::decide` (the ABox-seeded snapshot) on the
|
|
1714
|
+
/// exact query `Fruit ⊓ ¬EdibleThing`, unbounded and at the 200ms classify
|
|
1715
|
+
/// budget. Settles timeout-vs-wrong-verdict. See
|
|
1716
|
+
/// `docs/wine-residual-31-diagnosis-2026-06-07.md`. `#[ignore]`d (needs the
|
|
1717
|
+
/// gitignored wine fixture); run with `-- --ignored --nocapture`.
|
|
1718
|
+
#[test]
|
|
1719
|
+
#[ignore = "needs ontologies/real/wine.ofn; diagnostic for the Fruit cluster-A classify miss"]
|
|
1720
|
+
fn wine_fruit_prepared_vs_fresh_probe() {
|
|
1721
|
+
use horned_owl::io::ofn::reader::read as read_ofn;
|
|
1722
|
+
let path = std::path::Path::new("../../ontologies/real/wine.ofn");
|
|
1723
|
+
if !path.exists() {
|
|
1724
|
+
eprintln!("SKIP: missing {}", path.display());
|
|
1725
|
+
return;
|
|
1726
|
+
}
|
|
1727
|
+
let f = "http://www.w3.org/TR/2003/PR-owl-guide-20031209/food#Fruit";
|
|
1728
|
+
let e = "http://www.w3.org/TR/2003/PR-owl-guide-20031209/food#EdibleThing";
|
|
1729
|
+
let src = std::fs::read_to_string(path).expect("read wine");
|
|
1730
|
+
let parse_onto = || {
|
|
1731
|
+
let mut r = Cursor::new(src.clone());
|
|
1732
|
+
let (o, _): (SetOntology<RcStr>, _) =
|
|
1733
|
+
read_ofn(&mut r, ParserConfiguration::default()).expect("parse wine");
|
|
1734
|
+
o
|
|
1735
|
+
};
|
|
1736
|
+
|
|
1737
|
+
// Fresh path (what subclass / explain use).
|
|
1738
|
+
let fresh = crate::is_subclass_of(&parse_onto(), f, e).expect("fresh is_subclass_of");
|
|
1739
|
+
eprintln!("FRESH is_subclass_of(Fruit, EdibleThing) = {fresh}");
|
|
1740
|
+
|
|
1741
|
+
// Classify-path: PreparedOntology::decide on `Fruit ⊓ ¬EdibleThing`.
|
|
1742
|
+
let internal = owl_dl_core::convert::convert_ontology(&parse_onto()).expect("convert");
|
|
1743
|
+
let cons = "http://www.w3.org/TR/2003/PR-owl-guide-20031209/food#ConsumableThing";
|
|
1744
|
+
let fid = internal.vocabulary.class_id(f).expect("Fruit id");
|
|
1745
|
+
let eid = internal.vocabulary.class_id(e).expect("EdibleThing id");
|
|
1746
|
+
let cid = internal
|
|
1747
|
+
.vocabulary
|
|
1748
|
+
.class_id(cons)
|
|
1749
|
+
.expect("ConsumableThing id");
|
|
1750
|
+
// EL closure witness?
|
|
1751
|
+
let closure = owl_dl_saturation::saturate(&internal);
|
|
1752
|
+
eprintln!(
|
|
1753
|
+
"CLOSURE.contains(Fruit, EdibleThing) = {}",
|
|
1754
|
+
closure.contains(fid, eid)
|
|
1755
|
+
);
|
|
1756
|
+
let prepared = PreparedOntology::from_internal(internal).expect("prepare");
|
|
1757
|
+
// The classify walk tries the WEDGE first (hyper_decide), only falling
|
|
1758
|
+
// to the tableau on a non-proof. Measure both deadlines.
|
|
1759
|
+
let tw = std::time::Instant::now();
|
|
1760
|
+
let wedge_unbounded = prepared.hyper_decide(fid, eid, None);
|
|
1761
|
+
eprintln!(
|
|
1762
|
+
"WEDGE prepared.hyper_decide(None) = {wedge_unbounded:?} in {} ms",
|
|
1763
|
+
tw.elapsed().as_millis()
|
|
1764
|
+
);
|
|
1765
|
+
let tw2 = std::time::Instant::now();
|
|
1766
|
+
let wdl = std::time::Instant::now() + std::time::Duration::from_millis(200);
|
|
1767
|
+
let wedge_200 = prepared.hyper_decide(fid, eid, Some(wdl));
|
|
1768
|
+
eprintln!(
|
|
1769
|
+
"WEDGE prepared.hyper_decide(Fruit,EdibleThing,200ms) = {wedge_200:?} in {} ms",
|
|
1770
|
+
tw2.elapsed().as_millis()
|
|
1771
|
+
);
|
|
1772
|
+
// The descent GATE: EdibleThing ⊑ ConsumableThing (top-level), so the
|
|
1773
|
+
// walk reaches EdibleThing only by first accepting ConsumableThing.
|
|
1774
|
+
let tc = std::time::Instant::now();
|
|
1775
|
+
let cdl = std::time::Instant::now() + std::time::Duration::from_millis(200);
|
|
1776
|
+
let wedge_cons = prepared.hyper_decide(fid, cid, Some(cdl));
|
|
1777
|
+
eprintln!(
|
|
1778
|
+
"WEDGE prepared.hyper_decide(Fruit,ConsumableThing,200ms) = {wedge_cons:?} in {} ms [descent gate]",
|
|
1779
|
+
tc.elapsed().as_millis()
|
|
1780
|
+
);
|
|
1781
|
+
// SEPARATE finding (NOT cluster A's cause — the WEDGE proves Fruit ⊑
|
|
1782
|
+
// EdibleThing in 0 ms above, so the tableau is never reached for this
|
|
1783
|
+
// pair in classify). The ABox/nominal-seeded `prepared.decide` is
|
|
1784
|
+
// pathologically slow / non-terminating: a 5 s deadline times out, vs the
|
|
1785
|
+
// fresh path's 0.01 s (unbounded does not return in 150 s — do NOT call
|
|
1786
|
+
// it). This matters for the B/C/D pairs (whose wedge does NOT prove them
|
|
1787
|
+
// → tableau fallback). Cluster A's actual cause is the defined-sup sweep
|
|
1788
|
+
// coverage gap; see docs/classify-recovery-scope-2026-06-07.md.
|
|
1789
|
+
let build = |pool: &mut owl_dl_core::ir::ConceptPool| {
|
|
1790
|
+
let fc = pool.atomic(fid);
|
|
1791
|
+
let ec = pool.atomic(eid);
|
|
1792
|
+
let nec = pool.not(ec);
|
|
1793
|
+
pool.and(vec![fc, nec])
|
|
1794
|
+
};
|
|
1795
|
+
let t0 = std::time::Instant::now();
|
|
1796
|
+
let deadline = std::time::Instant::now() + std::time::Duration::from_secs(5);
|
|
1797
|
+
let bounded = prepared
|
|
1798
|
+
.decide_with_deadline(deadline, build)
|
|
1799
|
+
.expect("prepared.decide_with_deadline");
|
|
1800
|
+
let ms = t0.elapsed().as_millis();
|
|
1801
|
+
eprintln!("PREPARED.decide_with_deadline(5s) = {bounded:?} (None=timeout) in {ms} ms");
|
|
1802
|
+
|
|
1803
|
+
eprintln!(
|
|
1804
|
+
"VERDICT: {}",
|
|
1805
|
+
match (fresh, bounded) {
|
|
1806
|
+
(true, None) =>
|
|
1807
|
+
"wedge proves it in 0ms (cluster A = defined-sup-sweep gap); \
|
|
1808
|
+
SEPARATELY the ABox-seeded prepared.decide tableau times out even at 5s \
|
|
1809
|
+
(non-termination, affects B/C/D)",
|
|
1810
|
+
(true, Some(false)) =>
|
|
1811
|
+
"prepared agrees (subsumed) within 5s ⇒ the miss is only the 200ms budget",
|
|
1812
|
+
(true, Some(true)) =>
|
|
1813
|
+
"prepared returns WRONG Sat ⇒ PreparedOntology completeness bug",
|
|
1814
|
+
_ => "fresh disagrees — re-examine",
|
|
1815
|
+
}
|
|
1816
|
+
);
|
|
1817
|
+
// Pin the established finding: fresh proves it; prepared cannot in 5s.
|
|
1818
|
+
assert!(fresh, "fresh is_subclass_of must prove Fruit ⊑ EdibleThing");
|
|
1819
|
+
assert_eq!(
|
|
1820
|
+
bounded, None,
|
|
1821
|
+
"regression: prepared.decide now finishes in 5s — the ABox-seeding \
|
|
1822
|
+
pathology may be fixed; update docs/wine-residual-31-diagnosis"
|
|
1823
|
+
);
|
|
1824
|
+
}
|
|
1825
|
+
|
|
1628
1826
|
const HEADER: &str = "\
|
|
1629
1827
|
Prefix(:=<http://rustdl.test/>)\n\
|
|
1630
1828
|
Prefix(owl:=<http://www.w3.org/2002/07/owl#>)\n";
|
|
@@ -1700,6 +1898,41 @@ Ontology(<http://rustdl.test/test>\n\
|
|
|
1700
1898
|
assert_eq!(direct, vec![iri("B")]);
|
|
1701
1899
|
}
|
|
1702
1900
|
|
|
1901
|
+
/// Regression for the defined-SUB sweep (cluster A; wine residual-31,
|
|
1902
|
+
/// 2026-06-07). A union/covering-defined sub `C ≡ A ⊔ B` ⊑ a PRIMITIVE sup
|
|
1903
|
+
/// `X` (every disjunct `⊑ X`) is missed by both the tier-walk (the covering
|
|
1904
|
+
/// subsumption isn't in the EL closure) and the defined-sup sweep (`X` is
|
|
1905
|
+
/// primitive). The companion defined-SUB sweep recovers it soundly by
|
|
1906
|
+
/// construction. Mirrors wine's `Fruit ≡ NonSweetFruit ⊔ SweetFruit ⊑
|
|
1907
|
+
/// EdibleThing`. See docs/classify-recovery-scope-2026-06-07.md.
|
|
1908
|
+
#[test]
|
|
1909
|
+
fn defined_union_sub_under_primitive_sup() {
|
|
1910
|
+
let onto = parse(&format!(
|
|
1911
|
+
"{HEADER}\
|
|
1912
|
+
Ontology(<http://rustdl.test/test>\n\
|
|
1913
|
+
Declaration(Class(:C))\n\
|
|
1914
|
+
Declaration(Class(:A))\n\
|
|
1915
|
+
Declaration(Class(:B))\n\
|
|
1916
|
+
Declaration(Class(:X))\n\
|
|
1917
|
+
EquivalentClasses(:C ObjectUnionOf(:A :B))\n\
|
|
1918
|
+
SubClassOf(:A :X)\n\
|
|
1919
|
+
SubClassOf(:B :X)\n\
|
|
1920
|
+
)\n"
|
|
1921
|
+
));
|
|
1922
|
+
let h = classify(&onto).expect("classification");
|
|
1923
|
+
let iri = |s: &str| format!("http://rustdl.test/{s}");
|
|
1924
|
+
// C ≡ A ⊔ B, A ⊑ X, B ⊑ X ⟹ C ⊑ X (every model element of C is in
|
|
1925
|
+
// A or B, both ⊑ X). `X` is primitive, so only the defined-SUB sweep
|
|
1926
|
+
// recovers this.
|
|
1927
|
+
assert!(
|
|
1928
|
+
h.is_subclass(&iri("C"), &iri("X")),
|
|
1929
|
+
"defined-SUB sweep must place C ⊑ X"
|
|
1930
|
+
);
|
|
1931
|
+
// Disjuncts and the union are mutually subsumed by X but not vice versa.
|
|
1932
|
+
assert!(h.is_subclass(&iri("A"), &iri("X")));
|
|
1933
|
+
assert!(!h.is_subclass(&iri("X"), &iri("C")));
|
|
1934
|
+
}
|
|
1935
|
+
|
|
1703
1936
|
#[test]
|
|
1704
1937
|
fn classify_groups_equivalents() {
|
|
1705
1938
|
// EquivalentClasses(A, B) — they should appear as each
|
|
@@ -577,6 +577,9 @@ pub fn hyper_subsumption_probe<A: horned_owl::model::ForIRI>(
|
|
|
577
577
|
if hyper_double_block_enabled() {
|
|
578
578
|
engine = engine.with_double_blocking();
|
|
579
579
|
}
|
|
580
|
+
if hyper_precise_card_deps_enabled() {
|
|
581
|
+
engine = engine.with_precise_card_deps();
|
|
582
|
+
}
|
|
580
583
|
let result = engine.decide_with_deadline(max_depth, deadline);
|
|
581
584
|
let stats = engine.stats();
|
|
582
585
|
let wall_ms = start.elapsed().as_secs_f64() * 1000.0;
|
|
@@ -637,6 +640,23 @@ pub fn hyper_double_block_enabled() -> bool {
|
|
|
637
640
|
std::env::var_os("RUSTDL_HYPER_DOUBLE_BLOCK").is_none_or(|v| v != "0" && !v.is_empty())
|
|
638
641
|
}
|
|
639
642
|
|
|
643
|
+
/// Precise (sound over-approx) `≤n`-cardinality clash deps
|
|
644
|
+
/// (`RUSTDL_PRECISE_CARD_DEPS`). At the `forced_distinct_exceeds` pre-check site
|
|
645
|
+
/// replaces the conservative `DepSet::ALL` with `parent.at_most_dep ∪ ⋃(birth ∪
|
|
646
|
+
/// label of succs) ∪ parent(birth ∪ label)` — a provable superset of the clash's
|
|
647
|
+
/// true deps (sound by construction; see `card_clash_deps`), guarded by the
|
|
648
|
+
/// own-successor / `≠`-only / merge-taint fallbacks. Unblocks dependency-directed
|
|
649
|
+
/// backjumping on cardinality clashes (wine MISSED 34→31, −25% wall, FP=0;
|
|
650
|
+
/// see `docs/backjump-reconcile-2026-06-06.md`). **Default on** as of the flip
|
|
651
|
+
/// (2026-06-06): sound by construction, FP=0 across the cardinality/nominal
|
|
652
|
+
/// corpus, and inert on the EL/Horn corpus (Horn-shortcircuited, never enters
|
|
653
|
+
/// the wedge cardinality path). Set `RUSTDL_PRECISE_CARD_DEPS=0` to revert to the
|
|
654
|
+
/// conservative `DepSet::ALL` behaviour.
|
|
655
|
+
#[must_use]
|
|
656
|
+
pub fn hyper_precise_card_deps_enabled() -> bool {
|
|
657
|
+
std::env::var_os("RUSTDL_PRECISE_CARD_DEPS").is_none_or(|v| v != "0" && !v.is_empty())
|
|
658
|
+
}
|
|
659
|
+
|
|
640
660
|
/// HF5: whether the wedge is allowed to *trust* the engine's `Sat`
|
|
641
661
|
/// verdict (concluding "not subsumed" without consulting the tableau).
|
|
642
662
|
/// `Unsat` is sound by construction for any ontology; `Sat` is sound
|
|
@@ -914,6 +934,9 @@ impl HyperCache {
|
|
|
914
934
|
if hyper_double_block_enabled() {
|
|
915
935
|
engine = engine.with_double_blocking();
|
|
916
936
|
}
|
|
937
|
+
if hyper_precise_card_deps_enabled() {
|
|
938
|
+
engine = engine.with_precise_card_deps();
|
|
939
|
+
}
|
|
917
940
|
match engine.decide_with_deadline(HYPER_WEDGE_DEPTH, deadline) {
|
|
918
941
|
HyperResult::Unsat => HyperVerdict::Subsumed,
|
|
919
942
|
HyperResult::Sat => HyperVerdict::NotSubsumed,
|
|
@@ -942,6 +965,9 @@ impl HyperCache {
|
|
|
942
965
|
if hyper_double_block_enabled() {
|
|
943
966
|
engine = engine.with_double_blocking();
|
|
944
967
|
}
|
|
968
|
+
if hyper_precise_card_deps_enabled() {
|
|
969
|
+
engine = engine.with_precise_card_deps();
|
|
970
|
+
}
|
|
945
971
|
match engine.decide_with_deadline(HYPER_WEDGE_DEPTH, deadline) {
|
|
946
972
|
HyperResult::Unsat => LabelOracle::Unsat,
|
|
947
973
|
HyperResult::Sat => engine
|
|
@@ -390,7 +390,11 @@ fn wine_closure_matches_konclude() {
|
|
|
390
390
|
eprintln!("SKIP: missing wine fixture");
|
|
391
391
|
return;
|
|
392
392
|
}
|
|
393
|
-
let
|
|
393
|
+
let budget = std::env::var("RUSTDL_TEST_PAIR_MS")
|
|
394
|
+
.ok()
|
|
395
|
+
.and_then(|v| v.parse().ok())
|
|
396
|
+
.unwrap_or(200);
|
|
397
|
+
let (_r, _k, fp, _m) = diff_corpus_ontology("wine", input, truth, budget);
|
|
394
398
|
assert_eq!(
|
|
395
399
|
fp, 0,
|
|
396
400
|
"wine has FPs — soundness regression on nominals/datatypes"
|