fuzzy-dl-owl2 1.0.7__py3-none-any.whl → 1.0.9__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/__init__.py +2 -1
- fuzzy_dl_owl2/fuzzydl/assertion/assertion.py +1 -0
- fuzzy_dl_owl2/fuzzydl/assertion/atomic_assertion.py +2 -0
- fuzzy_dl_owl2/fuzzydl/classification_node.py +64 -0
- fuzzy_dl_owl2/fuzzydl/concept/__init__.py +2 -0
- fuzzy_dl_owl2/fuzzydl/concept/atomic_concept.py +1 -1
- fuzzy_dl_owl2/fuzzydl/concept/choquet_integral.py +6 -0
- fuzzy_dl_owl2/fuzzydl/concept/concept.py +8 -0
- fuzzy_dl_owl2/fuzzydl/concept/concrete/crisp_concrete_concept.py +1 -0
- fuzzy_dl_owl2/fuzzydl/concept/concrete/fuzzy_concrete_concept.py +1 -0
- fuzzy_dl_owl2/fuzzydl/concept/concrete/fuzzy_number/triangular_fuzzy_number.py +12 -0
- fuzzy_dl_owl2/fuzzydl/concept/concrete/left_concrete_concept.py +3 -0
- fuzzy_dl_owl2/fuzzydl/concept/concrete/linear_concrete_concept.py +3 -0
- fuzzy_dl_owl2/fuzzydl/concept/concrete/modified_concrete_concept.py +4 -0
- fuzzy_dl_owl2/fuzzydl/concept/concrete/right_concrete_concept.py +2 -0
- fuzzy_dl_owl2/fuzzydl/concept/concrete/trapezoidal_concrete_concept.py +1 -0
- fuzzy_dl_owl2/fuzzydl/concept/concrete/triangular_concrete_concept.py +2 -0
- fuzzy_dl_owl2/fuzzydl/concept/modified/linearly_modified_concept.py +3 -0
- fuzzy_dl_owl2/fuzzydl/concept/modified/modified_concept.py +3 -0
- fuzzy_dl_owl2/fuzzydl/concept/modified/triangularly_modified_concept.py +3 -0
- fuzzy_dl_owl2/fuzzydl/concept/negated_nominal.py +3 -0
- fuzzy_dl_owl2/fuzzydl/concept/operator_concept.py +8 -0
- fuzzy_dl_owl2/fuzzydl/concept/qowa_concept.py +4 -0
- fuzzy_dl_owl2/fuzzydl/concept/quasi_sugeno_integral.py +3 -0
- fuzzy_dl_owl2/fuzzydl/concept/sigma_concept.py +71 -0
- fuzzy_dl_owl2/fuzzydl/concept/sigma_count.py +56 -0
- fuzzy_dl_owl2/fuzzydl/concept/sugeno_integral.py +4 -0
- fuzzy_dl_owl2/fuzzydl/concept_equivalence.py +5 -0
- fuzzy_dl_owl2/fuzzydl/concrete_feature.py +6 -0
- fuzzy_dl_owl2/fuzzydl/domain_axiom.py +3 -0
- fuzzy_dl_owl2/fuzzydl/feature_function.py +3 -0
- fuzzy_dl_owl2/fuzzydl/fuzzydl_to_owl2.py +169 -27
- fuzzy_dl_owl2/fuzzydl/general_concept_inclusion.py +6 -0
- fuzzy_dl_owl2/fuzzydl/individual/created_individual.py +41 -2
- fuzzy_dl_owl2/fuzzydl/individual/individual.py +14 -0
- fuzzy_dl_owl2/fuzzydl/individual/representative_individual.py +9 -0
- fuzzy_dl_owl2/fuzzydl/knowledge_base.py +2033 -249
- fuzzy_dl_owl2/fuzzydl/label.py +18 -10
- fuzzy_dl_owl2/fuzzydl/milp/expression.py +33 -23
- fuzzy_dl_owl2/fuzzydl/milp/inequation.py +8 -0
- fuzzy_dl_owl2/fuzzydl/milp/milp_helper.py +720 -22
- fuzzy_dl_owl2/fuzzydl/milp/show_variables_helper.py +82 -0
- fuzzy_dl_owl2/fuzzydl/milp/solution.py +23 -0
- fuzzy_dl_owl2/fuzzydl/milp/variable.py +7 -0
- fuzzy_dl_owl2/fuzzydl/modifier/linear_modifier.py +3 -0
- fuzzy_dl_owl2/fuzzydl/modifier/modifier.py +21 -0
- fuzzy_dl_owl2/fuzzydl/parser/dl_parser.py +48 -7
- fuzzy_dl_owl2/fuzzydl/primitive_concept_definition.py +7 -0
- fuzzy_dl_owl2/fuzzydl/query/__init__.py +1 -0
- fuzzy_dl_owl2/fuzzydl/query/all_instances_query.py +80 -1
- fuzzy_dl_owl2/fuzzydl/query/bnp_query.py +2 -0
- fuzzy_dl_owl2/fuzzydl/query/classification_query.py +26 -0
- fuzzy_dl_owl2/fuzzydl/query/defuzzify/defuzzify_query.py +2 -1
- fuzzy_dl_owl2/fuzzydl/query/defuzzify/lom_defuzzify_query.py +4 -0
- fuzzy_dl_owl2/fuzzydl/query/defuzzify/mom_defuzzify_query.py +6 -2
- fuzzy_dl_owl2/fuzzydl/query/defuzzify/som_defuzzify_query.py +2 -0
- fuzzy_dl_owl2/fuzzydl/query/instance_query.py +5 -0
- fuzzy_dl_owl2/fuzzydl/query/kb_satisfiable_query.py +12 -2
- fuzzy_dl_owl2/fuzzydl/query/max/max_instance_query.py +6 -1
- fuzzy_dl_owl2/fuzzydl/query/max/max_query.py +7 -1
- fuzzy_dl_owl2/fuzzydl/query/max/max_related_query.py +6 -1
- fuzzy_dl_owl2/fuzzydl/query/max/max_satisfiable_query.py +15 -1
- fuzzy_dl_owl2/fuzzydl/query/max/max_subsumes_query.py +4 -1
- fuzzy_dl_owl2/fuzzydl/query/min/min_instance_query.py +6 -1
- fuzzy_dl_owl2/fuzzydl/query/min/min_query.py +7 -1
- fuzzy_dl_owl2/fuzzydl/query/min/min_related_query.py +5 -1
- fuzzy_dl_owl2/fuzzydl/query/min/min_satisfiable_query.py +17 -1
- fuzzy_dl_owl2/fuzzydl/query/min/min_subsumes_query.py +47 -7
- fuzzy_dl_owl2/fuzzydl/query/query.py +5 -2
- fuzzy_dl_owl2/fuzzydl/query/related_query.py +8 -1
- fuzzy_dl_owl2/fuzzydl/query/satisfiable_query.py +17 -0
- fuzzy_dl_owl2/fuzzydl/query/subsumption_query.py +5 -0
- fuzzy_dl_owl2/fuzzydl/range_axiom.py +4 -0
- fuzzy_dl_owl2/fuzzydl/relation.py +5 -0
- fuzzy_dl_owl2/fuzzydl/restriction/has_value_restriction.py +2 -0
- fuzzy_dl_owl2/fuzzydl/restriction/restriction.py +3 -0
- fuzzy_dl_owl2/fuzzydl/role_parent_with_degree.py +6 -1
- fuzzy_dl_owl2/fuzzydl/util/config_reader.py +17 -27
- fuzzy_dl_owl2/fuzzydl/util/constants.py +100 -0
- fuzzy_dl_owl2-1.0.9.dist-info/METADATA +848 -0
- {fuzzy_dl_owl2-1.0.7.dist-info → fuzzy_dl_owl2-1.0.9.dist-info}/RECORD +83 -79
- fuzzy_dl_owl2-1.0.7.dist-info/METADATA +0 -408
- {fuzzy_dl_owl2-1.0.7.dist-info → fuzzy_dl_owl2-1.0.9.dist-info}/LICENSE +0 -0
- {fuzzy_dl_owl2-1.0.7.dist-info → fuzzy_dl_owl2-1.0.9.dist-info}/WHEEL +0 -0
|
@@ -10,7 +10,12 @@ from fuzzy_dl_owl2.fuzzydl.util.util import Util
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class InstanceQuery(Query, ABC):
|
|
13
|
+
"""
|
|
14
|
+
Instance checking query
|
|
15
|
+
"""
|
|
16
|
+
|
|
13
17
|
def __init__(self, concept: Concept, individual: Individual) -> None:
|
|
18
|
+
super().__init__()
|
|
14
19
|
if concept.is_concrete():
|
|
15
20
|
Util.error(f"Error: {concept} cannot be a concrete concept.")
|
|
16
21
|
|
|
@@ -9,15 +9,25 @@ from fuzzy_dl_owl2.fuzzydl.query.query import Query
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class KbSatisfiableQuery(Query):
|
|
12
|
+
"""
|
|
13
|
+
Knowledge base satisfiability degree
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def __init__(self) -> None:
|
|
17
|
+
super().__init__()
|
|
12
18
|
|
|
13
19
|
def preprocess(self, kb: KnowledgeBase) -> None:
|
|
14
20
|
pass
|
|
15
21
|
|
|
16
22
|
def solve(self, kb: KnowledgeBase) -> Solution:
|
|
17
23
|
try:
|
|
18
|
-
return
|
|
24
|
+
return (
|
|
25
|
+
Solution(1.0)
|
|
26
|
+
if self.is_consistent_kb(kb)
|
|
27
|
+
else Solution(Solution.INCONSISTENT_KB)
|
|
28
|
+
)
|
|
19
29
|
except InconsistentOntologyException:
|
|
20
|
-
return Solution(
|
|
30
|
+
return Solution(Solution.INCONSISTENT_KB)
|
|
21
31
|
|
|
22
32
|
def is_consistent_kb(self, kb: KnowledgeBase) -> bool:
|
|
23
33
|
kb.solve_abox()
|
|
@@ -15,6 +15,10 @@ from fuzzy_dl_owl2.fuzzydl.query.instance_query import InstanceQuery
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class MaxInstanceQuery(InstanceQuery):
|
|
18
|
+
"""
|
|
19
|
+
Lowest upper bound of a concept assertion
|
|
20
|
+
"""
|
|
21
|
+
|
|
18
22
|
def __init__(self, concept: Concept, individual: Individual) -> None:
|
|
19
23
|
super().__init__(concept, individual)
|
|
20
24
|
|
|
@@ -26,6 +30,7 @@ class MaxInstanceQuery(InstanceQuery):
|
|
|
26
30
|
if "(all " in str(self.conc) or "(not (b-some " in str(self.conc):
|
|
27
31
|
kb.set_dynamic_blocking()
|
|
28
32
|
|
|
33
|
+
# a: c >= q
|
|
29
34
|
kb.add_assertion(self.ind, self.conc, DegreeVariable.get_degree(q))
|
|
30
35
|
kb.solve_assertions()
|
|
31
36
|
|
|
@@ -39,7 +44,7 @@ class MaxInstanceQuery(InstanceQuery):
|
|
|
39
44
|
self.set_total_time()
|
|
40
45
|
return sol
|
|
41
46
|
except InconsistentOntologyException:
|
|
42
|
-
return Solution(
|
|
47
|
+
return Solution(Solution.INCONSISTENT_KB)
|
|
43
48
|
|
|
44
49
|
def __str__(self) -> str:
|
|
45
50
|
return f"Is {self.ind} instance of {self.conc} ? <= "
|
|
@@ -10,7 +10,13 @@ from fuzzy_dl_owl2.fuzzydl.query.query import Query
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class MaxQuery(Query):
|
|
13
|
+
"""
|
|
14
|
+
Maximize expression query
|
|
15
|
+
"""
|
|
16
|
+
|
|
13
17
|
def __init__(self, expr: Expression) -> None:
|
|
18
|
+
super().__init__()
|
|
19
|
+
# Expression to be maximized
|
|
14
20
|
self.obj_expr: Expression = Expression.negate_expression(expr)
|
|
15
21
|
|
|
16
22
|
def preprocess(self, kb: KnowledgeBase) -> None:
|
|
@@ -25,7 +31,7 @@ class MaxQuery(Query):
|
|
|
25
31
|
self.set_total_time()
|
|
26
32
|
return sol
|
|
27
33
|
except InconsistentOntologyException:
|
|
28
|
-
return Solution(
|
|
34
|
+
return Solution(Solution.INCONSISTENT_KB)
|
|
29
35
|
|
|
30
36
|
def __str__(self) -> str:
|
|
31
37
|
return f"{self.obj_expr} <= "
|
|
@@ -16,12 +16,17 @@ from fuzzy_dl_owl2.fuzzydl.query.related_query import RelatedQuery
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class MaxRelatedQuery(RelatedQuery):
|
|
19
|
+
"""
|
|
20
|
+
Lowest upper bound of a role assertion (ind1, ind2, role)
|
|
21
|
+
"""
|
|
22
|
+
|
|
19
23
|
def __init__(self, a: Individual, b: Individual, role_name: str) -> None:
|
|
20
24
|
self.ind1: Individual = a
|
|
21
25
|
self.ind2: Individual = b
|
|
22
26
|
self.role: str = role_name
|
|
23
27
|
|
|
24
28
|
def preprocess(self, kb: KnowledgeBase) -> None:
|
|
29
|
+
# glb(ind1 : b-some R ind2)
|
|
25
30
|
conc: Concept = HasValueConcept(self.role, self.ind2)
|
|
26
31
|
q: Variable = kb.milp.get_variable(self.ind1, conc)
|
|
27
32
|
kb.add_assertion(self.ind1, conc, DegreeVariable.get_degree(q))
|
|
@@ -39,7 +44,7 @@ class MaxRelatedQuery(RelatedQuery):
|
|
|
39
44
|
self.set_total_time()
|
|
40
45
|
return sol
|
|
41
46
|
except InconsistentOntologyException:
|
|
42
|
-
return Solution(
|
|
47
|
+
return Solution(Solution.INCONSISTENT_KB)
|
|
43
48
|
|
|
44
49
|
def __str__(self) -> str:
|
|
45
50
|
return f"Is {self.ind1} related to {self.ind2} through {self.role} ? <= "
|
|
@@ -18,6 +18,9 @@ from fuzzy_dl_owl2.fuzzydl.util.config_reader import ConfigReader
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
class MaxSatisfiableQuery(SatisfiableQuery):
|
|
21
|
+
"""
|
|
22
|
+
Maximal satisfiability degree of a fuzzy concept.
|
|
23
|
+
"""
|
|
21
24
|
|
|
22
25
|
@typing.overload
|
|
23
26
|
def __init__(self, c: Concept) -> None: ...
|
|
@@ -35,9 +38,20 @@ class MaxSatisfiableQuery(SatisfiableQuery):
|
|
|
35
38
|
self.__max_sat_query_init_2(*args)
|
|
36
39
|
|
|
37
40
|
def __max_sat_query_init_1(self, c: Concept) -> None:
|
|
41
|
+
"""Constructor for a general satisfiability query
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
c (Concept): A fuzzy concept for which the satisfiability is to be tested.
|
|
45
|
+
"""
|
|
38
46
|
super().__init__(c)
|
|
39
47
|
|
|
40
48
|
def __max_sat_query_init_2(self, c: Concept, a: Individual) -> None:
|
|
49
|
+
"""Constructor for a satisfiability query involving a specific individual
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
c (Concept): A fuzzy concept for which the satisfiability is to be tested.
|
|
53
|
+
a (Individual): An individual used in the satisfiability test.
|
|
54
|
+
"""
|
|
41
55
|
super().__init__(c, a)
|
|
42
56
|
|
|
43
57
|
def preprocess(self, kb: KnowledgeBase) -> None:
|
|
@@ -65,7 +79,7 @@ class MaxSatisfiableQuery(SatisfiableQuery):
|
|
|
65
79
|
self.set_total_time()
|
|
66
80
|
return sol
|
|
67
81
|
except InconsistentOntologyException:
|
|
68
|
-
return Solution(
|
|
82
|
+
return Solution(Solution.INCONSISTENT_KB)
|
|
69
83
|
|
|
70
84
|
def __str__(self) -> str:
|
|
71
85
|
if self.ind is not None:
|
|
@@ -22,6 +22,9 @@ from fuzzy_dl_owl2.fuzzydl.util.constants import LogicOperatorType
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
class MaxSubsumesQuery(SubsumptionQuery):
|
|
25
|
+
"""
|
|
26
|
+
Maximize subsumption query.
|
|
27
|
+
"""
|
|
25
28
|
|
|
26
29
|
def __init__(self, c1: Concept, c2: Concept, type_: LogicOperatorType) -> None:
|
|
27
30
|
super().__init__(c1, c2, type_)
|
|
@@ -58,7 +61,7 @@ class MaxSubsumesQuery(SubsumptionQuery):
|
|
|
58
61
|
self.set_total_time()
|
|
59
62
|
return sol
|
|
60
63
|
except InconsistentOntologyException:
|
|
61
|
-
return Solution(
|
|
64
|
+
return Solution(Solution.INCONSISTENT_KB)
|
|
62
65
|
|
|
63
66
|
def __str__(self) -> str:
|
|
64
67
|
return f"{self.c1} subsumes {self.c2} ? <= "
|
|
@@ -16,6 +16,10 @@ from fuzzy_dl_owl2.fuzzydl.util.constants import VariableType
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class MinInstanceQuery(InstanceQuery):
|
|
19
|
+
"""
|
|
20
|
+
Greatest lower bound of a concept assertion.
|
|
21
|
+
"""
|
|
22
|
+
|
|
19
23
|
def __init__(self, concept: Concept, individual: Individual) -> None:
|
|
20
24
|
super().__init__(concept, individual)
|
|
21
25
|
|
|
@@ -27,6 +31,7 @@ class MinInstanceQuery(InstanceQuery):
|
|
|
27
31
|
if "(some " in str(self.conc) or "(b-some " in str(self.conc):
|
|
28
32
|
kb.set_dynamic_blocking()
|
|
29
33
|
|
|
34
|
+
# a: not c >= 1-q
|
|
30
35
|
kb.add_assertion(
|
|
31
36
|
self.ind,
|
|
32
37
|
-self.conc,
|
|
@@ -44,7 +49,7 @@ class MinInstanceQuery(InstanceQuery):
|
|
|
44
49
|
self.set_total_time()
|
|
45
50
|
return sol
|
|
46
51
|
except InconsistentOntologyException:
|
|
47
|
-
return Solution(
|
|
52
|
+
return Solution(Solution.INCONSISTENT_KB)
|
|
48
53
|
|
|
49
54
|
def __str__(self) -> str:
|
|
50
55
|
return f"Is {self.ind} instance of {self.conc} ? >= "
|
|
@@ -10,7 +10,13 @@ from fuzzy_dl_owl2.fuzzydl.query.query import Query
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class MinQuery(Query):
|
|
13
|
+
"""
|
|
14
|
+
Minimize expression query.
|
|
15
|
+
"""
|
|
16
|
+
|
|
13
17
|
def __init__(self, expr: Expression) -> None:
|
|
18
|
+
super().__init__()
|
|
19
|
+
# Expression to be minimized.
|
|
14
20
|
self.obj_expr = expr
|
|
15
21
|
|
|
16
22
|
def preprocess(self, kb: KnowledgeBase) -> None:
|
|
@@ -25,7 +31,7 @@ class MinQuery(Query):
|
|
|
25
31
|
self.set_total_time()
|
|
26
32
|
return sol
|
|
27
33
|
except InconsistentOntologyException:
|
|
28
|
-
return Solution(
|
|
34
|
+
return Solution(Solution.INCONSISTENT_KB)
|
|
29
35
|
|
|
30
36
|
def __str__(self) -> str:
|
|
31
37
|
return f"{self.obj_expr} ? >= "
|
|
@@ -17,6 +17,9 @@ from fuzzy_dl_owl2.fuzzydl.query.related_query import RelatedQuery
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class MinRelatedQuery(RelatedQuery):
|
|
20
|
+
"""
|
|
21
|
+
Greatest lower bound of a role assertion (ind1, ind2, role).
|
|
22
|
+
"""
|
|
20
23
|
|
|
21
24
|
def __init__(self, a: Individual, b: Individual, role_name: str) -> None:
|
|
22
25
|
self.ind1: Individual = a
|
|
@@ -33,6 +36,7 @@ class MinRelatedQuery(RelatedQuery):
|
|
|
33
36
|
if "(some " in str(conc) or "(b-some " in str(conc):
|
|
34
37
|
kb.set_dynamic_blocking()
|
|
35
38
|
|
|
39
|
+
# a: not c >= 1-q
|
|
36
40
|
kb.add_assertion(
|
|
37
41
|
self.ind1,
|
|
38
42
|
-conc,
|
|
@@ -51,7 +55,7 @@ class MinRelatedQuery(RelatedQuery):
|
|
|
51
55
|
self.set_total_time()
|
|
52
56
|
return sol
|
|
53
57
|
except InconsistentOntologyException:
|
|
54
|
-
return Solution(
|
|
58
|
+
return Solution(Solution.INCONSISTENT_KB)
|
|
55
59
|
|
|
56
60
|
def __str__(self) -> str:
|
|
57
61
|
return f"Is {self.ind1} related to {self.ind2} through {self.role} ? >= "
|
|
@@ -19,6 +19,9 @@ from fuzzy_dl_owl2.fuzzydl.util.constants import VariableType
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
class MinSatisfiableQuery(SatisfiableQuery):
|
|
22
|
+
"""
|
|
23
|
+
Minimal satisfiability degree of a fuzzy concept.
|
|
24
|
+
"""
|
|
22
25
|
|
|
23
26
|
@typing.overload
|
|
24
27
|
def __init__(self, c: Concept) -> None: ...
|
|
@@ -36,9 +39,22 @@ class MinSatisfiableQuery(SatisfiableQuery):
|
|
|
36
39
|
self.__min_sat_query_init_2(*args)
|
|
37
40
|
|
|
38
41
|
def __min_sat_query_init_1(self, c: Concept) -> None:
|
|
42
|
+
"""
|
|
43
|
+
Constructor for a general satisfiability query.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
c (Concept): A fuzzy concept for which the satisfiability is to be tested.
|
|
47
|
+
"""
|
|
39
48
|
super().__init__(c)
|
|
40
49
|
|
|
41
50
|
def __min_sat_query_init_2(self, c: Concept, a: Individual) -> None:
|
|
51
|
+
"""
|
|
52
|
+
Constructor for a satisfiability query involving a specific individual.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
c (Concept): A fuzzy concept for which the satisfiability is to be tested.
|
|
56
|
+
a (Individual): An individual used in the satisfiability test.
|
|
57
|
+
"""
|
|
42
58
|
super().__init__(c, a)
|
|
43
59
|
|
|
44
60
|
def preprocess(self, kb: KnowledgeBase) -> None:
|
|
@@ -72,7 +88,7 @@ class MinSatisfiableQuery(SatisfiableQuery):
|
|
|
72
88
|
return sol
|
|
73
89
|
|
|
74
90
|
except InconsistentOntologyException:
|
|
75
|
-
return Solution(
|
|
91
|
+
return Solution(Solution.INCONSISTENT_KB)
|
|
76
92
|
|
|
77
93
|
def __str__(self) -> str:
|
|
78
94
|
if self.ind is not None:
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import typing
|
|
4
|
+
|
|
5
|
+
from fuzzy_dl_owl2.fuzzydl.classification_node import ClassificationNode
|
|
3
6
|
from fuzzy_dl_owl2.fuzzydl.concept.concept import Concept
|
|
4
7
|
from fuzzy_dl_owl2.fuzzydl.concept.implies_concept import ImpliesConcept
|
|
5
8
|
from fuzzy_dl_owl2.fuzzydl.concept.operator_concept import OperatorConcept
|
|
@@ -19,11 +22,17 @@ from fuzzy_dl_owl2.fuzzydl.util.constants import LogicOperatorType, VariableType
|
|
|
19
22
|
|
|
20
23
|
|
|
21
24
|
class MinSubsumesQuery(SubsumptionQuery):
|
|
25
|
+
"""
|
|
26
|
+
Minimize subsumption query.
|
|
27
|
+
"""
|
|
22
28
|
|
|
23
29
|
def __init__(self, c1: Concept, c2: Concept, type_: LogicOperatorType) -> None:
|
|
24
30
|
super().__init__(c1, c2, type_)
|
|
25
31
|
|
|
26
32
|
def preprocess(self, kb: KnowledgeBase) -> None:
|
|
33
|
+
if kb.is_classified():
|
|
34
|
+
return
|
|
35
|
+
|
|
27
36
|
ind: Individual = kb.get_new_individual()
|
|
28
37
|
|
|
29
38
|
if self.type == LogicOperatorType.LUKASIEWICZ:
|
|
@@ -39,6 +48,7 @@ class MinSubsumesQuery(SubsumptionQuery):
|
|
|
39
48
|
kb.old_01_variables += 1
|
|
40
49
|
self.obj_expr: Expression = Expression(Term(1.0, q))
|
|
41
50
|
|
|
51
|
+
# a: not c or d >= 1-q
|
|
42
52
|
kb.add_assertion(
|
|
43
53
|
ind,
|
|
44
54
|
-conc,
|
|
@@ -46,20 +56,50 @@ class MinSubsumesQuery(SubsumptionQuery):
|
|
|
46
56
|
)
|
|
47
57
|
kb.solve_assertions()
|
|
48
58
|
|
|
59
|
+
# def solve(self, kb: KnowledgeBase) -> Solution:
|
|
60
|
+
# try:
|
|
61
|
+
# self.set_initial_time()
|
|
62
|
+
# if ConfigReader.OPTIMIZATIONS == 0 or kb.has_nominals_in_tbox():
|
|
63
|
+
# cloned: KnowledgeBase = kb.clone()
|
|
64
|
+
# cloned.solve_abox()
|
|
65
|
+
# else:
|
|
66
|
+
# cloned: KnowledgeBase = kb.clone_without_abox()
|
|
67
|
+
# self.preprocess(cloned)
|
|
68
|
+
# sol: Solution = cloned.optimize(self.obj_expr)
|
|
69
|
+
# self.set_total_time()
|
|
70
|
+
# return sol
|
|
71
|
+
# except InconsistentOntologyException:
|
|
72
|
+
# return Solution(Solution.INCONSISTENT_KB)
|
|
73
|
+
|
|
49
74
|
def solve(self, kb: KnowledgeBase) -> Solution:
|
|
50
75
|
try:
|
|
51
76
|
self.set_initial_time()
|
|
52
|
-
if
|
|
53
|
-
|
|
54
|
-
|
|
77
|
+
if kb.is_classified() and self.c1.is_atomic() and self.c2.is_atomic():
|
|
78
|
+
n1: typing.Optional[ClassificationNode] = kb.get_classification_node(
|
|
79
|
+
str(self.c1)
|
|
80
|
+
)
|
|
81
|
+
n2: typing.Optional[ClassificationNode] = kb.get_classification_node(
|
|
82
|
+
str(self.c2)
|
|
83
|
+
)
|
|
84
|
+
if n1 is not None and n1.is_thing():
|
|
85
|
+
sol: Solution = Solution(1.0)
|
|
86
|
+
elif n2 is not None and n1.is_thing():
|
|
87
|
+
sol: Solution = Solution(1.0)
|
|
88
|
+
else:
|
|
89
|
+
sol: Solution = Solution(kb.get_subsumption_flags(n1, n2))
|
|
55
90
|
else:
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
91
|
+
if ConfigReader.OPTIMIZATIONS == 0 or kb.has_nominals_in_tbox():
|
|
92
|
+
cloned: KnowledgeBase = kb.clone()
|
|
93
|
+
cloned.solve_abox()
|
|
94
|
+
else:
|
|
95
|
+
cloned: KnowledgeBase = kb.clone_without_abox()
|
|
96
|
+
self.preprocess(cloned)
|
|
97
|
+
sol: Solution = cloned.optimize(self.obj_expr)
|
|
98
|
+
|
|
59
99
|
self.set_total_time()
|
|
60
100
|
return sol
|
|
61
101
|
except InconsistentOntologyException:
|
|
62
|
-
return Solution(
|
|
102
|
+
return Solution(Solution.INCONSISTENT_KB)
|
|
63
103
|
|
|
64
104
|
def __str__(self) -> str:
|
|
65
105
|
return f"{self.c1} subsumes {self.c2} ? >= "
|
|
@@ -8,6 +8,7 @@ from fuzzy_dl_owl2.fuzzydl.milp.solution import Solution
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class Query(ABC):
|
|
11
|
+
|
|
11
12
|
def __init__(self) -> None:
|
|
12
13
|
self.initial_time: int = 0
|
|
13
14
|
self.total_time: int = 0
|
|
@@ -24,7 +25,9 @@ class Query(ABC):
|
|
|
24
25
|
|
|
25
26
|
@abstractmethod
|
|
26
27
|
def preprocess(self, knowledge_base: KnowledgeBase) -> None:
|
|
27
|
-
"""
|
|
28
|
+
"""
|
|
29
|
+
Performs some preprocessing steps of the query over a fuzzy KB.
|
|
30
|
+
"""
|
|
28
31
|
pass
|
|
29
32
|
|
|
30
33
|
@abstractmethod
|
|
@@ -34,5 +37,5 @@ class Query(ABC):
|
|
|
34
37
|
|
|
35
38
|
@abstractmethod
|
|
36
39
|
def __str__(self) -> str:
|
|
37
|
-
"""
|
|
40
|
+
"""Solves the query over a fuzzy KB"""
|
|
38
41
|
pass
|
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from abc import ABC
|
|
4
|
+
|
|
3
5
|
from fuzzy_dl_owl2.fuzzydl.individual.individual import Individual
|
|
4
6
|
from fuzzy_dl_owl2.fuzzydl.milp.expression import Expression
|
|
5
7
|
from fuzzy_dl_owl2.fuzzydl.query.query import Query
|
|
6
8
|
|
|
7
9
|
|
|
8
|
-
class RelatedQuery(Query):
|
|
10
|
+
class RelatedQuery(Query, ABC):
|
|
11
|
+
"""Entailment of a role assertion query"""
|
|
9
12
|
|
|
10
13
|
def __init__(self) -> None:
|
|
11
14
|
super().__init__()
|
|
15
|
+
# Abstract role
|
|
12
16
|
self.role: str = None
|
|
17
|
+
# Subject of the relation.
|
|
13
18
|
self.ind1: Individual = None
|
|
19
|
+
# Object of the relation.
|
|
14
20
|
self.ind2: Individual = None
|
|
21
|
+
# Objective expression
|
|
15
22
|
self.obj_expr: Expression = None
|
|
@@ -10,6 +10,7 @@ from fuzzy_dl_owl2.fuzzydl.util.util import Util
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class SatisfiableQuery(Query):
|
|
13
|
+
"""Fuzzy concept satisfiability query."""
|
|
13
14
|
|
|
14
15
|
@typing.overload
|
|
15
16
|
def __init__(self, c: Concept, a: Individual) -> None: ...
|
|
@@ -18,6 +19,7 @@ class SatisfiableQuery(Query):
|
|
|
18
19
|
def __init__(self, c: Concept) -> None: ...
|
|
19
20
|
|
|
20
21
|
def __init__(self, *args) -> None:
|
|
22
|
+
super().__init__()
|
|
21
23
|
assert len(args) in [1, 2]
|
|
22
24
|
assert isinstance(args[0], Concept)
|
|
23
25
|
if len(args) == 1:
|
|
@@ -27,11 +29,26 @@ class SatisfiableQuery(Query):
|
|
|
27
29
|
self.__satisfiable_query_init_1(*args)
|
|
28
30
|
|
|
29
31
|
def __satisfiable_query_init_1(self, c: Concept, a: Individual) -> None:
|
|
32
|
+
"""Constructor for a satisfiability query involving a specific individual.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
c (Concept): A fuzzy concept for which the satisfiability is to be tested.
|
|
36
|
+
a (Individual): An individual used in the satisfiability test.
|
|
37
|
+
"""
|
|
30
38
|
if c.is_concrete():
|
|
31
39
|
Util.error(f"Error: {c} cannot be a concrete concept.")
|
|
40
|
+
# Fuzzy concept
|
|
32
41
|
self.conc: Concept = c
|
|
42
|
+
# Optional individual used during the satisfiability test.
|
|
33
43
|
self.ind: Individual = a
|
|
44
|
+
# Objective expression
|
|
34
45
|
self.obj_expr: Expression = None
|
|
35
46
|
|
|
36
47
|
def __satisfiable_query_init_2(self, c: Concept) -> None:
|
|
48
|
+
"""
|
|
49
|
+
Constructor for a general satisfiability query.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
c (Concept): A fuzzy concept for which the satisfiability is to be tested.
|
|
53
|
+
"""
|
|
37
54
|
self.__init__(c, None)
|
|
@@ -10,11 +10,16 @@ from fuzzy_dl_owl2.fuzzydl.util.util import Util
|
|
|
10
10
|
class SubsumptionQuery(Query):
|
|
11
11
|
|
|
12
12
|
def __init__(self, c1: Concept, c2: Concept, s_type: LogicOperatorType) -> None:
|
|
13
|
+
super().__init__()
|
|
13
14
|
if c1.is_concrete():
|
|
14
15
|
Util.error(f"Error: {c1} cannot be a concrete concept.")
|
|
15
16
|
if c2.is_concrete():
|
|
16
17
|
Util.error(f"Error: {c1} cannot be a concrete concept.")
|
|
18
|
+
# Subsumed concept
|
|
17
19
|
self.c1: Concept = c1
|
|
20
|
+
# Subsumer concept
|
|
18
21
|
self.c2: Concept = c2
|
|
22
|
+
# Fuzzy implication used
|
|
19
23
|
self.type: LogicOperatorType = s_type
|
|
24
|
+
# Objective epxression
|
|
20
25
|
self.obj_expr: Expression = None
|
|
@@ -8,6 +8,10 @@ if typing.TYPE_CHECKING:
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class Relation:
|
|
11
|
+
"""
|
|
12
|
+
Represents a role assertion of the form (object individual, role, lower bound for the degree) with respect to a subject individual.
|
|
13
|
+
"""
|
|
14
|
+
|
|
11
15
|
def __init__(
|
|
12
16
|
self, role_name: str, ind1: Individual, ind2: Individual, degree: Degree
|
|
13
17
|
):
|
|
@@ -38,6 +42,7 @@ class Relation:
|
|
|
38
42
|
return self.degree
|
|
39
43
|
|
|
40
44
|
def get_name_without_degree(self) -> str:
|
|
45
|
+
"""Gets a printable name of the role assertion without the lower bound"""
|
|
41
46
|
return f"({self.ind_a}, {self.ind_b}): {self.role_name}"
|
|
42
47
|
|
|
43
48
|
def __repr__(self) -> str:
|
|
@@ -5,6 +5,8 @@ from fuzzy_dl_owl2.fuzzydl.restriction.restriction import Restriction
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class HasValueRestriction(Restriction):
|
|
8
|
+
"""Universal restriction formed by a role, a individual and a lower bound degree."""
|
|
9
|
+
|
|
8
10
|
def __init__(self, role_name: str, individual: str, degree: Degree) -> None:
|
|
9
11
|
super().__init__(role_name, None, degree)
|
|
10
12
|
self.ind_name: str = individual
|
|
@@ -7,6 +7,8 @@ from fuzzy_dl_owl2.fuzzydl.degree.degree import Degree
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class Restriction:
|
|
10
|
+
"""Universal restriction formed by a role, a concept and a lower bound degree."""
|
|
11
|
+
|
|
10
12
|
def __init__(self, role_name: str, concept: Concept, degree: Degree) -> None:
|
|
11
13
|
self.role_name: str = role_name
|
|
12
14
|
self.concept: Concept = concept
|
|
@@ -25,6 +27,7 @@ class Restriction:
|
|
|
25
27
|
return self.concept
|
|
26
28
|
|
|
27
29
|
def get_name_without_degree(self) -> str:
|
|
30
|
+
"""Gets the name of the restriction without the degree."""
|
|
28
31
|
return f"(all {self.role_name} {self.concept})"
|
|
29
32
|
|
|
30
33
|
def __repr__(self) -> str:
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
class RoleParentWithDegree:
|
|
2
|
+
"""
|
|
3
|
+
Pair of elements (role, degree in [0,1]).
|
|
4
|
+
Given a role, represents a role parent and the inclusion degree.
|
|
5
|
+
"""
|
|
6
|
+
|
|
2
7
|
def __init__(self, parent: str, degree: float) -> None:
|
|
3
|
-
self.degree: float = degree
|
|
4
8
|
self.parent: str = parent
|
|
9
|
+
self.degree: float = degree
|
|
5
10
|
|
|
6
11
|
def get_degree(self) -> float:
|
|
7
12
|
return self.degree
|
|
@@ -1,42 +1,32 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import configparser
|
|
4
|
-
import enum
|
|
5
4
|
import math
|
|
6
5
|
|
|
7
6
|
from fuzzy_dl_owl2.fuzzydl.util import constants
|
|
8
7
|
|
|
9
8
|
|
|
10
|
-
class MILPProvider(enum.StrEnum):
|
|
11
|
-
GUROBI = enum.auto()
|
|
12
|
-
MIP = enum.auto()
|
|
13
|
-
# SCIPY = enum.auto()
|
|
14
|
-
PULP = enum.auto()
|
|
15
|
-
PULP_GLPK = enum.auto()
|
|
16
|
-
PULP_HIGHS = enum.auto()
|
|
17
|
-
PULP_CPLEX = enum.auto()
|
|
18
|
-
|
|
19
|
-
@staticmethod
|
|
20
|
-
def from_str(value: str) -> MILPProvider:
|
|
21
|
-
try:
|
|
22
|
-
return MILPProvider(value.lower())
|
|
23
|
-
except ValueError:
|
|
24
|
-
raise ValueError(
|
|
25
|
-
f"Invalid MILP provider: {value}. Valid options are: {list(MILPProvider)}"
|
|
26
|
-
)
|
|
27
|
-
|
|
28
|
-
|
|
29
9
|
class ConfigReader:
|
|
10
|
+
# Anywhere pairwise blocking applied. false disables anywhere double blocking; true enables anywher edouble blocking.
|
|
30
11
|
ANYWHERE_DOUBLE_BLOCKING: bool = True
|
|
12
|
+
# Anywhere simple blocking applied. false disables anywhere simple blocking; true enables anywhere simple blocking.
|
|
31
13
|
ANYWHERE_SIMPLE_BLOCKING: bool = True
|
|
14
|
+
# Debugging mode
|
|
32
15
|
DEBUG_PRINT: bool = True
|
|
16
|
+
# Precision of the reasoner
|
|
33
17
|
EPSILON: float = 0.001
|
|
18
|
+
# Maximum number of new individuals that will be created
|
|
34
19
|
MAX_INDIVIDUALS: int = -1
|
|
20
|
+
# Number of digits of precision
|
|
35
21
|
NUMBER_DIGITS: int = 2
|
|
22
|
+
# Level of the optimizations applied. 0 disables optimizations; a positive value enables optimizations.
|
|
36
23
|
OPTIMIZATIONS: int = 1
|
|
24
|
+
# Rule acyclic TBox optimization applied
|
|
37
25
|
RULE_ACYCLIC_TBOXES: bool = True
|
|
26
|
+
# XML OWL 2 annotation label used to create and parse Fuzzy OWL 2 ontologies
|
|
38
27
|
OWL_ANNOTATION_LABEL: str = "fuzzyLabel"
|
|
39
|
-
|
|
28
|
+
# MILP Solver provider used by the reasoner
|
|
29
|
+
MILP_PROVIDER: constants.MILPProvider = constants.MILPProvider.GUROBI
|
|
40
30
|
|
|
41
31
|
@staticmethod
|
|
42
32
|
def load_parameters(config_file: str, args: list[str]) -> None:
|
|
@@ -62,22 +52,22 @@ class ConfigReader:
|
|
|
62
52
|
ConfigReader.OWL_ANNOTATION_LABEL = config.get(
|
|
63
53
|
"DEFAULT", "owlAnnotationLabel"
|
|
64
54
|
)
|
|
65
|
-
ConfigReader.MILP_PROVIDER = MILPProvider(
|
|
55
|
+
ConfigReader.MILP_PROVIDER = constants.MILPProvider(
|
|
66
56
|
config.get("DEFAULT", "milpProvider").lower()
|
|
67
57
|
)
|
|
68
58
|
ConfigReader.NUMBER_DIGITS = int(
|
|
69
59
|
round(abs(math.log10(ConfigReader.EPSILON) - 1.0))
|
|
70
60
|
)
|
|
71
61
|
if ConfigReader.MILP_PROVIDER in [
|
|
72
|
-
MILPProvider.MIP,
|
|
73
|
-
MILPProvider.PULP,
|
|
62
|
+
constants.MILPProvider.MIP,
|
|
63
|
+
constants.MILPProvider.PULP,
|
|
74
64
|
]:
|
|
75
65
|
constants.MAXVAL = (1 << 31) - 1
|
|
76
66
|
constants.MAXVAL2 = constants.MAXVAL * 2
|
|
77
67
|
elif ConfigReader.MILP_PROVIDER in [
|
|
78
|
-
MILPProvider.PULP_GLPK,
|
|
79
|
-
MILPProvider.PULP_HIGHS,
|
|
80
|
-
MILPProvider.PULP_CPLEX,
|
|
68
|
+
constants.MILPProvider.PULP_GLPK,
|
|
69
|
+
constants.MILPProvider.PULP_HIGHS,
|
|
70
|
+
constants.MILPProvider.PULP_CPLEX,
|
|
81
71
|
# MILPProvider.SCIPY,
|
|
82
72
|
]:
|
|
83
73
|
constants.MAXVAL = (1 << 28) - 1
|