fuzzy-dl-owl2 1.0.1__py3-none-any.whl → 1.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fuzzy_dl_owl2/fuzzydl/concept/approximation_concept.py +35 -10
- fuzzy_dl_owl2/fuzzydl/concept/concrete/fuzzy_number/triangular_fuzzy_number.py +2 -1
- fuzzy_dl_owl2/fuzzydl/concept/concrete/trapezoidal_concrete_concept.py +1 -0
- fuzzy_dl_owl2/fuzzydl/concept/implies_concept.py +14 -11
- fuzzy_dl_owl2/fuzzydl/concept/operator_concept.py +10 -6
- fuzzy_dl_owl2/fuzzydl/concept/value_concept.py +1 -1
- fuzzy_dl_owl2/fuzzydl/concrete_feature.py +7 -1
- fuzzy_dl_owl2/fuzzydl/feature_function.py +16 -2
- fuzzy_dl_owl2/fuzzydl/fuzzydl_to_owl2.py +1 -1
- fuzzy_dl_owl2/fuzzydl/knowledge_base.py +494 -358
- fuzzy_dl_owl2/fuzzydl/milp/expression.py +4 -2
- fuzzy_dl_owl2/fuzzydl/milp/milp_helper.py +3 -2
- fuzzy_dl_owl2/fuzzydl/milp/variable.py +3 -0
- fuzzy_dl_owl2/fuzzydl/modifier/triangular_modifier.py +1 -1
- fuzzy_dl_owl2/fuzzydl/parser/dl_parser.py +1465 -1210
- fuzzy_dl_owl2/fuzzydl/query/defuzzify/mom_defuzzify_query.py +14 -7
- fuzzy_dl_owl2/fuzzydl/query/min/min_subsumes_query.py +2 -2
- fuzzy_dl_owl2/fuzzydl/util/config_reader.py +0 -6
- fuzzy_dl_owl2/fuzzydl/util/constants.py +10 -9
- fuzzy_dl_owl2/fuzzydl/util/utils.py +48 -7
- fuzzy_dl_owl2/fuzzyowl2/fuzzyowl2.py +1 -1
- {fuzzy_dl_owl2-1.0.1.dist-info → fuzzy_dl_owl2-1.0.3.dist-info}/METADATA +51 -10
- {fuzzy_dl_owl2-1.0.1.dist-info → fuzzy_dl_owl2-1.0.3.dist-info}/RECORD +25 -31
- fuzzy_dl_owl2/fuzzydl/fuzzydl_to_owl2_java.py +0 -953
- fuzzy_dl_owl2/fuzzydl/parser/ParserConstants.py +0 -406
- fuzzy_dl_owl2/fuzzydl/parser/ebnf.lark +0 -290
- fuzzy_dl_owl2/fuzzydl/parser/larkx.py +0 -70
- fuzzy_dl_owl2/fuzzyowl2/fuzzyowl2_java.py +0 -1409
- fuzzy_dl_owl2/fuzzyowl2/fuzzyowl2_to_fuzzydl_java.py +0 -956
- {fuzzy_dl_owl2-1.0.1.dist-info → fuzzy_dl_owl2-1.0.3.dist-info}/LICENSE +0 -0
- {fuzzy_dl_owl2-1.0.1.dist-info → fuzzy_dl_owl2-1.0.3.dist-info}/WHEEL +0 -0
|
@@ -10,79 +10,84 @@ from sortedcontainers import SortedSet
|
|
|
10
10
|
|
|
11
11
|
from fuzzy_dl_owl2.fuzzydl.assertion.assertion import Assertion
|
|
12
12
|
from fuzzy_dl_owl2.fuzzydl.concept.all_some_concept import AllSomeConcept
|
|
13
|
-
from fuzzy_dl_owl2.fuzzydl.concept.approximation_concept import
|
|
14
|
-
ApproximationConcept
|
|
13
|
+
from fuzzy_dl_owl2.fuzzydl.concept.approximation_concept import ApproximationConcept
|
|
15
14
|
from fuzzy_dl_owl2.fuzzydl.concept.atomic_concept import AtomicConcept
|
|
16
15
|
from fuzzy_dl_owl2.fuzzydl.concept.choquet_integral import ChoquetIntegral
|
|
17
16
|
from fuzzy_dl_owl2.fuzzydl.concept.concept import Concept
|
|
18
|
-
from fuzzy_dl_owl2.fuzzydl.concept.concrete.crisp_concrete_concept import
|
|
19
|
-
CrispConcreteConcept
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
from fuzzy_dl_owl2.fuzzydl.concept.concrete.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
from fuzzy_dl_owl2.fuzzydl.concept.concrete.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
from fuzzy_dl_owl2.fuzzydl.concept.
|
|
37
|
-
|
|
17
|
+
from fuzzy_dl_owl2.fuzzydl.concept.concrete.crisp_concrete_concept import (
|
|
18
|
+
CrispConcreteConcept,
|
|
19
|
+
)
|
|
20
|
+
from fuzzy_dl_owl2.fuzzydl.concept.concrete.fuzzy_concrete_concept import (
|
|
21
|
+
FuzzyConcreteConcept,
|
|
22
|
+
)
|
|
23
|
+
from fuzzy_dl_owl2.fuzzydl.concept.concrete.fuzzy_number.triangular_fuzzy_number import (
|
|
24
|
+
TriangularFuzzyNumber,
|
|
25
|
+
)
|
|
26
|
+
from fuzzy_dl_owl2.fuzzydl.concept.concrete.left_concrete_concept import (
|
|
27
|
+
LeftConcreteConcept,
|
|
28
|
+
)
|
|
29
|
+
from fuzzy_dl_owl2.fuzzydl.concept.concrete.linear_concrete_concept import (
|
|
30
|
+
LinearConcreteConcept,
|
|
31
|
+
)
|
|
32
|
+
from fuzzy_dl_owl2.fuzzydl.concept.concrete.modified_concrete_concept import (
|
|
33
|
+
ModifiedConcreteConcept,
|
|
34
|
+
)
|
|
35
|
+
from fuzzy_dl_owl2.fuzzydl.concept.concrete.right_concrete_concept import (
|
|
36
|
+
RightConcreteConcept,
|
|
37
|
+
)
|
|
38
|
+
from fuzzy_dl_owl2.fuzzydl.concept.concrete.trapezoidal_concrete_concept import (
|
|
39
|
+
TrapezoidalConcreteConcept,
|
|
40
|
+
)
|
|
41
|
+
from fuzzy_dl_owl2.fuzzydl.concept.concrete.triangular_concrete_concept import (
|
|
42
|
+
TriangularConcreteConcept,
|
|
43
|
+
)
|
|
44
|
+
from fuzzy_dl_owl2.fuzzydl.concept.ext_threshold_concept import ExtThresholdConcept
|
|
38
45
|
from fuzzy_dl_owl2.fuzzydl.concept.has_value_concept import HasValueConcept
|
|
39
46
|
from fuzzy_dl_owl2.fuzzydl.concept.implies_concept import ImpliesConcept
|
|
40
|
-
from fuzzy_dl_owl2.fuzzydl.concept.interface.has_concepts_interface import
|
|
41
|
-
HasConceptsInterface
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
from fuzzy_dl_owl2.fuzzydl.concept.interface.has_value_interface import
|
|
45
|
-
HasValueInterface
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
from fuzzy_dl_owl2.fuzzydl.concept.modified.triangularly_modified_concept import
|
|
49
|
-
TriangularlyModifiedConcept
|
|
47
|
+
from fuzzy_dl_owl2.fuzzydl.concept.interface.has_concepts_interface import (
|
|
48
|
+
HasConceptsInterface,
|
|
49
|
+
)
|
|
50
|
+
from fuzzy_dl_owl2.fuzzydl.concept.interface.has_role_interface import HasRoleInterface
|
|
51
|
+
from fuzzy_dl_owl2.fuzzydl.concept.interface.has_value_interface import (
|
|
52
|
+
HasValueInterface,
|
|
53
|
+
)
|
|
54
|
+
from fuzzy_dl_owl2.fuzzydl.concept.modified.modified_concept import ModifiedConcept
|
|
55
|
+
from fuzzy_dl_owl2.fuzzydl.concept.modified.triangularly_modified_concept import (
|
|
56
|
+
TriangularlyModifiedConcept,
|
|
57
|
+
)
|
|
50
58
|
from fuzzy_dl_owl2.fuzzydl.concept.negated_nominal import NegatedNominal
|
|
51
59
|
from fuzzy_dl_owl2.fuzzydl.concept.operator_concept import OperatorConcept
|
|
52
60
|
from fuzzy_dl_owl2.fuzzydl.concept.owa_concept import OwaConcept
|
|
53
61
|
from fuzzy_dl_owl2.fuzzydl.concept.qowa_concept import QowaConcept
|
|
54
|
-
from fuzzy_dl_owl2.fuzzydl.concept.quasi_sugeno_integral import
|
|
55
|
-
QsugenoIntegral
|
|
62
|
+
from fuzzy_dl_owl2.fuzzydl.concept.quasi_sugeno_integral import QsugenoIntegral
|
|
56
63
|
from fuzzy_dl_owl2.fuzzydl.concept.self_concept import SelfConcept
|
|
57
64
|
from fuzzy_dl_owl2.fuzzydl.concept.sugeno_integral import SugenoIntegral
|
|
58
65
|
from fuzzy_dl_owl2.fuzzydl.concept.threshold_concept import ThresholdConcept
|
|
59
66
|
from fuzzy_dl_owl2.fuzzydl.concept.truth_concept import TruthConcept
|
|
60
67
|
from fuzzy_dl_owl2.fuzzydl.concept.value_concept import ValueConcept
|
|
61
68
|
from fuzzy_dl_owl2.fuzzydl.concept.weighted_concept import WeightedConcept
|
|
62
|
-
from fuzzy_dl_owl2.fuzzydl.concept.weighted_max_concept import
|
|
63
|
-
|
|
64
|
-
from fuzzy_dl_owl2.fuzzydl.concept.
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
from fuzzy_dl_owl2.fuzzydl.concept.weighted_sum_zero_concept import \
|
|
69
|
-
WeightedSumZeroConcept
|
|
69
|
+
from fuzzy_dl_owl2.fuzzydl.concept.weighted_max_concept import WeightedMaxConcept
|
|
70
|
+
from fuzzy_dl_owl2.fuzzydl.concept.weighted_min_concept import WeightedMinConcept
|
|
71
|
+
from fuzzy_dl_owl2.fuzzydl.concept.weighted_sum_concept import WeightedSumConcept
|
|
72
|
+
from fuzzy_dl_owl2.fuzzydl.concept.weighted_sum_zero_concept import (
|
|
73
|
+
WeightedSumZeroConcept,
|
|
74
|
+
)
|
|
70
75
|
from fuzzy_dl_owl2.fuzzydl.concept_equivalence import ConceptEquivalence
|
|
71
76
|
from fuzzy_dl_owl2.fuzzydl.concrete_feature import ConcreteFeature
|
|
72
77
|
from fuzzy_dl_owl2.fuzzydl.degree.degree import Degree
|
|
73
78
|
from fuzzy_dl_owl2.fuzzydl.degree.degree_expression import DegreeExpression
|
|
74
79
|
from fuzzy_dl_owl2.fuzzydl.degree.degree_numeric import DegreeNumeric
|
|
75
80
|
from fuzzy_dl_owl2.fuzzydl.degree.degree_variable import DegreeVariable
|
|
76
|
-
from fuzzy_dl_owl2.fuzzydl.exception.inconsistent_ontology_exception import
|
|
77
|
-
InconsistentOntologyException
|
|
81
|
+
from fuzzy_dl_owl2.fuzzydl.exception.inconsistent_ontology_exception import (
|
|
82
|
+
InconsistentOntologyException,
|
|
83
|
+
)
|
|
78
84
|
from fuzzy_dl_owl2.fuzzydl.feature_function import FeatureFunction
|
|
79
|
-
from fuzzy_dl_owl2.fuzzydl.general_concept_inclusion import
|
|
80
|
-
|
|
81
|
-
from fuzzy_dl_owl2.fuzzydl.individual.created_individual import \
|
|
82
|
-
CreatedIndividual
|
|
85
|
+
from fuzzy_dl_owl2.fuzzydl.general_concept_inclusion import GeneralConceptInclusion
|
|
86
|
+
from fuzzy_dl_owl2.fuzzydl.individual.created_individual import CreatedIndividual
|
|
83
87
|
from fuzzy_dl_owl2.fuzzydl.individual.individual import Individual
|
|
84
|
-
from fuzzy_dl_owl2.fuzzydl.individual.representative_individual import
|
|
85
|
-
RepresentativeIndividual
|
|
88
|
+
from fuzzy_dl_owl2.fuzzydl.individual.representative_individual import (
|
|
89
|
+
RepresentativeIndividual,
|
|
90
|
+
)
|
|
86
91
|
from fuzzy_dl_owl2.fuzzydl.milp.expression import Expression
|
|
87
92
|
from fuzzy_dl_owl2.fuzzydl.milp.milp_helper import MILPHelper
|
|
88
93
|
from fuzzy_dl_owl2.fuzzydl.milp.solution import Solution
|
|
@@ -90,28 +95,38 @@ from fuzzy_dl_owl2.fuzzydl.milp.term import Term
|
|
|
90
95
|
from fuzzy_dl_owl2.fuzzydl.milp.variable import Variable
|
|
91
96
|
from fuzzy_dl_owl2.fuzzydl.modifier.linear_modifier import LinearModifier
|
|
92
97
|
from fuzzy_dl_owl2.fuzzydl.modifier.modifier import Modifier
|
|
93
|
-
from fuzzy_dl_owl2.fuzzydl.modifier.triangular_modifier import
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
98
|
+
from fuzzy_dl_owl2.fuzzydl.modifier.triangular_modifier import TriangularModifier
|
|
99
|
+
from fuzzy_dl_owl2.fuzzydl.primitive_concept_definition import (
|
|
100
|
+
PrimitiveConceptDefinition,
|
|
101
|
+
)
|
|
97
102
|
from fuzzy_dl_owl2.fuzzydl.relation import Relation
|
|
98
|
-
from fuzzy_dl_owl2.fuzzydl.restriction.has_value_restriction import
|
|
99
|
-
HasValueRestriction
|
|
103
|
+
from fuzzy_dl_owl2.fuzzydl.restriction.has_value_restriction import HasValueRestriction
|
|
100
104
|
from fuzzy_dl_owl2.fuzzydl.restriction.restriction import Restriction
|
|
101
105
|
from fuzzy_dl_owl2.fuzzydl.util import constants
|
|
102
106
|
from fuzzy_dl_owl2.fuzzydl.util.config_reader import ConfigReader
|
|
103
107
|
from fuzzy_dl_owl2.fuzzydl.util.constants import (
|
|
104
|
-
BlockingDynamicType,
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
+
BlockingDynamicType,
|
|
109
|
+
ConceptType,
|
|
110
|
+
ConcreteFeatureType,
|
|
111
|
+
CreatedIndividualBlockingType,
|
|
112
|
+
FeatureFunctionType,
|
|
113
|
+
FuzzyLogic,
|
|
114
|
+
InequalityType,
|
|
115
|
+
KnowledgeBaseRules,
|
|
116
|
+
LogicOperatorType,
|
|
117
|
+
RepresentativeIndividualType,
|
|
118
|
+
RestrictionType,
|
|
119
|
+
VariableType,
|
|
120
|
+
)
|
|
108
121
|
from fuzzy_dl_owl2.fuzzydl.util.util import Util
|
|
122
|
+
from fuzzy_dl_owl2.fuzzydl.util.utils import class_debugging
|
|
109
123
|
|
|
110
124
|
|
|
125
|
+
@class_debugging()
|
|
111
126
|
class KnowledgeBase:
|
|
112
|
-
VERSION: float = 2.0
|
|
113
127
|
|
|
114
128
|
def __init__(self) -> None:
|
|
129
|
+
Variable.VARIABLE_NUMBER = 0
|
|
115
130
|
self.language: str = ""
|
|
116
131
|
|
|
117
132
|
self.milp: MILPHelper = MILPHelper()
|
|
@@ -342,7 +357,9 @@ class KnowledgeBase:
|
|
|
342
357
|
k: [r.clone() for r in v] for k, v in self.temp_relations_list.items()
|
|
343
358
|
}
|
|
344
359
|
kb.t_G = [gci.clone() for gci in self.t_G]
|
|
345
|
-
kb.t_inclusions = {
|
|
360
|
+
kb.t_inclusions = {
|
|
361
|
+
k: set([pcd.clone() for pcd in v]) for k, v in self.t_inclusions.items()
|
|
362
|
+
}
|
|
346
363
|
kb.transitive_roles = copy.deepcopy(self.transitive_roles)
|
|
347
364
|
kb.t_synonyms = copy.deepcopy(self.t_synonyms)
|
|
348
365
|
return kb
|
|
@@ -746,9 +763,9 @@ class KnowledgeBase:
|
|
|
746
763
|
return rel
|
|
747
764
|
|
|
748
765
|
def define_synonym(self, concept_name_1: str, concept_name_2: str) -> None:
|
|
749
|
-
self.t_synonyms[concept_name_1] = self.t_synonyms.get(
|
|
750
|
-
|
|
751
|
-
)
|
|
766
|
+
self.t_synonyms[concept_name_1] = self.t_synonyms.get(
|
|
767
|
+
concept_name_1, set()
|
|
768
|
+
) | set([concept_name_2])
|
|
752
769
|
self.get_concept(concept_name_1)
|
|
753
770
|
|
|
754
771
|
def define_synonyms(self, concept_name_1: str, concept_name_2: str) -> None:
|
|
@@ -1262,7 +1279,9 @@ class KnowledgeBase:
|
|
|
1262
1279
|
|
|
1263
1280
|
def add_simple_inverse_roles(self, role: str, inv_role: str) -> None:
|
|
1264
1281
|
self.inverse_roles[role] = self.inverse_roles.get(role, set()) | set([inv_role])
|
|
1265
|
-
self.inverse_roles[inv_role] = self.inverse_roles.get(inv_role, set()) | set(
|
|
1282
|
+
self.inverse_roles[inv_role] = self.inverse_roles.get(inv_role, set()) | set(
|
|
1283
|
+
[role]
|
|
1284
|
+
)
|
|
1266
1285
|
if role in self.inverse_functional_roles:
|
|
1267
1286
|
self.functional_roles.add(inv_role)
|
|
1268
1287
|
if inv_role in self.inverse_functional_roles:
|
|
@@ -1746,7 +1765,7 @@ class KnowledgeBase:
|
|
|
1746
1765
|
Util.debug(f"{constants.SEPARATOR}GCI completed{constants.SEPARATOR}")
|
|
1747
1766
|
|
|
1748
1767
|
def solve_reflexive_role(self, role: str) -> None:
|
|
1749
|
-
for ind in self.individuals:
|
|
1768
|
+
for ind in self.individuals.values():
|
|
1750
1769
|
self.add_relation(ind, role, ind, DegreeNumeric.get_degree(1.0))
|
|
1751
1770
|
|
|
1752
1771
|
@typing.overload
|
|
@@ -1789,7 +1808,7 @@ class KnowledgeBase:
|
|
|
1789
1808
|
def __get_correct_version_of_individual_1(self, ass: Assertion) -> None:
|
|
1790
1809
|
ind: Individual = ass.get_individual()
|
|
1791
1810
|
ind2: Individual = self.individuals.get(str(ind))
|
|
1792
|
-
if ind == ind2:
|
|
1811
|
+
if id(ind) == id(ind2):
|
|
1793
1812
|
return
|
|
1794
1813
|
if ind2 is None:
|
|
1795
1814
|
ind2 = self.get_individual(str(ind))
|
|
@@ -1799,7 +1818,7 @@ class KnowledgeBase:
|
|
|
1799
1818
|
def __get_correct_version_of_individual_2(self, rel: Relation) -> None:
|
|
1800
1819
|
ind: Individual = rel.get_object_individual()
|
|
1801
1820
|
ind2: Individual = self.individuals.get(str(ind))
|
|
1802
|
-
if ind == ind2:
|
|
1821
|
+
if id(ind) == id(ind2):
|
|
1803
1822
|
return
|
|
1804
1823
|
if ind2 is None:
|
|
1805
1824
|
ind2 = self.get_individual(str(ind))
|
|
@@ -1880,28 +1899,44 @@ class KnowledgeBase:
|
|
|
1880
1899
|
self.individuals[b_name] = a
|
|
1881
1900
|
|
|
1882
1901
|
def merge(self, a: Individual, b: Individual) -> None:
|
|
1902
|
+
"""
|
|
1903
|
+
Merges two individuals.
|
|
1904
|
+
"""
|
|
1905
|
+
|
|
1883
1906
|
if isinstance(a, CreatedIndividual) and not isinstance(b, CreatedIndividual):
|
|
1907
|
+
# Swap b and a, so the created individual is merged into the root individual
|
|
1884
1908
|
a, b = b, a
|
|
1885
1909
|
|
|
1886
1910
|
a_name, b_name = str(a), str(b)
|
|
1887
1911
|
Util.debug(f"Merging individual {b_name} into {a_name}")
|
|
1912
|
+
# To do: nominal variables needed only if language contains "B"
|
|
1913
|
+
|
|
1914
|
+
# Unique Name Assumption
|
|
1888
1915
|
if not isinstance(a, CreatedIndividual) and not isinstance(
|
|
1889
1916
|
b, CreatedIndividual
|
|
1890
1917
|
):
|
|
1918
|
+
# xAisA + xBisB <= 1
|
|
1891
1919
|
x_a_is_a: Variable = self.milp.get_nominal_variable(a_name)
|
|
1892
1920
|
x_b_is_b: Variable = self.milp.get_nominal_variable(b_name, b_name)
|
|
1893
1921
|
self.milp.add_new_constraint(
|
|
1894
1922
|
Expression(-1.0, Term(1.0, x_a_is_a), Term(1.0, x_b_is_b)),
|
|
1895
1923
|
InequalityType.LESS_THAN,
|
|
1896
1924
|
)
|
|
1925
|
+
# Add { b } to a
|
|
1897
1926
|
self.add_labels_with_nodes(b_name, a_name)
|
|
1898
1927
|
|
|
1928
|
+
# --------------------------------------------------------------
|
|
1929
|
+
# 1. Move edges leading to b so that they lead to a
|
|
1930
|
+
# --------------------------------------------------------------
|
|
1899
1931
|
for i in self.individuals.values():
|
|
1900
1932
|
for array in i.role_relations.values():
|
|
1901
1933
|
for r in array:
|
|
1902
1934
|
if r.get_object_individual() == b:
|
|
1903
1935
|
r.set_object_individual(a)
|
|
1904
1936
|
|
|
1937
|
+
# --------------------------------------------------------------------------
|
|
1938
|
+
# 2. Move edges leading from b to a nominal node so that they lead from a
|
|
1939
|
+
# --------------------------------------------------------------------------
|
|
1905
1940
|
to_remove: set[str] = set()
|
|
1906
1941
|
for role, b_rels in b.role_relations.items():
|
|
1907
1942
|
new_rels: list[Relation] = []
|
|
@@ -1910,18 +1945,21 @@ class KnowledgeBase:
|
|
|
1910
1945
|
if not r.get_object_individual().is_blockable():
|
|
1911
1946
|
r.set_subject_individual(a)
|
|
1912
1947
|
a_rels.append(r)
|
|
1913
|
-
|
|
1914
|
-
|
|
1948
|
+
else:
|
|
1949
|
+
new_rels.append(r)
|
|
1915
1950
|
|
|
1916
1951
|
a.role_relations[role] = a_rels
|
|
1917
1952
|
if len(new_rels) == 0:
|
|
1918
1953
|
to_remove.add(role)
|
|
1919
|
-
|
|
1920
|
-
|
|
1954
|
+
else:
|
|
1955
|
+
b.role_relations[role] = new_rels
|
|
1921
1956
|
|
|
1922
1957
|
for role in to_remove:
|
|
1923
1958
|
del b.role_relations[role]
|
|
1924
1959
|
|
|
1960
|
+
# -------------------------------------------------------
|
|
1961
|
+
# 3. Concept assertions using b, now use a
|
|
1962
|
+
# -----------------------------------------------------
|
|
1925
1963
|
for ass in self.assertions:
|
|
1926
1964
|
if str(ass.get_individual()) == b_name:
|
|
1927
1965
|
ass.set_individual(a)
|
|
@@ -1930,8 +1968,15 @@ class KnowledgeBase:
|
|
|
1930
1968
|
if str(ass.get_individual()) == b_name:
|
|
1931
1969
|
ass.set_individual(a)
|
|
1932
1970
|
|
|
1971
|
+
# -----------------------------------------
|
|
1972
|
+
# 4. Variables using b, now use a
|
|
1973
|
+
# -----------------------------------------
|
|
1933
1974
|
param: bool = isinstance(b, CreatedIndividual)
|
|
1934
1975
|
self.milp.change_variable_names(b_name, a_name, param)
|
|
1976
|
+
|
|
1977
|
+
# -----------------------------------------
|
|
1978
|
+
# 5. Prune
|
|
1979
|
+
# -----------------------------------------
|
|
1935
1980
|
b.prune()
|
|
1936
1981
|
|
|
1937
1982
|
def goedel_implies(self, conc1: Concept, conc2: Concept, degree: Degree) -> None:
|
|
@@ -2222,9 +2267,11 @@ class KnowledgeBase:
|
|
|
2222
2267
|
role = typing.cast(AllSomeConcept, conc2).role
|
|
2223
2268
|
c_range: Concept = typing.cast(AllSomeConcept, conc2).curr_concept
|
|
2224
2269
|
else:
|
|
2225
|
-
assert isinstance(conc2,
|
|
2226
|
-
|
|
2227
|
-
|
|
2270
|
+
assert isinstance(conc2, OperatorConcept)
|
|
2271
|
+
has_value: Concept = conc2.get_atom()
|
|
2272
|
+
assert isinstance(has_value, HasValueInterface)
|
|
2273
|
+
role = has_value.role
|
|
2274
|
+
c_range: Concept = NegatedNominal(str(has_value.value))
|
|
2228
2275
|
self.role_range(role, c_range)
|
|
2229
2276
|
self.remove_C_is_a_X(key, tau, atomic)
|
|
2230
2277
|
Util.debug(f"Absorbed: range {role}, {c_range}")
|
|
@@ -2240,8 +2287,14 @@ class KnowledgeBase:
|
|
|
2240
2287
|
if (
|
|
2241
2288
|
type_c2 == ConceptType.ALL or OperatorConcept.is_not_has_value(conc2)
|
|
2242
2289
|
) and degree_is_one:
|
|
2243
|
-
|
|
2244
|
-
|
|
2290
|
+
if OperatorConcept.is_not_has_value(conc2):
|
|
2291
|
+
atom: Concept = typing.cast(OperatorConcept, conc2).get_atom()
|
|
2292
|
+
assert isinstance(atom, HasRoleInterface)
|
|
2293
|
+
role: str = atom.role
|
|
2294
|
+
else:
|
|
2295
|
+
assert isinstance(conc2, HasRoleInterface)
|
|
2296
|
+
role: str = conc2.role
|
|
2297
|
+
|
|
2245
2298
|
if self.is_crisp_role(role) and (
|
|
2246
2299
|
implication_type != LogicOperatorType.KLEENE_DIENES
|
|
2247
2300
|
or constants.KNOWLEDGE_BASE_SEMANTICS == FuzzyLogic.CLASSICAL
|
|
@@ -2266,11 +2319,15 @@ class KnowledgeBase:
|
|
|
2266
2319
|
-conc1,
|
|
2267
2320
|
)
|
|
2268
2321
|
else:
|
|
2269
|
-
assert isinstance(conc2, HasValueInterface)
|
|
2270
2322
|
g_imp_concept: Concept = ImpliesConcept.goedel_implies(
|
|
2271
2323
|
HasValueConcept(
|
|
2272
2324
|
role,
|
|
2273
|
-
str(
|
|
2325
|
+
str(
|
|
2326
|
+
typing.cast(
|
|
2327
|
+
HasValueConcept,
|
|
2328
|
+
typing.cast(OperatorConcept, conc2).get_atom(),
|
|
2329
|
+
).value
|
|
2330
|
+
),
|
|
2274
2331
|
),
|
|
2275
2332
|
-conc1,
|
|
2276
2333
|
)
|
|
@@ -2848,7 +2905,7 @@ class KnowledgeBase:
|
|
|
2848
2905
|
Util.debug("No optimization: DOUBLE_BLOCKING + dynamicblocking")
|
|
2849
2906
|
return
|
|
2850
2907
|
if len(self.inverse_roles) == 0 or len(self.functional_roles) == 0:
|
|
2851
|
-
if len(self.t_G) == 0
|
|
2908
|
+
if len(self.t_G) == 0 and self.is_tbox_acyclic():
|
|
2852
2909
|
self.blocking_type = BlockingDynamicType.NO_BLOCKING
|
|
2853
2910
|
Util.debug("NO_BLOCKING")
|
|
2854
2911
|
else:
|
|
@@ -2945,6 +3002,10 @@ class KnowledgeBase:
|
|
|
2945
3002
|
def __restrict_range_2(
|
|
2946
3003
|
self, x_b: Variable, x_f: Variable, k1: float, k2: float
|
|
2947
3004
|
) -> None:
|
|
3005
|
+
"""
|
|
3006
|
+
Restricts the range of a variable to [k1, k2] if x_f not zero
|
|
3007
|
+
"""
|
|
3008
|
+
# x_b \geq k1
|
|
2948
3009
|
self.milp.add_new_constraint(
|
|
2949
3010
|
Expression(
|
|
2950
3011
|
constants.MAXVAL,
|
|
@@ -2954,6 +3015,7 @@ class KnowledgeBase:
|
|
|
2954
3015
|
),
|
|
2955
3016
|
InequalityType.GREATER_THAN,
|
|
2956
3017
|
)
|
|
3018
|
+
# x_b \leq k2
|
|
2957
3019
|
self.milp.add_new_constraint(
|
|
2958
3020
|
Expression(
|
|
2959
3021
|
-constants.MAXVAL,
|
|
@@ -3048,8 +3110,6 @@ class KnowledgeBase:
|
|
|
3048
3110
|
def solve_kb(self) -> None:
|
|
3049
3111
|
if constants.KNOWLEDGE_BASE_SEMANTICS is None:
|
|
3050
3112
|
self.set_logic(FuzzyLogic.LUKASIEWICZ)
|
|
3051
|
-
if ConfigReader.SHOW_VERSION:
|
|
3052
|
-
Util.info(f"Version: {self.get_version()}")
|
|
3053
3113
|
self.compute_language()
|
|
3054
3114
|
self.convert_strings_into_integers()
|
|
3055
3115
|
self.solve_inverse_roles()
|
|
@@ -3136,188 +3196,203 @@ class KnowledgeBase:
|
|
|
3136
3196
|
Util.debug(
|
|
3137
3197
|
f"{constants.SEPARATOR}Assertion completed{constants.SEPARATOR}"
|
|
3138
3198
|
)
|
|
3199
|
+
continue
|
|
3200
|
+
|
|
3201
|
+
# Use right version of the individual (needed when we clone the KB or merge individuals)
|
|
3202
|
+
self.get_correct_version_of_individual(ass)
|
|
3203
|
+
if ass.get_individual().is_blockable():
|
|
3204
|
+
Util.debug(
|
|
3205
|
+
f"Direct Blocking status {typing.cast(CreatedIndividual, ass.get_individual()).directly_blocked}"
|
|
3206
|
+
)
|
|
3207
|
+
Util.debug(
|
|
3208
|
+
f"Indirect Blocking status {typing.cast(CreatedIndividual, ass.get_individual()).indirectly_blocked}"
|
|
3209
|
+
)
|
|
3210
|
+
|
|
3211
|
+
# If the individual is indirectly blocked we skip the assertion
|
|
3212
|
+
if (
|
|
3213
|
+
ass.get_individual().is_blockable()
|
|
3214
|
+
and CreatedIndividualHandler.is_indirectly_blocked(
|
|
3215
|
+
typing.cast(CreatedIndividual, ass.get_individual()), self
|
|
3216
|
+
)
|
|
3217
|
+
):
|
|
3218
|
+
name: str = str(ass.get_individual())
|
|
3219
|
+
Util.debug(
|
|
3220
|
+
"Skipping assertion (it has an indirectly blocked individual)"
|
|
3221
|
+
)
|
|
3222
|
+
self.blocked_assertions[name] = self.blocked_assertions.get(
|
|
3223
|
+
name, []
|
|
3224
|
+
) + [ass]
|
|
3225
|
+
continue
|
|
3226
|
+
|
|
3227
|
+
# Add xAss >= lowerBound
|
|
3228
|
+
self.milp.add_new_constraint(ass)
|
|
3229
|
+
if self.is_assertion_processed(ass):
|
|
3230
|
+
Util.debug(
|
|
3231
|
+
f"Assertion (without the degree): {ass} already processed."
|
|
3232
|
+
)
|
|
3233
|
+
continue
|
|
3234
|
+
|
|
3235
|
+
ind: Individual = ass.get_individual()
|
|
3236
|
+
ci: Concept = ass.get_concept()
|
|
3237
|
+
self.add_negated_equations(ind, ci)
|
|
3238
|
+
c_type: ConceptType = ass.get_type()
|
|
3239
|
+
|
|
3240
|
+
# Apply reasoning rule according to the type of the assertion
|
|
3241
|
+
if c_type == ConceptType.ATOMIC:
|
|
3242
|
+
self.rule_atomic(ass)
|
|
3243
|
+
elif ci.is_complemented_atomic():
|
|
3244
|
+
self.rule_complemented_atomic(ass)
|
|
3245
|
+
elif c_type == ConceptType.AND:
|
|
3246
|
+
self.rule_and(ass)
|
|
3247
|
+
elif c_type == ConceptType.OR:
|
|
3248
|
+
self.rule_or(ass)
|
|
3249
|
+
elif c_type in (ConceptType.SOME, ConceptType.HAS_VALUE):
|
|
3250
|
+
self.exist_assertions.append(ass)
|
|
3251
|
+
continue
|
|
3252
|
+
elif c_type == ConceptType.ALL:
|
|
3253
|
+
self.rule_all(ass)
|
|
3254
|
+
elif OperatorConcept.is_not_has_value(ci):
|
|
3255
|
+
self.rule_complemented_has_value(ass)
|
|
3256
|
+
elif c_type == ConceptType.CONCRETE:
|
|
3257
|
+
self.rule_concrete(ass)
|
|
3258
|
+
elif OperatorConcept.is_not_concrete(ci):
|
|
3259
|
+
self.rule_complemented_concrete(ass)
|
|
3260
|
+
elif c_type == ConceptType.FUZZY_NUMBER:
|
|
3261
|
+
self.rule_fuzzy_number(ass)
|
|
3262
|
+
elif OperatorConcept.is_not_fuzzy_number(ci):
|
|
3263
|
+
self.rule_complemented_fuzzy_number(ass)
|
|
3264
|
+
elif c_type == ConceptType.MODIFIED:
|
|
3265
|
+
self.rule_modified(ass)
|
|
3266
|
+
elif OperatorConcept.is_not_modified(ci):
|
|
3267
|
+
self.rule_complemented_modified(ass)
|
|
3268
|
+
elif c_type == ConceptType.TOP:
|
|
3269
|
+
self.rule_top(ass)
|
|
3270
|
+
elif c_type == ConceptType.BOTTOM:
|
|
3271
|
+
self.rule_bottom(ass)
|
|
3272
|
+
elif c_type in (
|
|
3273
|
+
ConceptType.AT_MOST_VALUE,
|
|
3274
|
+
ConceptType.AT_LEAST_VALUE,
|
|
3275
|
+
ConceptType.EXACT_VALUE,
|
|
3276
|
+
):
|
|
3277
|
+
self.positive_concrete_value_assertions.append(ass)
|
|
3278
|
+
elif (
|
|
3279
|
+
OperatorConcept.is_not_at_least_value(ci)
|
|
3280
|
+
or OperatorConcept.is_not_at_most_value(ci)
|
|
3281
|
+
or OperatorConcept.is_not_exact_value(ci)
|
|
3282
|
+
):
|
|
3283
|
+
self.add_negated_datatype_restriction(ass)
|
|
3284
|
+
elif c_type == ConceptType.SELF:
|
|
3285
|
+
self.rule_self(ass)
|
|
3286
|
+
elif OperatorConcept.is_not_self(ci):
|
|
3287
|
+
self.rule_complemented_self(ass)
|
|
3288
|
+
elif c_type == ConceptType.UPPER_APPROX:
|
|
3289
|
+
self.rule_upper_approximation(ass)
|
|
3290
|
+
elif c_type == ConceptType.TIGHT_UPPER_APPROX:
|
|
3291
|
+
self.rule_tight_upper_approximation(ass)
|
|
3292
|
+
elif c_type == ConceptType.LOOSE_UPPER_APPROX:
|
|
3293
|
+
self.rule_loose_upper_approximation(ass)
|
|
3294
|
+
elif c_type == ConceptType.LOWER_APPROX:
|
|
3295
|
+
self.rule_lower_approximation(ass)
|
|
3296
|
+
elif c_type == ConceptType.TIGHT_LOWER_APPROX:
|
|
3297
|
+
self.rule_tight_lower_approximation(ass)
|
|
3298
|
+
elif c_type == ConceptType.LOOSE_LOWER_APPROX:
|
|
3299
|
+
self.rule_loose_lower_approximation(ass)
|
|
3300
|
+
elif c_type == ConceptType.GOEDEL_AND:
|
|
3301
|
+
self.rule_goedel_and(ass)
|
|
3302
|
+
elif c_type == ConceptType.LUKASIEWICZ_AND:
|
|
3303
|
+
self.rule_lukasiewicz_and(ass)
|
|
3304
|
+
elif c_type == ConceptType.GOEDEL_OR:
|
|
3305
|
+
self.rule_goedel_or(ass)
|
|
3306
|
+
elif c_type == ConceptType.LUKASIEWICZ_OR:
|
|
3307
|
+
self.rule_lukasiewicz_or(ass)
|
|
3308
|
+
elif c_type == ConceptType.GOEDEL_IMPLIES:
|
|
3309
|
+
self.rule_goedel_implication(ass)
|
|
3310
|
+
elif OperatorConcept.is_not_goedel_implies(ci):
|
|
3311
|
+
self.rule_complemented_goedel_implication(ass)
|
|
3312
|
+
elif c_type == ConceptType.ZADEH_IMPLIES:
|
|
3313
|
+
self.rule_zadeh_implication(ass)
|
|
3314
|
+
elif OperatorConcept.is_not_zadeh_implies(ci):
|
|
3315
|
+
self.rule_complemented_zadeh_implication(ass)
|
|
3316
|
+
elif c_type == ConceptType.W_SUM:
|
|
3317
|
+
self.rule_weighted_sum(ass)
|
|
3318
|
+
elif OperatorConcept.is_not_weighted_sum(ci):
|
|
3319
|
+
self.rule_complemented_weighted_sum(ass)
|
|
3320
|
+
elif c_type == ConceptType.W_SUM_ZERO:
|
|
3321
|
+
self.rule_weighted_sum_zero(ass)
|
|
3322
|
+
elif OperatorConcept.is_not_weighted_sum_zero(ci):
|
|
3323
|
+
self.rule_complemented_weighted_sum_zero(ass)
|
|
3324
|
+
elif c_type == ConceptType.WEIGHTED:
|
|
3325
|
+
self.rule_weighted_concept(ass)
|
|
3326
|
+
elif OperatorConcept.is_not_weighted(ci):
|
|
3327
|
+
self.rule_complemented_weighted_concept(ass)
|
|
3328
|
+
elif c_type == ConceptType.POS_THRESHOLD:
|
|
3329
|
+
self.rule_positive_threshold(ass)
|
|
3330
|
+
elif OperatorConcept.is_not_pos_threshold(ci):
|
|
3331
|
+
self.rule_complemented_positive_threshold(ass)
|
|
3332
|
+
elif c_type == ConceptType.NEG_THRESHOLD:
|
|
3333
|
+
self.rule_negative_threshold(ass)
|
|
3334
|
+
elif OperatorConcept.is_not_neg_threshold(ci):
|
|
3335
|
+
self.rule_complemented_negative_threshold(ass)
|
|
3336
|
+
elif c_type == ConceptType.EXT_POS_THRESHOLD:
|
|
3337
|
+
self.rule_extended_positive_threshold(ass)
|
|
3338
|
+
elif OperatorConcept.is_not_ext_pos_threshold(ci):
|
|
3339
|
+
self.rule_complemented_extended_positive_threshold(ass)
|
|
3340
|
+
elif c_type == ConceptType.EXT_NEG_THRESHOLD:
|
|
3341
|
+
self.rule_extended_negative_threshold(ass)
|
|
3342
|
+
elif OperatorConcept.is_not_ext_neg_threshold(ci):
|
|
3343
|
+
self.rule_complemented_extended_negative_threshold(ass)
|
|
3344
|
+
elif c_type == ConceptType.OWA:
|
|
3345
|
+
self.rule_owa(ass)
|
|
3346
|
+
elif OperatorConcept.is_not_owa(ci):
|
|
3347
|
+
self.rule_complemented_owa(ass)
|
|
3348
|
+
elif c_type == ConceptType.QUANTIFIED_OWA:
|
|
3349
|
+
self.rule_quantified_owa(ass)
|
|
3350
|
+
elif OperatorConcept.is_not_qowa(ci):
|
|
3351
|
+
self.rule_complemented_quantified_owa(ass)
|
|
3352
|
+
elif c_type == ConceptType.CHOQUET_INTEGRAL:
|
|
3353
|
+
self.rule_choquet(ass)
|
|
3354
|
+
elif OperatorConcept.is_not_choquet(ci):
|
|
3355
|
+
self.rule_complemented_choquet(ass)
|
|
3356
|
+
elif c_type == ConceptType.SUGENO_INTEGRAL:
|
|
3357
|
+
self.rule_sugeno(ass)
|
|
3358
|
+
elif OperatorConcept.is_not_sugeno(ci):
|
|
3359
|
+
self.rule_complemented_sugeno(ass)
|
|
3360
|
+
elif c_type == ConceptType.QUASI_SUGENO_INTEGRAL:
|
|
3361
|
+
self.rule_quasi_sugeno(ass)
|
|
3362
|
+
elif OperatorConcept.is_not_quasi_sugeno(ci):
|
|
3363
|
+
self.rule_complemented_quasi_sugeno(ass)
|
|
3364
|
+
elif c_type == ConceptType.W_MIN:
|
|
3365
|
+
self.rule_weighted_min(ass)
|
|
3366
|
+
elif OperatorConcept.is_not_weighted_min(ci):
|
|
3367
|
+
self.rule_complemented_weighted_min(ass)
|
|
3368
|
+
elif c_type == ConceptType.W_MAX:
|
|
3369
|
+
self.rule_weighted_max(ass)
|
|
3370
|
+
elif OperatorConcept.is_not_weighted_max(ci):
|
|
3371
|
+
self.rule_complemented_weighted_max(ass)
|
|
3139
3372
|
else:
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
):
|
|
3154
|
-
name: str = str(ass.get_individual())
|
|
3155
|
-
Util.debug(
|
|
3156
|
-
"Skipping assertion (it has an indirectly blocked individual)"
|
|
3157
|
-
)
|
|
3158
|
-
self.blocked_assertions[name] = self.blocked_assertions.get(
|
|
3159
|
-
name, []
|
|
3160
|
-
) + [ass]
|
|
3161
|
-
else:
|
|
3162
|
-
self.milp.add_new_constraint(ass)
|
|
3163
|
-
if self.is_assertion_processed(ass):
|
|
3164
|
-
Util.debug(
|
|
3165
|
-
f"Assertion (without the degree): {ass} already processed."
|
|
3166
|
-
)
|
|
3167
|
-
else:
|
|
3168
|
-
ind: Individual = ass.get_individual()
|
|
3169
|
-
ci: Concept = ass.get_concept()
|
|
3170
|
-
self.add_negated_equations(ind, ci)
|
|
3171
|
-
c_type: ConceptType = ass.get_type()
|
|
3172
|
-
if c_type == ConceptType.ATOMIC:
|
|
3173
|
-
self.rule_atomic(ass)
|
|
3174
|
-
elif ci.is_complemented_atomic():
|
|
3175
|
-
self.rule_complemented_atomic(ass)
|
|
3176
|
-
elif c_type == ConceptType.AND:
|
|
3177
|
-
self.rule_and(ass)
|
|
3178
|
-
elif c_type == ConceptType.OR:
|
|
3179
|
-
self.rule_or(ass)
|
|
3180
|
-
elif c_type in (ConceptType.SOME, ConceptType.HAS_VALUE):
|
|
3181
|
-
self.exist_assertions.append(ass)
|
|
3182
|
-
continue
|
|
3183
|
-
elif c_type == ConceptType.ALL:
|
|
3184
|
-
self.rule_all(ass)
|
|
3185
|
-
elif OperatorConcept.is_not_has_value(ci):
|
|
3186
|
-
self.rule_complemented_has_value(ass)
|
|
3187
|
-
elif c_type == ConceptType.CONCRETE:
|
|
3188
|
-
self.rule_concrete(ass)
|
|
3189
|
-
elif OperatorConcept.is_not_concrete(ci):
|
|
3190
|
-
self.rule_complemented_concrete(ass)
|
|
3191
|
-
elif c_type == ConceptType.FUZZY_NUMBER:
|
|
3192
|
-
self.rule_fuzzy_number(ass)
|
|
3193
|
-
elif OperatorConcept.is_not_fuzzy_number(ci):
|
|
3194
|
-
self.rule_complemented_fuzzy_number(ass)
|
|
3195
|
-
elif c_type == ConceptType.MODIFIED:
|
|
3196
|
-
self.rule_modified(ass)
|
|
3197
|
-
elif OperatorConcept.is_not_modified(ci):
|
|
3198
|
-
self.rule_complemented_modified(ass)
|
|
3199
|
-
elif c_type == ConceptType.TOP:
|
|
3200
|
-
self.rule_top(ass)
|
|
3201
|
-
elif c_type == ConceptType.BOTTOM:
|
|
3202
|
-
self.rule_bottom(ass)
|
|
3203
|
-
elif c_type in (
|
|
3204
|
-
ConceptType.AT_MOST_VALUE,
|
|
3205
|
-
ConceptType.AT_LEAST_VALUE,
|
|
3206
|
-
ConceptType.EXACT_VALUE,
|
|
3207
|
-
):
|
|
3208
|
-
self.positive_concrete_value_assertions.append(ass)
|
|
3209
|
-
elif (
|
|
3210
|
-
OperatorConcept.is_not_at_least_value(ci)
|
|
3211
|
-
or OperatorConcept.is_not_at_most_value(ci)
|
|
3212
|
-
or OperatorConcept.is_not_exact_value(ci)
|
|
3213
|
-
):
|
|
3214
|
-
self.add_negated_datatype_restriction(ass)
|
|
3215
|
-
elif c_type == ConceptType.SELF:
|
|
3216
|
-
self.rule_self(ass)
|
|
3217
|
-
elif OperatorConcept.is_not_self(ci):
|
|
3218
|
-
self.rule_complemented_self(ass)
|
|
3219
|
-
elif c_type == ConceptType.UPPER_APPROX:
|
|
3220
|
-
self.rule_upper_approximation(ass)
|
|
3221
|
-
elif c_type == ConceptType.TIGHT_UPPER_APPROX:
|
|
3222
|
-
self.rule_tight_upper_approximation(ass)
|
|
3223
|
-
elif c_type == ConceptType.LOOSE_UPPER_APPROX:
|
|
3224
|
-
self.rule_loose_upper_approximation(ass)
|
|
3225
|
-
elif c_type == ConceptType.LOWER_APPROX:
|
|
3226
|
-
self.rule_lower_approximation(ass)
|
|
3227
|
-
elif c_type == ConceptType.TIGHT_LOWER_APPROX:
|
|
3228
|
-
self.rule_tight_lower_approximation(ass)
|
|
3229
|
-
elif c_type == ConceptType.LOOSE_LOWER_APPROX:
|
|
3230
|
-
self.rule_loose_lower_approximation(ass)
|
|
3231
|
-
elif c_type == ConceptType.GOEDEL_AND:
|
|
3232
|
-
self.rule_goedel_and(ass)
|
|
3233
|
-
elif c_type == ConceptType.LUKASIEWICZ_AND:
|
|
3234
|
-
self.rule_lukasiewicz_and(ass)
|
|
3235
|
-
elif c_type == ConceptType.GOEDEL_OR:
|
|
3236
|
-
self.rule_goedel_or(ass)
|
|
3237
|
-
elif c_type == ConceptType.LUKASIEWICZ_OR:
|
|
3238
|
-
self.rule_lukasiewicz_or(ass)
|
|
3239
|
-
elif c_type == ConceptType.GOEDEL_IMPLIES:
|
|
3240
|
-
self.rule_goedel_implication(ass)
|
|
3241
|
-
elif OperatorConcept.is_not_goedel_implies(ci):
|
|
3242
|
-
self.rule_complemented_goedel_implication(ass)
|
|
3243
|
-
elif c_type == ConceptType.ZADEH_IMPLIES:
|
|
3244
|
-
self.rule_zadeh_implication(ass)
|
|
3245
|
-
elif OperatorConcept.is_not_zadeh_implies(ci):
|
|
3246
|
-
self.rule_complemented_zadeh_implication(ass)
|
|
3247
|
-
elif c_type == ConceptType.W_SUM:
|
|
3248
|
-
self.rule_weighted_sum(ass)
|
|
3249
|
-
elif OperatorConcept.is_not_weighted_sum(ci):
|
|
3250
|
-
self.rule_complemented_weighted_sum(ass)
|
|
3251
|
-
elif c_type == ConceptType.W_SUM_ZERO:
|
|
3252
|
-
self.rule_weighted_sum_zero(ass)
|
|
3253
|
-
elif OperatorConcept.is_not_weighted_sum_zero(ci):
|
|
3254
|
-
self.rule_complemented_weighted_sum_zero(ass)
|
|
3255
|
-
elif c_type == ConceptType.WEIGHTED:
|
|
3256
|
-
self.rule_weighted_concept(ass)
|
|
3257
|
-
elif OperatorConcept.is_not_weighted(ci):
|
|
3258
|
-
self.rule_complemented_weighted_concept(ass)
|
|
3259
|
-
elif c_type == ConceptType.POS_THRESHOLD:
|
|
3260
|
-
self.rule_positive_threshold(ass)
|
|
3261
|
-
elif OperatorConcept.is_not_pos_threshold(ci):
|
|
3262
|
-
self.rule_complemented_positive_threshold(ass)
|
|
3263
|
-
elif c_type == ConceptType.NEG_THRESHOLD:
|
|
3264
|
-
self.rule_negative_threshold(ass)
|
|
3265
|
-
elif OperatorConcept.is_not_neg_threshold(ci):
|
|
3266
|
-
self.rule_complemented_negative_threshold(ass)
|
|
3267
|
-
elif c_type == ConceptType.EXT_POS_THRESHOLD:
|
|
3268
|
-
self.rule_extended_positive_threshold(ass)
|
|
3269
|
-
elif OperatorConcept.is_not_ext_pos_threshold(ci):
|
|
3270
|
-
self.rule_complemented_extended_positive_threshold(ass)
|
|
3271
|
-
elif c_type == ConceptType.EXT_NEG_THRESHOLD:
|
|
3272
|
-
self.rule_extended_negative_threshold(ass)
|
|
3273
|
-
elif OperatorConcept.is_not_ext_neg_threshold(ci):
|
|
3274
|
-
self.rule_complemented_extended_negative_threshold(ass)
|
|
3275
|
-
elif c_type == ConceptType.OWA:
|
|
3276
|
-
self.rule_owa(ass)
|
|
3277
|
-
elif OperatorConcept.is_not_owa(ci):
|
|
3278
|
-
self.rule_complemented_owa(ass)
|
|
3279
|
-
elif c_type == ConceptType.QUANTIFIED_OWA:
|
|
3280
|
-
self.rule_quantified_owa(ass)
|
|
3281
|
-
elif OperatorConcept.is_not_qowa(ci):
|
|
3282
|
-
self.rule_complemented_quantified_owa(ass)
|
|
3283
|
-
elif c_type == ConceptType.CHOQUET_INTEGRAL:
|
|
3284
|
-
self.rule_choquet(ass)
|
|
3285
|
-
elif OperatorConcept.is_not_choquet(ci):
|
|
3286
|
-
self.rule_complemented_choquet(ass)
|
|
3287
|
-
elif c_type == ConceptType.SUGENO_INTEGRAL:
|
|
3288
|
-
self.rule_sugeno(ass)
|
|
3289
|
-
elif OperatorConcept.is_not_sugeno(ci):
|
|
3290
|
-
self.rule_complemented_sugeno(ass)
|
|
3291
|
-
elif c_type == ConceptType.QUASI_SUGENO_INTEGRAL:
|
|
3292
|
-
self.rule_quasi_sugeno(ass)
|
|
3293
|
-
elif OperatorConcept.is_not_quasi_sugeno(ci):
|
|
3294
|
-
self.rule_complemented_quasi_sugeno(ass)
|
|
3295
|
-
elif c_type == ConceptType.W_MIN:
|
|
3296
|
-
self.rule_weighted_min(ass)
|
|
3297
|
-
elif OperatorConcept.is_not_weighted_min(ci):
|
|
3298
|
-
self.rule_complemented_weighted_min(ass)
|
|
3299
|
-
elif c_type == ConceptType.W_MAX:
|
|
3300
|
-
self.rule_weighted_max(ass)
|
|
3301
|
-
elif OperatorConcept.is_not_weighted_max(ci):
|
|
3302
|
-
self.rule_complemented_weighted_max(ass)
|
|
3303
|
-
else:
|
|
3304
|
-
Util.warning(f"Warning: Assertion with type {c_type}")
|
|
3305
|
-
|
|
3306
|
-
nodes: set[str] = self.labels_with_nodes.get(str(ind))
|
|
3307
|
-
if nodes is not None:
|
|
3308
|
-
for node in nodes:
|
|
3309
|
-
self.rule_ass_nom(ind, ci, node)
|
|
3310
|
-
|
|
3311
|
-
self.mark_process_assertion(ass)
|
|
3312
|
-
ind.add_concept(ci)
|
|
3313
|
-
Util.debug(
|
|
3314
|
-
f"{constants.SEPARATOR}Assertion completed{constants.SEPARATOR}"
|
|
3315
|
-
)
|
|
3373
|
+
Util.warning(f"Warning: Assertion with type {c_type}")
|
|
3374
|
+
|
|
3375
|
+
# For each node in labelsWithNodes, apply AssNom rule
|
|
3376
|
+
nodes: set[str] = self.labels_with_nodes.get(str(ind))
|
|
3377
|
+
if nodes is not None:
|
|
3378
|
+
for node in nodes:
|
|
3379
|
+
self.rule_ass_nom(ind, ci, node)
|
|
3380
|
+
|
|
3381
|
+
self.mark_process_assertion(ass)
|
|
3382
|
+
ind.add_concept(ci)
|
|
3383
|
+
Util.debug(
|
|
3384
|
+
f"{constants.SEPARATOR}Assertion completed{constants.SEPARATOR}"
|
|
3385
|
+
)
|
|
3316
3386
|
self.assertions.clear()
|
|
3387
|
+
|
|
3388
|
+
# Solve one some rule
|
|
3317
3389
|
if len(self.assertions) == 0:
|
|
3318
3390
|
self.solve_one_exist_assertion()
|
|
3391
|
+
|
|
3392
|
+
# Check if there are more assertions
|
|
3319
3393
|
if len(self.assertions) == 0 and len(self.exist_assertions) == 0:
|
|
3320
3394
|
break
|
|
3395
|
+
# Concrete assertions
|
|
3321
3396
|
self.solve_concrete_value_assertions()
|
|
3322
3397
|
|
|
3323
3398
|
def solve_concept_assertion(self, ind: Individual, concept: Concept) -> None:
|
|
@@ -3355,25 +3430,31 @@ class KnowledgeBase:
|
|
|
3355
3430
|
def solve_concept_complemented_assertion(
|
|
3356
3431
|
self, ind: Individual, lower_limit: Degree, concept: Concept
|
|
3357
3432
|
) -> None:
|
|
3358
|
-
if
|
|
3433
|
+
if OperatorConcept.is_not_choquet(concept):
|
|
3359
3434
|
self.solve_choquet_integral_complemented_assertion(ind, concept)
|
|
3360
|
-
elif
|
|
3435
|
+
elif OperatorConcept.is_not_sugeno(
|
|
3436
|
+
concept
|
|
3437
|
+
) or OperatorConcept.is_not_quasi_sugeno(concept):
|
|
3361
3438
|
self.solve_sugeno_integral_complemented_assertion(ind, concept)
|
|
3362
|
-
elif
|
|
3439
|
+
elif OperatorConcept.is_not_owa(concept) or OperatorConcept.is_not_qowa(
|
|
3440
|
+
concept
|
|
3441
|
+
):
|
|
3363
3442
|
self.solve_owa_complemented_assertion(ind, concept)
|
|
3364
|
-
elif
|
|
3443
|
+
elif OperatorConcept.is_not_weighted_max(concept):
|
|
3365
3444
|
self.solve_w_max_complemented_assertion(ind, concept)
|
|
3366
|
-
elif
|
|
3445
|
+
elif OperatorConcept.is_not_weighted_min(concept):
|
|
3367
3446
|
self.solve_w_min_complemented_assertion(ind, concept)
|
|
3368
|
-
elif
|
|
3447
|
+
elif OperatorConcept.is_not_weighted_sum(concept):
|
|
3369
3448
|
self.solve_w_sum_complemented_assertion(ind, concept)
|
|
3370
|
-
elif
|
|
3449
|
+
elif OperatorConcept.is_not_weighted_sum_zero(concept):
|
|
3371
3450
|
self.solve_w_sum_zero_complemented_assertion(ind, concept)
|
|
3372
|
-
elif isinstance(concept, (
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
)
|
|
3376
|
-
elif isinstance(concept,
|
|
3451
|
+
elif isinstance(concept, OperatorConcept) and isinstance(
|
|
3452
|
+
concept.get_atom(), (ModifiedConcept, ModifiedConcreteConcept)
|
|
3453
|
+
):
|
|
3454
|
+
self.solve_modifier_complemented_assertion(ind, concept, lower_limit)
|
|
3455
|
+
elif isinstance(concept, OperatorConcept) and isinstance(
|
|
3456
|
+
concept.get_atom(), FuzzyConcreteConcept
|
|
3457
|
+
):
|
|
3377
3458
|
self.solve_fuzzy_concrete_concept_complement_assertion(
|
|
3378
3459
|
ind, lower_limit, concept
|
|
3379
3460
|
)
|
|
@@ -3417,12 +3498,15 @@ class KnowledgeBase:
|
|
|
3417
3498
|
self.milp.add_new_constraint(exp, InequalityType.EQUAL, degree)
|
|
3418
3499
|
|
|
3419
3500
|
def solve_choquet_integral_complemented_assertion(
|
|
3420
|
-
self, ind: Individual, c:
|
|
3501
|
+
self, ind: Individual, c: OperatorConcept
|
|
3421
3502
|
) -> None:
|
|
3422
|
-
|
|
3503
|
+
assert isinstance(c.get_atom(), ChoquetIntegral)
|
|
3504
|
+
ci: ChoquetIntegral = c.get_atom()
|
|
3505
|
+
|
|
3506
|
+
n: int = len(ci.concepts)
|
|
3423
3507
|
x: list[Variable] = [None] * n
|
|
3424
3508
|
for i in range(n):
|
|
3425
|
-
not_ci = -
|
|
3509
|
+
not_ci = -ci.concepts[i]
|
|
3426
3510
|
x[i] = self.milp.get_variable(ind, not_ci)
|
|
3427
3511
|
self.add_assertion(ind, not_ci, DegreeVariable.get_degree(x[i]))
|
|
3428
3512
|
|
|
@@ -3433,9 +3517,9 @@ class KnowledgeBase:
|
|
|
3433
3517
|
y: list[Variable] = self.milp.get_ordered_permutation(x, z)
|
|
3434
3518
|
|
|
3435
3519
|
exp = Expression(1.0)
|
|
3436
|
-
exp.add_term(Term(-
|
|
3520
|
+
exp.add_term(Term(-ci.weights[0], y[0]))
|
|
3437
3521
|
for k in range(1, n):
|
|
3438
|
-
exp.add_term(Term(
|
|
3522
|
+
exp.add_term(Term(ci.weights[k - 1] - ci.weights[k], y[k]))
|
|
3439
3523
|
|
|
3440
3524
|
degree: DegreeVariable = DegreeVariable.get_degree(
|
|
3441
3525
|
self.milp.get_variable(ind, c)
|
|
@@ -3489,8 +3573,11 @@ class KnowledgeBase:
|
|
|
3489
3573
|
self.milp.add_new_constraint(exp, InequalityType.EQUAL, degree)
|
|
3490
3574
|
|
|
3491
3575
|
def solve_owa_complemented_assertion(
|
|
3492
|
-
self, ind: Individual,
|
|
3576
|
+
self, ind: Individual, curr_concept: OperatorConcept
|
|
3493
3577
|
) -> None:
|
|
3578
|
+
assert isinstance(curr_concept.get_atom(), (OwaConcept, QowaConcept))
|
|
3579
|
+
|
|
3580
|
+
c: typing.Union[OwaConcept, QowaConcept] = curr_concept.get_atom()
|
|
3494
3581
|
x_A_in_not_WS: Variable = self.milp.get_variable(ind, c)
|
|
3495
3582
|
n: int = len(c.concepts)
|
|
3496
3583
|
x: list[Variable] = []
|
|
@@ -3509,7 +3596,7 @@ class KnowledgeBase:
|
|
|
3509
3596
|
for j in range(n):
|
|
3510
3597
|
exp.add_term(Term(-c.weights[j], y[j]))
|
|
3511
3598
|
self.milp.add_new_constraint(exp, InequalityType.EQUAL)
|
|
3512
|
-
self.rule_complemented(ind,
|
|
3599
|
+
self.rule_complemented(ind, curr_concept)
|
|
3513
3600
|
|
|
3514
3601
|
def solve_sugeno_integral_assertion(
|
|
3515
3602
|
self, ind: Individual, concept: typing.Union[SugenoIntegral, QsugenoIntegral]
|
|
@@ -3561,12 +3648,12 @@ class KnowledgeBase:
|
|
|
3561
3648
|
self.milp.get_new_variable(VariableType.SEMI_CONTINUOUS) for _ in range(n)
|
|
3562
3649
|
]
|
|
3563
3650
|
|
|
3564
|
-
if isinstance(concept,
|
|
3565
|
-
for i in range(n):
|
|
3566
|
-
ZadehSolver.and_equation(c[i], y[i], a[i], self.milp)
|
|
3567
|
-
elif isinstance(concept, QsugenoIntegral):
|
|
3651
|
+
if isinstance(concept, QsugenoIntegral):
|
|
3568
3652
|
for i in range(n):
|
|
3569
3653
|
LukasiewiczSolver.and_equation(c[i], y[i], a[i], self.milp)
|
|
3654
|
+
elif isinstance(concept, SugenoIntegral):
|
|
3655
|
+
for i in range(n):
|
|
3656
|
+
ZadehSolver.and_equation(c[i], y[i], a[i], self.milp)
|
|
3570
3657
|
|
|
3571
3658
|
degree: DegreeVariable = DegreeVariable.get_degree(
|
|
3572
3659
|
self.milp.get_variable(ind, concept)
|
|
@@ -3587,8 +3674,11 @@ class KnowledgeBase:
|
|
|
3587
3674
|
self.milp.add_new_constraint(exp, InequalityType.EQUAL, n - 1)
|
|
3588
3675
|
|
|
3589
3676
|
def solve_sugeno_integral_complemented_assertion(
|
|
3590
|
-
self, ind: Individual,
|
|
3677
|
+
self, ind: Individual, curr_concept: OperatorConcept
|
|
3591
3678
|
) -> None:
|
|
3679
|
+
assert isinstance(curr_concept.get_atom(), (SugenoIntegral, QsugenoIntegral))
|
|
3680
|
+
concept: typing.Union[SugenoIntegral, QsugenoIntegral] = curr_concept.get_atom()
|
|
3681
|
+
|
|
3592
3682
|
n: int = len(concept.concepts)
|
|
3593
3683
|
x: list[Variable] = []
|
|
3594
3684
|
for i in range(n):
|
|
@@ -3638,15 +3728,15 @@ class KnowledgeBase:
|
|
|
3638
3728
|
self.milp.get_new_variable(VariableType.SEMI_CONTINUOUS) for _ in range(n)
|
|
3639
3729
|
]
|
|
3640
3730
|
|
|
3641
|
-
if isinstance(concept,
|
|
3642
|
-
for i in range(n):
|
|
3643
|
-
ZadehSolver.and_equation(c[i], y[i], a[i], self.milp)
|
|
3644
|
-
elif isinstance(concept, QsugenoIntegral):
|
|
3731
|
+
if isinstance(concept, QsugenoIntegral):
|
|
3645
3732
|
for i in range(n):
|
|
3646
3733
|
LukasiewiczSolver.and_equation(c[i], y[i], a[i], self.milp)
|
|
3734
|
+
elif isinstance(concept, SugenoIntegral):
|
|
3735
|
+
for i in range(n):
|
|
3736
|
+
ZadehSolver.and_equation(c[i], y[i], a[i], self.milp)
|
|
3647
3737
|
|
|
3648
3738
|
degree: DegreeVariable = DegreeVariable.get_degree(
|
|
3649
|
-
self.milp.get_variable(ind,
|
|
3739
|
+
self.milp.get_variable(ind, curr_concept)
|
|
3650
3740
|
)
|
|
3651
3741
|
b: list[Variable] = [
|
|
3652
3742
|
self.milp.get_new_variable(VariableType.BINARY) for _ in range(n)
|
|
@@ -3662,7 +3752,7 @@ class KnowledgeBase:
|
|
|
3662
3752
|
for i in range(n):
|
|
3663
3753
|
exp.add_term(Term(1.0, b[i]))
|
|
3664
3754
|
self.milp.add_new_constraint(exp, InequalityType.EQUAL, n - 1)
|
|
3665
|
-
self.rule_complemented(ind,
|
|
3755
|
+
self.rule_complemented(ind, curr_concept)
|
|
3666
3756
|
|
|
3667
3757
|
def solve_w_max_assertion(
|
|
3668
3758
|
self, ind: Individual, concept: WeightedMaxConcept
|
|
@@ -3678,9 +3768,12 @@ class KnowledgeBase:
|
|
|
3678
3768
|
ZadehSolver.or_equation(min_vars, x_A_in_WS, self.milp)
|
|
3679
3769
|
|
|
3680
3770
|
def solve_w_max_complemented_assertion(
|
|
3681
|
-
self, ind: Individual,
|
|
3771
|
+
self, ind: Individual, curr_concept: OperatorConcept
|
|
3682
3772
|
) -> None:
|
|
3683
|
-
|
|
3773
|
+
assert isinstance(curr_concept.get_atom(), WeightedMaxConcept)
|
|
3774
|
+
concept: WeightedMaxConcept = curr_concept.get_atom()
|
|
3775
|
+
|
|
3776
|
+
x_A_in_WS: Variable = self.milp.get_variable(ind, curr_concept)
|
|
3684
3777
|
negmin: list[Variable] = []
|
|
3685
3778
|
for ci, weight in zip(concept.concepts, concept.weights):
|
|
3686
3779
|
not_ci: Concept = -ci
|
|
@@ -3691,7 +3784,7 @@ class KnowledgeBase:
|
|
|
3691
3784
|
ZadehSolver.or_negated_equation(max_var, xi, 1.0 - weight, self.milp)
|
|
3692
3785
|
negmin.append(max_var)
|
|
3693
3786
|
ZadehSolver.and_equation(negmin, x_A_in_WS, self.milp)
|
|
3694
|
-
self.rule_complemented(ind,
|
|
3787
|
+
self.rule_complemented(ind, curr_concept)
|
|
3695
3788
|
|
|
3696
3789
|
def solve_w_min_assertion(
|
|
3697
3790
|
self, ind: Individual, concept: WeightedMinConcept
|
|
@@ -3707,9 +3800,12 @@ class KnowledgeBase:
|
|
|
3707
3800
|
ZadehSolver.and_equation(max_vars, x_A_in_WS, self.milp)
|
|
3708
3801
|
|
|
3709
3802
|
def solve_w_min_complemented_assertion(
|
|
3710
|
-
self, ind: Individual,
|
|
3803
|
+
self, ind: Individual, curr_concept: OperatorConcept
|
|
3711
3804
|
) -> None:
|
|
3712
|
-
|
|
3805
|
+
assert isinstance(curr_concept.get_atom(), WeightedMinConcept)
|
|
3806
|
+
concept: WeightedMinConcept = curr_concept.get_atom()
|
|
3807
|
+
|
|
3808
|
+
x_A_in_WS: Variable = self.milp.get_variable(ind, curr_concept)
|
|
3713
3809
|
negmax: list[Variable] = []
|
|
3714
3810
|
for ci, weight in zip(concept.concepts, concept.weights):
|
|
3715
3811
|
not_ci: Concept = -ci
|
|
@@ -3720,7 +3816,7 @@ class KnowledgeBase:
|
|
|
3720
3816
|
ZadehSolver.and_negated_equation(max_var, xi, weight, self.milp)
|
|
3721
3817
|
negmax.append(max_var)
|
|
3722
3818
|
ZadehSolver.or_equation(negmax, x_A_in_WS, self.milp)
|
|
3723
|
-
self.rule_complemented(ind,
|
|
3819
|
+
self.rule_complemented(ind, curr_concept)
|
|
3724
3820
|
|
|
3725
3821
|
def solve_w_sum_assertion(
|
|
3726
3822
|
self, ind: Individual, concept: WeightedSumConcept
|
|
@@ -3738,9 +3834,12 @@ class KnowledgeBase:
|
|
|
3738
3834
|
)
|
|
3739
3835
|
|
|
3740
3836
|
def solve_w_sum_complemented_assertion(
|
|
3741
|
-
self, ind: Individual,
|
|
3837
|
+
self, ind: Individual, curr_concept: OperatorConcept
|
|
3742
3838
|
) -> None:
|
|
3743
|
-
|
|
3839
|
+
assert isinstance(curr_concept.get_atom(), WeightedSumConcept)
|
|
3840
|
+
concept: WeightedSumConcept = curr_concept.get_atom()
|
|
3841
|
+
|
|
3842
|
+
x_A_in_not_WS: Variable = self.milp.get_variable(ind, curr_concept)
|
|
3744
3843
|
terms: list[Term] = []
|
|
3745
3844
|
for ci, weight in zip(concept.concepts, concept.weights):
|
|
3746
3845
|
not_ci: Concept = -ci
|
|
@@ -3753,7 +3852,7 @@ class KnowledgeBase:
|
|
|
3753
3852
|
InequalityType.EQUAL,
|
|
3754
3853
|
DegreeVariable.get_degree(x_A_in_not_WS),
|
|
3755
3854
|
)
|
|
3756
|
-
self.rule_complemented(ind,
|
|
3855
|
+
self.rule_complemented(ind, curr_concept)
|
|
3757
3856
|
|
|
3758
3857
|
def solve_w_sum_zero_assertion(
|
|
3759
3858
|
self, ind: Individual, concept: WeightedSumZeroConcept
|
|
@@ -3787,11 +3886,14 @@ class KnowledgeBase:
|
|
|
3787
3886
|
self.rule_complemented(ind, concept)
|
|
3788
3887
|
|
|
3789
3888
|
def solve_w_sum_zero_complemented_assertion(
|
|
3790
|
-
self, ind: Individual,
|
|
3889
|
+
self, ind: Individual, curr_concept: OperatorConcept
|
|
3791
3890
|
) -> None:
|
|
3891
|
+
assert isinstance(curr_concept.get_atom(), WeightedSumZeroConcept)
|
|
3892
|
+
concept: WeightedSumZeroConcept = curr_concept.get_atom()
|
|
3893
|
+
|
|
3792
3894
|
terms: list[Term] = []
|
|
3793
3895
|
vx: list[Variable] = []
|
|
3794
|
-
x_A_in_not_ws: Variable = self.milp.get_variable(ind,
|
|
3896
|
+
x_A_in_not_ws: Variable = self.milp.get_variable(ind, curr_concept)
|
|
3795
3897
|
y: Variable = self.milp.get_new_variable(VariableType.BINARY)
|
|
3796
3898
|
z: Variable = self.milp.get_new_variable(VariableType.SEMI_CONTINUOUS)
|
|
3797
3899
|
for ci, weight in zip(concept.concepts, concept.weights):
|
|
@@ -3814,7 +3916,7 @@ class KnowledgeBase:
|
|
|
3814
3916
|
exp2: Expression = Expression(*terms)
|
|
3815
3917
|
exp2.add_term(Term(1.0, y))
|
|
3816
3918
|
self.milp.add_new_constraint(exp2, InequalityType.GREATER_THAN)
|
|
3817
|
-
self.rule_complemented(ind,
|
|
3919
|
+
self.rule_complemented(ind, curr_concept)
|
|
3818
3920
|
|
|
3819
3921
|
def solve_crisp_concrete_concept_assertion(
|
|
3820
3922
|
self, ind: Individual, concept: CrispConcreteConcept
|
|
@@ -3888,10 +3990,11 @@ class KnowledgeBase:
|
|
|
3888
3990
|
self,
|
|
3889
3991
|
ind: CreatedIndividual,
|
|
3890
3992
|
lower_limit: Degree,
|
|
3891
|
-
|
|
3993
|
+
curr_concept: OperatorConcept,
|
|
3892
3994
|
) -> None:
|
|
3893
3995
|
"""Solve a complement assertion"""
|
|
3894
|
-
|
|
3996
|
+
assert isinstance(curr_concept.get_atom(), FuzzyConcreteConcept)
|
|
3997
|
+
assertion: Assertion = Assertion(ind, curr_concept, lower_limit)
|
|
3895
3998
|
self.rule_complemented_complex_assertion(assertion)
|
|
3896
3999
|
|
|
3897
4000
|
def solve_left_concrete_concept_assertion(
|
|
@@ -4264,9 +4367,12 @@ class KnowledgeBase:
|
|
|
4264
4367
|
)
|
|
4265
4368
|
|
|
4266
4369
|
def solve_modifier_complemented_assertion(
|
|
4267
|
-
self, ind: Individual,
|
|
4370
|
+
self, ind: Individual, concept: OperatorConcept, degree: Degree
|
|
4268
4371
|
) -> None:
|
|
4269
|
-
|
|
4372
|
+
assert isinstance(concept, OperatorConcept) and isinstance(
|
|
4373
|
+
concept.get_atom(), (ModifiedConcept, ModifiedConcreteConcept)
|
|
4374
|
+
)
|
|
4375
|
+
ass: Assertion = Assertion(ind, concept, degree)
|
|
4270
4376
|
self.rule_complemented_complex_assertion(ass)
|
|
4271
4377
|
|
|
4272
4378
|
def solve_linear_modifier_assertion(
|
|
@@ -4434,7 +4540,9 @@ class KnowledgeBase:
|
|
|
4434
4540
|
|
|
4435
4541
|
def add_negated_datatype_restriction(self, ass: Assertion) -> None:
|
|
4436
4542
|
a: Individual = ass.get_individual()
|
|
4437
|
-
|
|
4543
|
+
op: Concept = ass.get_concept()
|
|
4544
|
+
assert isinstance(op, OperatorConcept) and op.type == ConceptType.COMPLEMENT
|
|
4545
|
+
c: Concept = op.get_atom()
|
|
4438
4546
|
assert isinstance(c, HasRoleInterface)
|
|
4439
4547
|
f_name: str = c.role
|
|
4440
4548
|
a.add_concrete_restriction(f_name, ass)
|
|
@@ -5372,7 +5480,7 @@ class KnowledgeBase:
|
|
|
5372
5480
|
self.compute_variables_old_calculus(fcc)
|
|
5373
5481
|
ind: CreatedIndividual = typing.cast(CreatedIndividual, ass.get_individual())
|
|
5374
5482
|
|
|
5375
|
-
self.solve_concept_complemented_assertion(ind, ass.get_lower_limit(),
|
|
5483
|
+
self.solve_concept_complemented_assertion(ind, ass.get_lower_limit(), c)
|
|
5376
5484
|
# fcc.solve_complement_assertion(ind, ass.get_lower_limit(), self)
|
|
5377
5485
|
|
|
5378
5486
|
def rule_fuzzy_number(self, ass: Assertion) -> None:
|
|
@@ -5413,7 +5521,7 @@ class KnowledgeBase:
|
|
|
5413
5521
|
# ass.get_individual(), ass.get_lower_limit(), self
|
|
5414
5522
|
# )
|
|
5415
5523
|
self.solve_modifier_complemented_assertion(
|
|
5416
|
-
ass.get_individual(),
|
|
5524
|
+
ass.get_individual(), c, ass.get_lower_limit()
|
|
5417
5525
|
)
|
|
5418
5526
|
|
|
5419
5527
|
def rule_bottom(self, ass: Assertion) -> None:
|
|
@@ -5786,7 +5894,7 @@ class KnowledgeBase:
|
|
|
5786
5894
|
self.milp.add_new_constraint(
|
|
5787
5895
|
Expression(Term(1.0, x_a_in_wc), Term(-w, x_a_in_c)), InequalityType.EQUAL
|
|
5788
5896
|
)
|
|
5789
|
-
self.rule_complemented(i,
|
|
5897
|
+
self.rule_complemented(i, c)
|
|
5790
5898
|
|
|
5791
5899
|
def rule_complemented_complex_assertion(self, ass: Assertion) -> None:
|
|
5792
5900
|
i: Individual = ass.get_individual()
|
|
@@ -5818,12 +5926,13 @@ class KnowledgeBase:
|
|
|
5818
5926
|
c: Concept = ass.get_concept()
|
|
5819
5927
|
assert isinstance(c, OperatorConcept)
|
|
5820
5928
|
ws: WeightedSumConcept = typing.cast(WeightedSumConcept, c.get_atom())
|
|
5929
|
+
|
|
5821
5930
|
n: int = len(ws.concepts)
|
|
5822
5931
|
self.old_01_variables += n
|
|
5823
5932
|
self.rules_applied[KnowledgeBaseRules.RULE_NOT_W_SUM] += 1
|
|
5824
5933
|
|
|
5825
5934
|
# ws.solve_complemented_assertion(ass.get_individual(), self)
|
|
5826
|
-
self.solve_concept_complemented_assertion(ass.get_individual(), None,
|
|
5935
|
+
self.solve_concept_complemented_assertion(ass.get_individual(), None, c)
|
|
5827
5936
|
|
|
5828
5937
|
def rule_weighted_sum_zero(self, ass: Assertion) -> None:
|
|
5829
5938
|
n: int = len(typing.cast(WeightedSumZeroConcept, ass.get_concept()).concepts)
|
|
@@ -5839,11 +5948,11 @@ class KnowledgeBase:
|
|
|
5839
5948
|
def rule_complemented_weighted_sum_zero(self, ass: Assertion) -> None:
|
|
5840
5949
|
c: Concept = ass.get_concept()
|
|
5841
5950
|
assert isinstance(c, OperatorConcept)
|
|
5842
|
-
|
|
5951
|
+
assert isinstance(c.get_atom(), WeightedSumZeroConcept)
|
|
5843
5952
|
|
|
5844
5953
|
self.rules_applied[KnowledgeBaseRules.RULE_NOT_W_SUM_ZERO] += 1
|
|
5845
5954
|
# wsz.solve_complemented_assertion(ass.get_individual(), self)
|
|
5846
|
-
self.solve_concept_complemented_assertion(ass.get_individual(), None,
|
|
5955
|
+
self.solve_concept_complemented_assertion(ass.get_individual(), None, c)
|
|
5847
5956
|
|
|
5848
5957
|
def rule_weighted_min(self, ass: Assertion) -> None:
|
|
5849
5958
|
self.rules_applied[KnowledgeBaseRules.RULE_W_MIN] += 1
|
|
@@ -5857,11 +5966,11 @@ class KnowledgeBase:
|
|
|
5857
5966
|
def rule_complemented_weighted_min(self, ass: Assertion) -> None:
|
|
5858
5967
|
c: Concept = ass.get_concept()
|
|
5859
5968
|
assert isinstance(c, OperatorConcept)
|
|
5860
|
-
|
|
5969
|
+
assert isinstance(c.get_atom(), WeightedMinConcept)
|
|
5861
5970
|
|
|
5862
5971
|
self.rules_applied[KnowledgeBaseRules.RULE_NOT_W_MIN] += 1
|
|
5863
5972
|
# wm.solve_complemented_assertion(ass.get_individual(), self)
|
|
5864
|
-
self.solve_concept_complemented_assertion(ass.get_individual(), None,
|
|
5973
|
+
self.solve_concept_complemented_assertion(ass.get_individual(), None, c)
|
|
5865
5974
|
|
|
5866
5975
|
def rule_weighted_max(self, ass: Assertion) -> None:
|
|
5867
5976
|
self.rules_applied[KnowledgeBaseRules.RULE_W_MAX] += 1
|
|
@@ -5875,11 +5984,11 @@ class KnowledgeBase:
|
|
|
5875
5984
|
def rule_complemented_weighted_max(self, ass: Assertion) -> None:
|
|
5876
5985
|
c: Concept = ass.get_concept()
|
|
5877
5986
|
assert isinstance(c, OperatorConcept)
|
|
5878
|
-
|
|
5987
|
+
assert isinstance(c.get_atom(), WeightedMaxConcept)
|
|
5879
5988
|
|
|
5880
5989
|
self.rules_applied[KnowledgeBaseRules.RULE_NOT_W_MAX] += 1
|
|
5881
5990
|
# wm.solve_complemented_assertion(ass.get_individual(), self)
|
|
5882
|
-
self.solve_concept_complemented_assertion(ass.get_individual(), None,
|
|
5991
|
+
self.solve_concept_complemented_assertion(ass.get_individual(), None, c)
|
|
5883
5992
|
|
|
5884
5993
|
def rule_owa(self, ass: Assertion) -> None:
|
|
5885
5994
|
n: int = len(typing.cast(OwaConcept, ass.get_concept()).concepts)
|
|
@@ -5904,7 +6013,7 @@ class KnowledgeBase:
|
|
|
5904
6013
|
self.rules_applied[KnowledgeBaseRules.RULE_NOT_OWA] += 1
|
|
5905
6014
|
# oc.solve_complemented_assertion(ass.get_individual(), self)
|
|
5906
6015
|
|
|
5907
|
-
self.solve_concept_complemented_assertion(ass.get_individual(), None,
|
|
6016
|
+
self.solve_concept_complemented_assertion(ass.get_individual(), None, c)
|
|
5908
6017
|
|
|
5909
6018
|
def rule_quantified_owa(self, ass: Assertion) -> None:
|
|
5910
6019
|
self.rules_applied[KnowledgeBaseRules.RULE_OWA] += 1
|
|
@@ -5932,12 +6041,12 @@ class KnowledgeBase:
|
|
|
5932
6041
|
def rule_complemented_choquet(self, ass: Assertion) -> None:
|
|
5933
6042
|
c: Concept = ass.get_concept()
|
|
5934
6043
|
assert isinstance(c, OperatorConcept)
|
|
5935
|
-
|
|
6044
|
+
assert isinstance(c.get_atom(), ChoquetIntegral)
|
|
5936
6045
|
|
|
5937
6046
|
self.rules_applied[KnowledgeBaseRules.RULE_NOT_CHOQUET_INTEGRAL] += 1
|
|
5938
6047
|
# ci.solve_complemented_assertion(ass.get_individual(), self)
|
|
5939
6048
|
|
|
5940
|
-
self.solve_concept_complemented_assertion(ass.get_individual(), None,
|
|
6049
|
+
self.solve_concept_complemented_assertion(ass.get_individual(), None, c)
|
|
5941
6050
|
|
|
5942
6051
|
def rule_sugeno(self, ass: Assertion) -> None:
|
|
5943
6052
|
self.rules_applied[KnowledgeBaseRules.RULE_SUGENO_INTEGRAL] += 1
|
|
@@ -5951,11 +6060,11 @@ class KnowledgeBase:
|
|
|
5951
6060
|
def rule_complemented_sugeno(self, ass: Assertion) -> None:
|
|
5952
6061
|
c: Concept = ass.get_concept()
|
|
5953
6062
|
assert isinstance(c, OperatorConcept)
|
|
5954
|
-
|
|
6063
|
+
assert isinstance(c.get_atom(), SugenoIntegral)
|
|
5955
6064
|
|
|
5956
6065
|
self.rules_applied[KnowledgeBaseRules.RULE_NOT_SUGENO_INTEGRAL] += 1
|
|
5957
6066
|
# si.solve_complemented_assertion(ass.get_individual(), self)
|
|
5958
|
-
self.solve_concept_complemented_assertion(ass.get_individual(), None,
|
|
6067
|
+
self.solve_concept_complemented_assertion(ass.get_individual(), None, c)
|
|
5959
6068
|
|
|
5960
6069
|
def rule_quasi_sugeno(self, ass: Assertion) -> None:
|
|
5961
6070
|
self.rules_applied[KnowledgeBaseRules.RULE_QUASI_SUGENO_INTEGRAL] += 1
|
|
@@ -5969,11 +6078,11 @@ class KnowledgeBase:
|
|
|
5969
6078
|
def rule_complemented_quasi_sugeno(self, ass: Assertion) -> None:
|
|
5970
6079
|
c: Concept = ass.get_concept()
|
|
5971
6080
|
assert isinstance(c, OperatorConcept)
|
|
5972
|
-
|
|
6081
|
+
assert isinstance(c.get_atom(), QsugenoIntegral)
|
|
5973
6082
|
|
|
5974
6083
|
self.rules_applied[KnowledgeBaseRules.RULE_NOT_QUASI_SUGENO_INTEGRAL] += 1
|
|
5975
6084
|
# qsi.solve_complemented_assertion(ass.get_individual(), self)
|
|
5976
|
-
self.solve_concept_complemented_assertion(ass.get_individual(), None,
|
|
6085
|
+
self.solve_concept_complemented_assertion(ass.get_individual(), None, c)
|
|
5977
6086
|
|
|
5978
6087
|
def rule_complemented_at_most_datatype_restriction(
|
|
5979
6088
|
self, b: CreatedIndividual, ass: Assertion
|
|
@@ -6002,9 +6111,6 @@ class KnowledgeBase:
|
|
|
6002
6111
|
def set_dynamic_blocking(self) -> None:
|
|
6003
6112
|
self.blocking_dynamic = True
|
|
6004
6113
|
|
|
6005
|
-
def get_version(self) -> float:
|
|
6006
|
-
return KnowledgeBase.VERSION
|
|
6007
|
-
|
|
6008
6114
|
def is_crisp_role(self, role_name: str) -> bool:
|
|
6009
6115
|
return (
|
|
6010
6116
|
constants.KNOWLEDGE_BASE_SEMANTICS == FuzzyLogic.CLASSICAL
|
|
@@ -6216,6 +6322,7 @@ class KnowledgeBase:
|
|
|
6216
6322
|
Util.debug(f"{constants.STAR_SEPARATOR * 2}")
|
|
6217
6323
|
|
|
6218
6324
|
|
|
6325
|
+
@class_debugging()
|
|
6219
6326
|
class DatatypeReasoner:
|
|
6220
6327
|
|
|
6221
6328
|
@staticmethod
|
|
@@ -6256,7 +6363,7 @@ class DatatypeReasoner:
|
|
|
6256
6363
|
ind, role, b, DegreeVariable.get_degree(x_f), kb
|
|
6257
6364
|
)
|
|
6258
6365
|
x_b: Variable = DatatypeReasoner.get_xb(b, t, kb)
|
|
6259
|
-
if new_variable
|
|
6366
|
+
if new_variable and k is not None:
|
|
6260
6367
|
kb.restrict_range(x_b, x_f, k[0], k[1])
|
|
6261
6368
|
return [b, x_b, x_f]
|
|
6262
6369
|
|
|
@@ -6495,7 +6602,7 @@ class DatatypeReasoner:
|
|
|
6495
6602
|
n, kb, x_b, x_is_c, x_f, k, InequalityType.LESS_THAN
|
|
6496
6603
|
)
|
|
6497
6604
|
elif type == InequalityType.GREATER_THAN:
|
|
6498
|
-
if isinstance(n,
|
|
6605
|
+
if isinstance(n, constants.NUMBER):
|
|
6499
6606
|
kb.milp.add_new_constraint(
|
|
6500
6607
|
Expression(
|
|
6501
6608
|
constants.MAXVAL,
|
|
@@ -6524,7 +6631,7 @@ class DatatypeReasoner:
|
|
|
6524
6631
|
InequalityType.GREATER_THAN,
|
|
6525
6632
|
)
|
|
6526
6633
|
elif type == InequalityType.LESS_THAN:
|
|
6527
|
-
if isinstance(n,
|
|
6634
|
+
if isinstance(n, constants.NUMBER):
|
|
6528
6635
|
kb.milp.add_new_constraint(
|
|
6529
6636
|
Expression(
|
|
6530
6637
|
-constants.MAXVAL,
|
|
@@ -6564,7 +6671,7 @@ class DatatypeReasoner:
|
|
|
6564
6671
|
t: ConcreteFeature = DatatypeReasoner.get_feature(f_name, kb)
|
|
6565
6672
|
k: typing.Optional[list[float]] = DatatypeReasoner.get_bounds(t)
|
|
6566
6673
|
return_value: list[typing.Any] = (
|
|
6567
|
-
DatatypeReasoner.get_created_individual_and_variables(a,
|
|
6674
|
+
DatatypeReasoner.get_created_individual_and_variables(a, f_name, t, k, kb)
|
|
6568
6675
|
)
|
|
6569
6676
|
b: CreatedIndividual = typing.cast(CreatedIndividual, return_value[0])
|
|
6570
6677
|
x_b: Variable = typing.cast(Variable, return_value[1])
|
|
@@ -6647,7 +6754,8 @@ class DatatypeReasoner:
|
|
|
6647
6754
|
type: InequalityType,
|
|
6648
6755
|
) -> None:
|
|
6649
6756
|
if type == InequalityType.GREATER_THAN:
|
|
6650
|
-
if isinstance(n,
|
|
6757
|
+
if isinstance(n, constants.NUMBER):
|
|
6758
|
+
# x_b <= (n - \epsilon) + (2 k_\infty + \epsilon) (1 - x_f) + (2k_\infty + \epsilon) x_is_c
|
|
6651
6759
|
kb.milp.add_new_constraint(
|
|
6652
6760
|
Expression(
|
|
6653
6761
|
constants.MAXVAL2 + n,
|
|
@@ -6658,6 +6766,7 @@ class DatatypeReasoner:
|
|
|
6658
6766
|
InequalityType.GREATER_THAN,
|
|
6659
6767
|
)
|
|
6660
6768
|
elif isinstance(n, Variable):
|
|
6769
|
+
# x_b <= x - \epsilon x_f + 2k_\infty (1 - x_f) + (2k_\infty + \epsilon) x_is_c
|
|
6661
6770
|
kb.milp.add_new_constraint(
|
|
6662
6771
|
Expression(
|
|
6663
6772
|
constants.MAXVAL2,
|
|
@@ -6668,16 +6777,19 @@ class DatatypeReasoner:
|
|
|
6668
6777
|
),
|
|
6669
6778
|
InequalityType.GREATER_THAN,
|
|
6670
6779
|
)
|
|
6780
|
+
# x \geq -max_val
|
|
6671
6781
|
kb.milp.add_new_constraint(
|
|
6672
6782
|
Expression(constants.MAXVAL, Term(1.0, n)),
|
|
6673
6783
|
InequalityType.GREATER_THAN,
|
|
6674
6784
|
)
|
|
6785
|
+
# x \leq max_val
|
|
6675
6786
|
kb.milp.add_new_constraint(
|
|
6676
6787
|
Expression(constants.MAXVAL, Term(-1.0, n)),
|
|
6677
6788
|
InequalityType.GREATER_THAN,
|
|
6678
6789
|
)
|
|
6679
6790
|
elif type == InequalityType.LESS_THAN:
|
|
6680
|
-
if isinstance(n,
|
|
6791
|
+
if isinstance(n, constants.NUMBER):
|
|
6792
|
+
# x_b >= (n + \epsilon) - (2 k_\infty + \epsilon) (1 - x_f) - (2k_\infty + \epsilon) x_is_c
|
|
6681
6793
|
kb.milp.add_new_constraint(
|
|
6682
6794
|
Expression(
|
|
6683
6795
|
-constants.MAXVAL2 + n,
|
|
@@ -6688,6 +6800,7 @@ class DatatypeReasoner:
|
|
|
6688
6800
|
InequalityType.LESS_THAN,
|
|
6689
6801
|
)
|
|
6690
6802
|
elif isinstance(n, Variable):
|
|
6803
|
+
# x_b >= x + \epsilon x_f - 2k_\infty (1 - x_f) - (2k_\infty + \epsilon) x_is_c
|
|
6691
6804
|
kb.milp.add_new_constraint(
|
|
6692
6805
|
Expression(
|
|
6693
6806
|
-constants.MAXVAL2,
|
|
@@ -6698,16 +6811,19 @@ class DatatypeReasoner:
|
|
|
6698
6811
|
),
|
|
6699
6812
|
InequalityType.LESS_THAN,
|
|
6700
6813
|
)
|
|
6814
|
+
# x \geq -max_val
|
|
6701
6815
|
kb.milp.add_new_constraint(
|
|
6702
6816
|
Expression(constants.MAXVAL, Term(1.0, n)),
|
|
6703
6817
|
InequalityType.GREATER_THAN,
|
|
6704
6818
|
)
|
|
6819
|
+
# x \leq max_val
|
|
6705
6820
|
kb.milp.add_new_constraint(
|
|
6706
6821
|
Expression(constants.MAXVAL, Term(-1.0, n)),
|
|
6707
6822
|
InequalityType.GREATER_THAN,
|
|
6708
6823
|
)
|
|
6709
6824
|
elif type == InequalityType.EQUAL:
|
|
6710
|
-
if isinstance(n,
|
|
6825
|
+
if isinstance(n, constants.NUMBER):
|
|
6826
|
+
# x_b <= (n - \epsilon) y + k_\infty (1 - y) + (2 k_\infty + \epsilon) (1 - x_f) + (2k_\infty + \epsilon) x_is_c
|
|
6711
6827
|
y: Variable = kb.milp.get_new_variable(VariableType.BINARY)
|
|
6712
6828
|
kb.milp.add_new_constraint(
|
|
6713
6829
|
Expression(
|
|
@@ -6719,6 +6835,7 @@ class DatatypeReasoner:
|
|
|
6719
6835
|
),
|
|
6720
6836
|
InequalityType.GREATER_THAN,
|
|
6721
6837
|
)
|
|
6838
|
+
# x_b >= (n + \epsilon) (1 - y) - k_\infty y - (2 k_\infty + \epsilon) (1 - x_f) - (2k_\infty + \epsilon) x_is_c
|
|
6722
6839
|
kb.milp.add_new_constraint(
|
|
6723
6840
|
Expression(
|
|
6724
6841
|
-constants.MAXVAL2 + n,
|
|
@@ -6730,10 +6847,11 @@ class DatatypeReasoner:
|
|
|
6730
6847
|
InequalityType.LESS_THAN,
|
|
6731
6848
|
)
|
|
6732
6849
|
elif isinstance(n, Variable):
|
|
6850
|
+
# x_b <= x - \epsilon x_f + (2k_\infty + \epsilon) (1 - y) + 2k_\infty (1 - x_f) + (2k_\infty + \epsilon) x_is_c
|
|
6733
6851
|
y: Variable = kb.milp.get_new_variable(VariableType.BINARY)
|
|
6734
6852
|
kb.milp.add_new_constraint(
|
|
6735
6853
|
Expression(
|
|
6736
|
-
|
|
6854
|
+
4 * constants.MAXVAL + ConfigReader.EPSILON,
|
|
6737
6855
|
Term(constants.MAXVAL + n + ConfigReader.EPSILON, y),
|
|
6738
6856
|
Term(-1.0, x_b),
|
|
6739
6857
|
Term(1.0, n),
|
|
@@ -6742,6 +6860,7 @@ class DatatypeReasoner:
|
|
|
6742
6860
|
),
|
|
6743
6861
|
InequalityType.GREATER_THAN,
|
|
6744
6862
|
)
|
|
6863
|
+
# x_b >= x + \epsilon x_f - (2k_\infty + \epsilon) y - 2k_\infty (1 - x_f) - (2k_\infty + \epsilon) x_is_c
|
|
6745
6864
|
kb.milp.add_new_constraint(
|
|
6746
6865
|
Expression(
|
|
6747
6866
|
-constants.MAXVAL2,
|
|
@@ -6753,10 +6872,12 @@ class DatatypeReasoner:
|
|
|
6753
6872
|
),
|
|
6754
6873
|
InequalityType.LESS_THAN,
|
|
6755
6874
|
)
|
|
6875
|
+
# x \geq -maxval
|
|
6756
6876
|
kb.milp.add_new_constraint(
|
|
6757
6877
|
Expression(constants.MAXVAL, Term(1.0, n)),
|
|
6758
6878
|
InequalityType.GREATER_THAN,
|
|
6759
6879
|
)
|
|
6880
|
+
# x \leq maxval
|
|
6760
6881
|
kb.milp.add_new_constraint(
|
|
6761
6882
|
Expression(constants.MAXVAL, Term(-1.0, n)),
|
|
6762
6883
|
InequalityType.GREATER_THAN,
|
|
@@ -6920,27 +7041,23 @@ class DatatypeReasoner:
|
|
|
6920
7041
|
b: CreatedIndividual, ass: Assertion, kb: KnowledgeBase, type: InequalityType
|
|
6921
7042
|
) -> None:
|
|
6922
7043
|
a: Individual = ass.get_individual()
|
|
7044
|
+
not_c: Concept = ass.get_concept()
|
|
7045
|
+
assert isinstance(not_c, OperatorConcept)
|
|
7046
|
+
c: Concept = not_c.get_atom()
|
|
7047
|
+
assert isinstance(c, HasValueInterface)
|
|
6923
7048
|
|
|
6924
|
-
|
|
6925
|
-
assert isinstance(c, OperatorConcept)
|
|
6926
|
-
|
|
6927
|
-
not_c: Concept = c.get_atom()
|
|
6928
|
-
assert isinstance(not_c, HasValueInterface)
|
|
6929
|
-
|
|
6930
|
-
f_name: str = not_c.role
|
|
7049
|
+
f_name: str = c.role
|
|
6931
7050
|
t: ConcreteFeature = DatatypeReasoner.get_feature(f_name, kb)
|
|
6932
7051
|
k: typing.Optional[list[float]] = DatatypeReasoner.get_bounds(t)
|
|
6933
7052
|
return_value: list[typing.Any] = (
|
|
6934
|
-
DatatypeReasoner.get_created_individual_and_variables(
|
|
6935
|
-
a, not_c.role, t, k, kb
|
|
6936
|
-
)
|
|
7053
|
+
DatatypeReasoner.get_created_individual_and_variables(a, f_name, t, k, kb)
|
|
6937
7054
|
)
|
|
6938
7055
|
x_f: Variable = typing.cast(Variable, return_value[2])
|
|
6939
7056
|
x_is_not_c: Variable = kb.milp.get_variable(ass)
|
|
6940
7057
|
kb.old_binary_variables += 1
|
|
6941
7058
|
x_f.set_binary_variable()
|
|
6942
7059
|
x_b: Variable = DatatypeReasoner.get_xb(b, t, kb)
|
|
6943
|
-
c: Concept = -not_c
|
|
7060
|
+
# c: Concept = -not_c
|
|
6944
7061
|
x_is_c: Variable = kb.milp.get_variable(a, c)
|
|
6945
7062
|
x_b.set_datatype_filler_variable()
|
|
6946
7063
|
kb.milp.add_new_constraint(
|
|
@@ -6972,6 +7089,7 @@ class DatatypeReasoner:
|
|
|
6972
7089
|
x_is_not_c.set_binary_variable()
|
|
6973
7090
|
x_is_c.set_binary_variable()
|
|
6974
7091
|
if isinstance(n, FeatureFunction):
|
|
7092
|
+
# If n is a FeatureFunction, check that there exist fillers
|
|
6975
7093
|
fun: FeatureFunction = typing.cast(FeatureFunction, n)
|
|
6976
7094
|
array: set[str] = fun.get_features()
|
|
6977
7095
|
for feature in array:
|
|
@@ -7026,6 +7144,7 @@ class DatatypeReasoner:
|
|
|
7026
7144
|
DatatypeReasoner.apply_not_rule(b, ass, kb, InequalityType.EQUAL)
|
|
7027
7145
|
|
|
7028
7146
|
|
|
7147
|
+
@class_debugging()
|
|
7029
7148
|
class LukasiewiczSolver:
|
|
7030
7149
|
@staticmethod
|
|
7031
7150
|
def solve_and(ass: Assertion, kb: KnowledgeBase) -> None:
|
|
@@ -7352,6 +7471,7 @@ class LukasiewiczSolver:
|
|
|
7352
7471
|
milp.add_new_constraint(exp2, InequalityType.LESS_THAN)
|
|
7353
7472
|
|
|
7354
7473
|
|
|
7474
|
+
@class_debugging()
|
|
7355
7475
|
class ZadehSolver:
|
|
7356
7476
|
|
|
7357
7477
|
@staticmethod
|
|
@@ -7849,14 +7969,12 @@ class ZadehSolver:
|
|
|
7849
7969
|
else:
|
|
7850
7970
|
assert isinstance(args[0], Variable)
|
|
7851
7971
|
assert isinstance(args[1], Variable)
|
|
7852
|
-
assert isinstance(args[2],
|
|
7972
|
+
assert isinstance(args[2], constants.NUMBER)
|
|
7853
7973
|
assert isinstance(args[3], MILPHelper)
|
|
7854
7974
|
ZadehSolver.__or_equation_1(*args)
|
|
7855
7975
|
|
|
7856
7976
|
@staticmethod
|
|
7857
|
-
def __or_equation_1(
|
|
7858
|
-
z: Variable, x1: Variable, x2: Variable, milp: MILPHelper
|
|
7859
|
-
) -> None:
|
|
7977
|
+
def __or_equation_1(z: Variable, x1: Variable, x2: float, milp: MILPHelper) -> None:
|
|
7860
7978
|
y: Variable = milp.get_new_variable(VariableType.BINARY)
|
|
7861
7979
|
milp.add_new_constraint(
|
|
7862
7980
|
Expression(Term(1.0, z), Term(-1.0, x1)), InequalityType.GREATER_THAN
|
|
@@ -7936,6 +8054,7 @@ class ZadehSolver:
|
|
|
7936
8054
|
return n1
|
|
7937
8055
|
|
|
7938
8056
|
|
|
8057
|
+
@class_debugging()
|
|
7939
8058
|
class ClassicalSolver:
|
|
7940
8059
|
@staticmethod
|
|
7941
8060
|
def solve_and(ass: Assertion, kb: KnowledgeBase) -> None:
|
|
@@ -7954,6 +8073,7 @@ class ClassicalSolver:
|
|
|
7954
8073
|
ZadehSolver.solve_all(rel, restrict, kb)
|
|
7955
8074
|
|
|
7956
8075
|
|
|
8076
|
+
@class_debugging()
|
|
7957
8077
|
class IndividualHandler:
|
|
7958
8078
|
|
|
7959
8079
|
@staticmethod
|
|
@@ -8134,6 +8254,7 @@ class IndividualHandler:
|
|
|
8134
8254
|
return
|
|
8135
8255
|
|
|
8136
8256
|
|
|
8257
|
+
@class_debugging()
|
|
8137
8258
|
class CreatedIndividualHandler:
|
|
8138
8259
|
|
|
8139
8260
|
@staticmethod
|
|
@@ -8167,16 +8288,22 @@ class CreatedIndividualHandler:
|
|
|
8167
8288
|
def unblock_pairwise(
|
|
8168
8289
|
current_individual: CreatedIndividual, kb: KnowledgeBase
|
|
8169
8290
|
) -> None:
|
|
8291
|
+
"""
|
|
8292
|
+
Unblock the individual
|
|
8293
|
+
"""
|
|
8170
8294
|
Util.debug(f"Test of Pair-wise Unblock children of {current_individual.name}")
|
|
8295
|
+
# "current_individual" is a blocking Y node: unblock blocked nodes
|
|
8171
8296
|
if current_individual.name in kb.directly_blocked_children:
|
|
8172
8297
|
Util.debug(f"{current_individual.name} is a blocking Y node")
|
|
8298
|
+
# remove Y from the Yprime list
|
|
8173
8299
|
y_prime: CreatedIndividual = typing.cast(
|
|
8174
8300
|
CreatedIndividual,
|
|
8175
8301
|
typing.cast(CreatedIndividual, current_individual).parent,
|
|
8176
8302
|
)
|
|
8177
8303
|
y_individuals: list[str] = kb.y_prime_individuals.get(str(y_prime), [])
|
|
8178
|
-
|
|
8304
|
+
y_individuals.remove(current_individual.name)
|
|
8179
8305
|
|
|
8306
|
+
# update Xprime list
|
|
8180
8307
|
if len(y_individuals) > 0:
|
|
8181
8308
|
kb.y_prime_individuals[str(y_prime)] = y_individuals
|
|
8182
8309
|
else:
|
|
@@ -8184,6 +8311,7 @@ class CreatedIndividualHandler:
|
|
|
8184
8311
|
|
|
8185
8312
|
for x_name in kb.directly_blocked_children.get(current_individual.name):
|
|
8186
8313
|
Util.debug(f"Processing X node {x_name}")
|
|
8314
|
+
# remove Xname from the Xprime list
|
|
8187
8315
|
x: CreatedIndividual = typing.cast(
|
|
8188
8316
|
CreatedIndividual, kb.individuals.get(x_name)
|
|
8189
8317
|
)
|
|
@@ -8191,22 +8319,25 @@ class CreatedIndividualHandler:
|
|
|
8191
8319
|
CreatedIndividual, x.get_parent()
|
|
8192
8320
|
)
|
|
8193
8321
|
x_individuals: list[str] = kb.x_prime_individuals.get(str(x_prime), [])
|
|
8194
|
-
|
|
8195
|
-
|
|
8322
|
+
x_individuals.remove(x_name)
|
|
8196
8323
|
if len(x_individuals) > 0:
|
|
8197
8324
|
kb.x_prime_individuals[str(x_prime)] = x_individuals
|
|
8198
8325
|
else:
|
|
8199
8326
|
del kb.x_prime_individuals[str(x_prime)]
|
|
8327
|
+
# at last, unblock
|
|
8200
8328
|
kb.unblock_individual(x_name)
|
|
8201
8329
|
|
|
8330
|
+
# now, Y (= current_individual) cannot be a blocking node anymore
|
|
8202
8331
|
del kb.directly_blocked_children[current_individual.name]
|
|
8203
8332
|
|
|
8333
|
+
# if "current_individual" is a Yprime node: unblock blocking Y nodes
|
|
8204
8334
|
if current_individual.name in kb.y_prime_individuals:
|
|
8205
8335
|
Util.debug(f"{current_individual.name} is a y_prime node")
|
|
8206
8336
|
for y_name in kb.y_prime_individuals.get(current_individual.name):
|
|
8207
8337
|
Util.debug(f"Processing Y node {y_name}")
|
|
8208
8338
|
for x_name in kb.directly_blocked_children.get(y_name):
|
|
8209
8339
|
Util.debug(f"Processing X node {x_name}")
|
|
8340
|
+
# remove X from the Xprime list
|
|
8210
8341
|
x: CreatedIndividual = typing.cast(
|
|
8211
8342
|
CreatedIndividual, kb.individuals.get(x_name)
|
|
8212
8343
|
)
|
|
@@ -8219,17 +8350,19 @@ class CreatedIndividualHandler:
|
|
|
8219
8350
|
x_individuals: list[str] = kb.x_prime_individuals.get(
|
|
8220
8351
|
str(x_prime), []
|
|
8221
8352
|
)
|
|
8222
|
-
|
|
8353
|
+
x_individuals.remove(x_name)
|
|
8223
8354
|
if len(x_individuals) > 0:
|
|
8224
8355
|
kb.x_prime_individuals[str(x_prime)] = x_individuals
|
|
8225
8356
|
else:
|
|
8226
8357
|
del kb.x_prime_individuals[str(x_prime)]
|
|
8227
|
-
|
|
8358
|
+
# unblock X
|
|
8228
8359
|
kb.unblock_individual(x_name)
|
|
8229
|
-
|
|
8360
|
+
# now, Yname cannot be a blocking node anymore
|
|
8230
8361
|
del kb.directly_blocked_children[y_name]
|
|
8362
|
+
# now, remove Yprime from the Yprime list
|
|
8231
8363
|
del kb.y_prime_individuals[current_individual.name]
|
|
8232
8364
|
|
|
8365
|
+
# if "current_individual" is a Xprime node: unblock blocked X nodes
|
|
8233
8366
|
if current_individual.name in kb.x_prime_individuals:
|
|
8234
8367
|
Util.debug(f"{current_individual.name} is a x_prime node")
|
|
8235
8368
|
x_individuals: list[str] = kb.x_prime_individuals.get(
|
|
@@ -8237,6 +8370,7 @@ class CreatedIndividualHandler:
|
|
|
8237
8370
|
)
|
|
8238
8371
|
for x_name in x_individuals:
|
|
8239
8372
|
Util.debug(f"Processing X node {x_name}")
|
|
8373
|
+
# remove X from the directlyBlockedChildren list
|
|
8240
8374
|
x: CreatedIndividual = typing.cast(
|
|
8241
8375
|
CreatedIndividual, kb.individuals.get(x_name)
|
|
8242
8376
|
)
|
|
@@ -8246,26 +8380,28 @@ class CreatedIndividualHandler:
|
|
|
8246
8380
|
CreatedIndividual, kb.individuals.get(y_name)
|
|
8247
8381
|
)
|
|
8248
8382
|
blocked_by_y: list[str] = kb.directly_blocked_children[y_name]
|
|
8249
|
-
|
|
8383
|
+
blocked_by_y.remove(x_name)
|
|
8250
8384
|
|
|
8251
8385
|
if len(blocked_by_y) > 0:
|
|
8252
8386
|
kb.directly_blocked_children[y_name] = blocked_by_y
|
|
8253
8387
|
else:
|
|
8254
8388
|
del kb.directly_blocked_children[y_name]
|
|
8389
|
+
# update Yprime list
|
|
8255
8390
|
y_prime: CreatedIndividual = typing.cast(
|
|
8256
8391
|
CreatedIndividual, y.get_parent()
|
|
8257
8392
|
)
|
|
8258
8393
|
y_individuals: list[str] = kb.x_prime_individuals.get(
|
|
8259
8394
|
str(y_prime)
|
|
8260
8395
|
)
|
|
8261
|
-
|
|
8396
|
+
y_individuals.remove(y_name)
|
|
8262
8397
|
|
|
8263
8398
|
if len(y_individuals) > 0:
|
|
8264
8399
|
kb.y_prime_individuals[str(y_prime)] = x_individuals
|
|
8265
8400
|
else:
|
|
8266
8401
|
del kb.y_prime_individuals[str(y_prime)]
|
|
8267
|
-
|
|
8402
|
+
# unblock X
|
|
8268
8403
|
kb.unblock_individual(x_name)
|
|
8404
|
+
# now, remove Xprime from the Xprime list
|
|
8269
8405
|
del kb.x_prime_individuals[current_individual.name]
|
|
8270
8406
|
|
|
8271
8407
|
@staticmethod
|