fuzzy-dl-owl2 1.0.0__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/__init__.py +2 -0
- fuzzy_dl_owl2/fuzzydl/__init__.py +23 -0
- fuzzy_dl_owl2/fuzzydl/assertion/__init__.py +2 -0
- fuzzy_dl_owl2/fuzzydl/assertion/assertion.py +72 -0
- fuzzy_dl_owl2/fuzzydl/assertion/atomic_assertion.py +19 -0
- fuzzy_dl_owl2/fuzzydl/concept/__init__.py +13 -0
- fuzzy_dl_owl2/fuzzydl/concept/all_some_concept.py +85 -0
- fuzzy_dl_owl2/fuzzydl/concept/approximation_concept.py +147 -0
- fuzzy_dl_owl2/fuzzydl/concept/atomic_concept.py +91 -0
- fuzzy_dl_owl2/fuzzydl/concept/choquet_integral.py +64 -0
- fuzzy_dl_owl2/fuzzydl/concept/concept.py +230 -0
- fuzzy_dl_owl2/fuzzydl/concept/concrete/__init__.py +10 -0
- fuzzy_dl_owl2/fuzzydl/concept/concrete/crisp_concrete_concept.py +60 -0
- fuzzy_dl_owl2/fuzzydl/concept/concrete/fuzzy_concrete_concept.py +63 -0
- fuzzy_dl_owl2/fuzzydl/concept/concrete/fuzzy_number/__init__.py +1 -0
- fuzzy_dl_owl2/fuzzydl/concept/concrete/fuzzy_number/triangular_fuzzy_number.py +127 -0
- fuzzy_dl_owl2/fuzzydl/concept/concrete/left_concrete_concept.py +70 -0
- fuzzy_dl_owl2/fuzzydl/concept/concrete/linear_concrete_concept.py +70 -0
- fuzzy_dl_owl2/fuzzydl/concept/concrete/modified_concrete_concept.py +66 -0
- fuzzy_dl_owl2/fuzzydl/concept/concrete/right_concrete_concept.py +70 -0
- fuzzy_dl_owl2/fuzzydl/concept/concrete/trapezoidal_concrete_concept.py +96 -0
- fuzzy_dl_owl2/fuzzydl/concept/concrete/triangular_concrete_concept.py +89 -0
- fuzzy_dl_owl2/fuzzydl/concept/ext_threshold_concept.py +77 -0
- fuzzy_dl_owl2/fuzzydl/concept/has_value_concept.py +51 -0
- fuzzy_dl_owl2/fuzzydl/concept/implies_concept.py +144 -0
- fuzzy_dl_owl2/fuzzydl/concept/interface/__init__.py +6 -0
- fuzzy_dl_owl2/fuzzydl/concept/interface/has_concept_interface.py +17 -0
- fuzzy_dl_owl2/fuzzydl/concept/interface/has_concepts_interface.py +18 -0
- fuzzy_dl_owl2/fuzzydl/concept/interface/has_role_concept_interface.py +14 -0
- fuzzy_dl_owl2/fuzzydl/concept/interface/has_role_interface.py +15 -0
- fuzzy_dl_owl2/fuzzydl/concept/interface/has_value_interface.py +21 -0
- fuzzy_dl_owl2/fuzzydl/concept/interface/has_weighted_concepts_interface.py +29 -0
- fuzzy_dl_owl2/fuzzydl/concept/modified/__init__.py +3 -0
- fuzzy_dl_owl2/fuzzydl/concept/modified/linearly_modified_concept.py +32 -0
- fuzzy_dl_owl2/fuzzydl/concept/modified/modified_concept.py +59 -0
- fuzzy_dl_owl2/fuzzydl/concept/modified/triangularly_modified_concept.py +33 -0
- fuzzy_dl_owl2/fuzzydl/concept/negated_nominal.py +42 -0
- fuzzy_dl_owl2/fuzzydl/concept/operator_concept.py +707 -0
- fuzzy_dl_owl2/fuzzydl/concept/owa_concept.py +57 -0
- fuzzy_dl_owl2/fuzzydl/concept/qowa_concept.py +62 -0
- fuzzy_dl_owl2/fuzzydl/concept/quasi_sugeno_integral.py +46 -0
- fuzzy_dl_owl2/fuzzydl/concept/self_concept.py +45 -0
- fuzzy_dl_owl2/fuzzydl/concept/string_concept.py +35 -0
- fuzzy_dl_owl2/fuzzydl/concept/sugeno_integral.py +83 -0
- fuzzy_dl_owl2/fuzzydl/concept/threshold_concept.py +81 -0
- fuzzy_dl_owl2/fuzzydl/concept/truth_concept.py +83 -0
- fuzzy_dl_owl2/fuzzydl/concept/value_concept.py +67 -0
- fuzzy_dl_owl2/fuzzydl/concept/weighted_concept.py +55 -0
- fuzzy_dl_owl2/fuzzydl/concept/weighted_max_concept.py +63 -0
- fuzzy_dl_owl2/fuzzydl/concept/weighted_min_concept.py +57 -0
- fuzzy_dl_owl2/fuzzydl/concept/weighted_sum_concept.py +62 -0
- fuzzy_dl_owl2/fuzzydl/concept/weighted_sum_zero_concept.py +62 -0
- fuzzy_dl_owl2/fuzzydl/concept_equivalence.py +20 -0
- fuzzy_dl_owl2/fuzzydl/concrete_feature.py +94 -0
- fuzzy_dl_owl2/fuzzydl/degree/__init__.py +4 -0
- fuzzy_dl_owl2/fuzzydl/degree/degree.py +79 -0
- fuzzy_dl_owl2/fuzzydl/degree/degree_expression.py +57 -0
- fuzzy_dl_owl2/fuzzydl/degree/degree_numeric.py +57 -0
- fuzzy_dl_owl2/fuzzydl/degree/degree_variable.py +54 -0
- fuzzy_dl_owl2/fuzzydl/domain_axiom.py +8 -0
- fuzzy_dl_owl2/fuzzydl/exception/__init__.py +2 -0
- fuzzy_dl_owl2/fuzzydl/exception/fuzzy_ontology_exception.py +4 -0
- fuzzy_dl_owl2/fuzzydl/exception/inconsistent_ontology_exception.py +4 -0
- fuzzy_dl_owl2/fuzzydl/feature_function.py +148 -0
- fuzzy_dl_owl2/fuzzydl/fuzzydl_to_owl2.py +920 -0
- fuzzy_dl_owl2/fuzzydl/fuzzydl_to_owl2_java.py +953 -0
- fuzzy_dl_owl2/fuzzydl/general_concept_inclusion.py +82 -0
- fuzzy_dl_owl2/fuzzydl/individual/__init__.py +3 -0
- fuzzy_dl_owl2/fuzzydl/individual/created_individual.py +219 -0
- fuzzy_dl_owl2/fuzzydl/individual/individual.py +113 -0
- fuzzy_dl_owl2/fuzzydl/individual/representative_individual.py +37 -0
- fuzzy_dl_owl2/fuzzydl/knowledge_base.py +9037 -0
- fuzzy_dl_owl2/fuzzydl/label.py +32 -0
- fuzzy_dl_owl2/fuzzydl/milp/__init__.py +7 -0
- fuzzy_dl_owl2/fuzzydl/milp/expression.py +186 -0
- fuzzy_dl_owl2/fuzzydl/milp/inequation.py +55 -0
- fuzzy_dl_owl2/fuzzydl/milp/milp_helper.py +787 -0
- fuzzy_dl_owl2/fuzzydl/milp/show_variables_helper.py +151 -0
- fuzzy_dl_owl2/fuzzydl/milp/solution.py +45 -0
- fuzzy_dl_owl2/fuzzydl/milp/term.py +76 -0
- fuzzy_dl_owl2/fuzzydl/milp/variable.py +89 -0
- fuzzy_dl_owl2/fuzzydl/modifier/__init__.py +3 -0
- fuzzy_dl_owl2/fuzzydl/modifier/linear_modifier.py +76 -0
- fuzzy_dl_owl2/fuzzydl/modifier/modifier.py +39 -0
- fuzzy_dl_owl2/fuzzydl/modifier/triangular_modifier.py +76 -0
- fuzzy_dl_owl2/fuzzydl/parser/ParserConstants.py +406 -0
- fuzzy_dl_owl2/fuzzydl/parser/__init__.py +1 -0
- fuzzy_dl_owl2/fuzzydl/parser/dl_parser.py +2029 -0
- fuzzy_dl_owl2/fuzzydl/parser/ebnf.lark +290 -0
- fuzzy_dl_owl2/fuzzydl/parser/larkx.py +70 -0
- fuzzy_dl_owl2/fuzzydl/primitive_concept_definition.py +81 -0
- fuzzy_dl_owl2/fuzzydl/query/__init__.py +14 -0
- fuzzy_dl_owl2/fuzzydl/query/all_instances_query.py +50 -0
- fuzzy_dl_owl2/fuzzydl/query/bnp_query.py +22 -0
- fuzzy_dl_owl2/fuzzydl/query/defuzzify/__init__.py +4 -0
- fuzzy_dl_owl2/fuzzydl/query/defuzzify/defuzzify_query.py +76 -0
- fuzzy_dl_owl2/fuzzydl/query/defuzzify/lom_defuzzify_query.py +19 -0
- fuzzy_dl_owl2/fuzzydl/query/defuzzify/mom_defuzzify_query.py +88 -0
- fuzzy_dl_owl2/fuzzydl/query/defuzzify/som_defuzzify_query.py +20 -0
- fuzzy_dl_owl2/fuzzydl/query/instance_query.py +19 -0
- fuzzy_dl_owl2/fuzzydl/query/kb_satisfiable_query.py +32 -0
- fuzzy_dl_owl2/fuzzydl/query/max/__init__.py +5 -0
- fuzzy_dl_owl2/fuzzydl/query/max/max_instance_query.py +45 -0
- fuzzy_dl_owl2/fuzzydl/query/max/max_query.py +31 -0
- fuzzy_dl_owl2/fuzzydl/query/max/max_related_query.py +45 -0
- fuzzy_dl_owl2/fuzzydl/query/max/max_satisfiable_query.py +73 -0
- fuzzy_dl_owl2/fuzzydl/query/max/max_subsumes_query.py +64 -0
- fuzzy_dl_owl2/fuzzydl/query/min/__init__.py +5 -0
- fuzzy_dl_owl2/fuzzydl/query/min/min_instance_query.py +50 -0
- fuzzy_dl_owl2/fuzzydl/query/min/min_query.py +31 -0
- fuzzy_dl_owl2/fuzzydl/query/min/min_related_query.py +57 -0
- fuzzy_dl_owl2/fuzzydl/query/min/min_satisfiable_query.py +80 -0
- fuzzy_dl_owl2/fuzzydl/query/min/min_subsumes_query.py +65 -0
- fuzzy_dl_owl2/fuzzydl/query/query.py +38 -0
- fuzzy_dl_owl2/fuzzydl/query/related_query.py +15 -0
- fuzzy_dl_owl2/fuzzydl/query/satisfiable_query.py +37 -0
- fuzzy_dl_owl2/fuzzydl/query/subsumption_query.py +20 -0
- fuzzy_dl_owl2/fuzzydl/range_axiom.py +7 -0
- fuzzy_dl_owl2/fuzzydl/relation.py +47 -0
- fuzzy_dl_owl2/fuzzydl/restriction/__init__.py +2 -0
- fuzzy_dl_owl2/fuzzydl/restriction/has_value_restriction.py +16 -0
- fuzzy_dl_owl2/fuzzydl/restriction/restriction.py +34 -0
- fuzzy_dl_owl2/fuzzydl/role_parent_with_degree.py +10 -0
- fuzzy_dl_owl2/fuzzydl/util/__init__.py +3 -0
- fuzzy_dl_owl2/fuzzydl/util/config_reader.py +56 -0
- fuzzy_dl_owl2/fuzzydl/util/constants.py +424 -0
- fuzzy_dl_owl2/fuzzydl/util/util.py +73 -0
- fuzzy_dl_owl2/fuzzyowl2/__init__.py +5 -0
- fuzzy_dl_owl2/fuzzyowl2/fuzzyowl2.py +1513 -0
- fuzzy_dl_owl2/fuzzyowl2/fuzzyowl2_java.py +1409 -0
- fuzzy_dl_owl2/fuzzyowl2/fuzzyowl2_to_fuzzydl.py +917 -0
- fuzzy_dl_owl2/fuzzyowl2/fuzzyowl2_to_fuzzydl_java.py +956 -0
- fuzzy_dl_owl2/fuzzyowl2/owl_types/__init__.py +0 -0
- fuzzy_dl_owl2/fuzzyowl2/owl_types/choquet_concept.py +19 -0
- fuzzy_dl_owl2/fuzzyowl2/owl_types/concept_definition.py +14 -0
- fuzzy_dl_owl2/fuzzyowl2/owl_types/fuzzy_datatype.py +22 -0
- fuzzy_dl_owl2/fuzzyowl2/owl_types/fuzzy_modifier.py +4 -0
- fuzzy_dl_owl2/fuzzyowl2/owl_types/fuzzy_nominal_concept.py +19 -0
- fuzzy_dl_owl2/fuzzyowl2/owl_types/fuzzy_property.py +5 -0
- fuzzy_dl_owl2/fuzzyowl2/owl_types/left_shoulder_function.py +17 -0
- fuzzy_dl_owl2/fuzzyowl2/owl_types/linear_function.py +17 -0
- fuzzy_dl_owl2/fuzzyowl2/owl_types/linear_modifier.py +13 -0
- fuzzy_dl_owl2/fuzzyowl2/owl_types/modified_concept.py +19 -0
- fuzzy_dl_owl2/fuzzyowl2/owl_types/modified_function.py +17 -0
- fuzzy_dl_owl2/fuzzyowl2/owl_types/modified_property.py +15 -0
- fuzzy_dl_owl2/fuzzyowl2/owl_types/owa_concept.py +19 -0
- fuzzy_dl_owl2/fuzzyowl2/owl_types/property_definition.py +10 -0
- fuzzy_dl_owl2/fuzzyowl2/owl_types/qowa_concept.py +19 -0
- fuzzy_dl_owl2/fuzzyowl2/owl_types/quasi_sugeno_concept.py +21 -0
- fuzzy_dl_owl2/fuzzyowl2/owl_types/right_shoulder_function.py +17 -0
- fuzzy_dl_owl2/fuzzyowl2/owl_types/sugeno_concept.py +21 -0
- fuzzy_dl_owl2/fuzzyowl2/owl_types/trapezoidal_function.py +25 -0
- fuzzy_dl_owl2/fuzzyowl2/owl_types/triangular_function.py +21 -0
- fuzzy_dl_owl2/fuzzyowl2/owl_types/triangular_modifer.py +21 -0
- fuzzy_dl_owl2/fuzzyowl2/owl_types/weighted_concept.py +19 -0
- fuzzy_dl_owl2/fuzzyowl2/owl_types/weighted_max_concept.py +15 -0
- fuzzy_dl_owl2/fuzzyowl2/owl_types/weighted_min_concept.py +15 -0
- fuzzy_dl_owl2/fuzzyowl2/owl_types/weighted_sum_concept.py +15 -0
- fuzzy_dl_owl2/fuzzyowl2/owl_types/weighted_sum_zero_concept.py +15 -0
- fuzzy_dl_owl2/fuzzyowl2/parser/__init__.py +1 -0
- fuzzy_dl_owl2/fuzzyowl2/parser/owl2_parser.py +491 -0
- fuzzy_dl_owl2/fuzzyowl2/util/__init__.py +1 -0
- fuzzy_dl_owl2/fuzzyowl2/util/constants.py +112 -0
- fuzzy_dl_owl2-1.0.0.dist-info/LICENSE +427 -0
- fuzzy_dl_owl2-1.0.0.dist-info/METADATA +299 -0
- fuzzy_dl_owl2-1.0.0.dist-info/RECORD +167 -0
- fuzzy_dl_owl2-1.0.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,787 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import copy
|
|
4
|
+
import os
|
|
5
|
+
import typing
|
|
6
|
+
|
|
7
|
+
import gurobipy as gp
|
|
8
|
+
from gurobipy import GRB
|
|
9
|
+
|
|
10
|
+
from fuzzy_dl_owl2.fuzzydl.assertion.assertion import Assertion
|
|
11
|
+
from fuzzy_dl_owl2.fuzzydl.concept.concept import Concept
|
|
12
|
+
from fuzzy_dl_owl2.fuzzydl.concept.interface.has_value_interface import (
|
|
13
|
+
HasValueInterface,
|
|
14
|
+
)
|
|
15
|
+
from fuzzy_dl_owl2.fuzzydl.degree.degree import Degree
|
|
16
|
+
from fuzzy_dl_owl2.fuzzydl.degree.degree_numeric import DegreeNumeric
|
|
17
|
+
from fuzzy_dl_owl2.fuzzydl.degree.degree_variable import DegreeVariable
|
|
18
|
+
from fuzzy_dl_owl2.fuzzydl.individual.created_individual import CreatedIndividual
|
|
19
|
+
from fuzzy_dl_owl2.fuzzydl.individual.individual import Individual
|
|
20
|
+
from fuzzy_dl_owl2.fuzzydl.milp.expression import Expression
|
|
21
|
+
from fuzzy_dl_owl2.fuzzydl.milp.inequation import Inequation
|
|
22
|
+
from fuzzy_dl_owl2.fuzzydl.milp.show_variables_helper import ShowVariablesHelper
|
|
23
|
+
from fuzzy_dl_owl2.fuzzydl.milp.solution import Solution
|
|
24
|
+
from fuzzy_dl_owl2.fuzzydl.milp.term import Term
|
|
25
|
+
from fuzzy_dl_owl2.fuzzydl.milp.variable import Variable
|
|
26
|
+
from fuzzy_dl_owl2.fuzzydl.relation import Relation
|
|
27
|
+
from fuzzy_dl_owl2.fuzzydl.restriction.restriction import Restriction
|
|
28
|
+
from fuzzy_dl_owl2.fuzzydl.util import constants
|
|
29
|
+
from fuzzy_dl_owl2.fuzzydl.util.config_reader import ConfigReader
|
|
30
|
+
from fuzzy_dl_owl2.fuzzydl.util.constants import (
|
|
31
|
+
ConceptType,
|
|
32
|
+
InequalityType,
|
|
33
|
+
VariableType,
|
|
34
|
+
)
|
|
35
|
+
from fuzzy_dl_owl2.fuzzydl.util.util import Util
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# @utils.singleton
|
|
39
|
+
class MILPHelper:
|
|
40
|
+
PRINT_LABELS: bool = True
|
|
41
|
+
PRINT_VARIABLES: bool = True
|
|
42
|
+
|
|
43
|
+
def __init__(self) -> None:
|
|
44
|
+
self.constraints: list[Inequation] = list()
|
|
45
|
+
self.crisp_concepts: set[str] = set()
|
|
46
|
+
self.crisp_roles: set[str] = set()
|
|
47
|
+
self.number_of_variables: dict[str, int] = dict()
|
|
48
|
+
self.show_vars: ShowVariablesHelper = ShowVariablesHelper()
|
|
49
|
+
self.string_features: set[str] = set()
|
|
50
|
+
self.string_values: dict[int, str] = dict()
|
|
51
|
+
self.variables: list[Variable] = []
|
|
52
|
+
|
|
53
|
+
def clone(self) -> typing.Self:
|
|
54
|
+
milp: MILPHelper = MILPHelper()
|
|
55
|
+
milp.constraints = [c.clone() for c in self.constraints]
|
|
56
|
+
milp.crisp_concepts = copy.deepcopy(self.crisp_concepts)
|
|
57
|
+
milp.crisp_roles = copy.deepcopy(self.crisp_roles)
|
|
58
|
+
milp.number_of_variables = copy.deepcopy(self.number_of_variables)
|
|
59
|
+
milp.show_vars = self.show_vars.clone()
|
|
60
|
+
milp.string_features = copy.deepcopy(self.string_features)
|
|
61
|
+
milp.string_values = copy.deepcopy(self.string_values)
|
|
62
|
+
milp.variables = [v.clone() for v in self.variables]
|
|
63
|
+
return milp
|
|
64
|
+
|
|
65
|
+
def optimize(self, objective: Expression) -> Solution:
|
|
66
|
+
return self.solve_gurobi(objective)
|
|
67
|
+
|
|
68
|
+
@typing.overload
|
|
69
|
+
def print_instance_of_labels(
|
|
70
|
+
self, f_name: str, ind_name: str, value: float
|
|
71
|
+
) -> None: ...
|
|
72
|
+
|
|
73
|
+
@typing.overload
|
|
74
|
+
def print_instance_of_labels(self, name: str, value: float) -> None: ...
|
|
75
|
+
|
|
76
|
+
def print_instance_of_labels(self, *args) -> None:
|
|
77
|
+
assert len(args) in [2, 3]
|
|
78
|
+
assert isinstance(args[0], str)
|
|
79
|
+
if len(args) == 2:
|
|
80
|
+
assert isinstance(args[1], constants.NUMBER)
|
|
81
|
+
self.__print_instance_of_labels_2(*args)
|
|
82
|
+
else:
|
|
83
|
+
assert isinstance(args[1], str)
|
|
84
|
+
assert isinstance(args[2], constants.NUMBER)
|
|
85
|
+
self.__print_instance_of_labels_1(*args)
|
|
86
|
+
|
|
87
|
+
def __print_instance_of_labels_1(
|
|
88
|
+
self, f_name: str, ind_name: str, value: float
|
|
89
|
+
) -> None:
|
|
90
|
+
name = f"{f_name}({ind_name})"
|
|
91
|
+
labels = self.show_vars.get_labels(name)
|
|
92
|
+
for f in labels:
|
|
93
|
+
Util.info(
|
|
94
|
+
f"{name} is {f.compute_name()} = {f.get_membership_degree(value)}"
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
def __print_instance_of_labels_2(self, name: str, value: float) -> None:
|
|
98
|
+
labels = self.show_vars.get_labels(name)
|
|
99
|
+
for f in labels:
|
|
100
|
+
Util.info(
|
|
101
|
+
f"{name} is {f.compute_name()} = {f.get_membership_degree(value)}"
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
def get_new_variable(self, v_type: VariableType) -> Variable:
|
|
105
|
+
while True:
|
|
106
|
+
new_var: Variable = Variable.get_new_variable(v_type)
|
|
107
|
+
var_name = str(new_var)
|
|
108
|
+
if var_name not in self.number_of_variables:
|
|
109
|
+
break
|
|
110
|
+
|
|
111
|
+
self.variables.append(new_var)
|
|
112
|
+
self.number_of_variables[var_name] = len(self.variables)
|
|
113
|
+
return new_var
|
|
114
|
+
|
|
115
|
+
@typing.overload
|
|
116
|
+
def get_variable(self, var_name: str) -> Variable: ...
|
|
117
|
+
|
|
118
|
+
@typing.overload
|
|
119
|
+
def get_variable(self, var_name: str, v_type: VariableType) -> Variable: ...
|
|
120
|
+
|
|
121
|
+
@typing.overload
|
|
122
|
+
def get_variable(self, ass: Assertion) -> Variable: ...
|
|
123
|
+
|
|
124
|
+
@typing.overload
|
|
125
|
+
def get_variable(self, rel: Relation) -> Variable: ...
|
|
126
|
+
|
|
127
|
+
@typing.overload
|
|
128
|
+
def get_variable(self, ind: Individual, restrict: Restriction) -> Variable: ...
|
|
129
|
+
|
|
130
|
+
@typing.overload
|
|
131
|
+
def get_variable(self, ind: Individual, c: Concept) -> Variable: ...
|
|
132
|
+
|
|
133
|
+
@typing.overload
|
|
134
|
+
def get_variable(self, ind: Individual, concept_name: str) -> Variable: ...
|
|
135
|
+
|
|
136
|
+
@typing.overload
|
|
137
|
+
def get_variable(self, a: Individual, b: Individual, role: str) -> Variable: ...
|
|
138
|
+
|
|
139
|
+
@typing.overload
|
|
140
|
+
def get_variable(
|
|
141
|
+
self, a: Individual, b: Individual, role: str, v_type: VariableType
|
|
142
|
+
) -> Variable: ...
|
|
143
|
+
|
|
144
|
+
@typing.overload
|
|
145
|
+
def get_variable(
|
|
146
|
+
self, a: str, b: str, role: str, v_type: VariableType
|
|
147
|
+
) -> Variable: ...
|
|
148
|
+
|
|
149
|
+
@typing.overload
|
|
150
|
+
def get_variable(self, ind: CreatedIndividual) -> Variable: ...
|
|
151
|
+
|
|
152
|
+
@typing.overload
|
|
153
|
+
def get_variable(self, ind: CreatedIndividual, v_type: VariableType) -> None: ...
|
|
154
|
+
|
|
155
|
+
def get_variable(self, *args) -> Variable:
|
|
156
|
+
assert len(args) in [1, 2, 3, 4]
|
|
157
|
+
if len(args) == 1:
|
|
158
|
+
if isinstance(args[0], str):
|
|
159
|
+
return self.__get_variable_1(*args)
|
|
160
|
+
elif isinstance(args[0], Assertion):
|
|
161
|
+
return self.__get_variable_3(*args)
|
|
162
|
+
elif isinstance(args[0], Relation):
|
|
163
|
+
return self.__get_variable_4(*args)
|
|
164
|
+
elif isinstance(args[0], CreatedIndividual):
|
|
165
|
+
return self.__get_variable_11(*args)
|
|
166
|
+
else:
|
|
167
|
+
raise ValueError
|
|
168
|
+
elif len(args) == 2:
|
|
169
|
+
if isinstance(args[0], str) and isinstance(args[1], VariableType):
|
|
170
|
+
return self.__get_variable_2(*args)
|
|
171
|
+
elif isinstance(args[0], Individual) and isinstance(args[1], Restriction):
|
|
172
|
+
return self.__get_variable_5(*args)
|
|
173
|
+
elif isinstance(args[0], Individual) and isinstance(args[1], Concept):
|
|
174
|
+
return self.__get_variable_6(*args)
|
|
175
|
+
elif isinstance(args[0], CreatedIndividual) and isinstance(
|
|
176
|
+
args[1], VariableType
|
|
177
|
+
):
|
|
178
|
+
return self.__get_variable_12(*args)
|
|
179
|
+
elif isinstance(args[0], Individual) and isinstance(args[1], str):
|
|
180
|
+
return self.__get_variable_7(*args)
|
|
181
|
+
else:
|
|
182
|
+
raise ValueError
|
|
183
|
+
elif len(args) == 3:
|
|
184
|
+
if (
|
|
185
|
+
isinstance(args[0], Individual)
|
|
186
|
+
and isinstance(args[1], Individual)
|
|
187
|
+
and isinstance(args[2], str)
|
|
188
|
+
):
|
|
189
|
+
return self.__get_variable_8(*args)
|
|
190
|
+
else:
|
|
191
|
+
raise ValueError
|
|
192
|
+
elif len(args) == 4:
|
|
193
|
+
if (
|
|
194
|
+
isinstance(args[0], Individual)
|
|
195
|
+
and isinstance(args[1], Individual)
|
|
196
|
+
and isinstance(args[2], str)
|
|
197
|
+
and isinstance(args[3], VariableType)
|
|
198
|
+
):
|
|
199
|
+
return self.__get_variable_9(*args)
|
|
200
|
+
elif (
|
|
201
|
+
isinstance(args[0], str)
|
|
202
|
+
and isinstance(args[1], str)
|
|
203
|
+
and isinstance(args[2], str)
|
|
204
|
+
and isinstance(args[3], VariableType)
|
|
205
|
+
):
|
|
206
|
+
return self.__get_variable_10(*args)
|
|
207
|
+
else:
|
|
208
|
+
raise ValueError
|
|
209
|
+
else:
|
|
210
|
+
raise ValueError
|
|
211
|
+
|
|
212
|
+
def __get_variable_1(self, var_name: str) -> Variable:
|
|
213
|
+
if var_name in self.number_of_variables:
|
|
214
|
+
for variable in self.variables:
|
|
215
|
+
if str(variable) == var_name:
|
|
216
|
+
return variable
|
|
217
|
+
var: Variable = Variable(var_name, VariableType.SEMI_CONTINUOUS)
|
|
218
|
+
self.variables.append(var)
|
|
219
|
+
self.number_of_variables[str(var)] = len(self.variables)
|
|
220
|
+
return var
|
|
221
|
+
|
|
222
|
+
def __get_variable_2(self, var_name: str, v_type: VariableType) -> Variable:
|
|
223
|
+
var: Variable = self.get_variable(var_name)
|
|
224
|
+
var.set_type(v_type)
|
|
225
|
+
return var
|
|
226
|
+
|
|
227
|
+
def __get_variable_3(self, ass: Assertion) -> Variable:
|
|
228
|
+
return self.get_variable(ass.get_individual(), ass.get_concept())
|
|
229
|
+
|
|
230
|
+
def __get_variable_4(self, rel: Relation) -> Variable:
|
|
231
|
+
a: Individual = rel.get_subject_individual()
|
|
232
|
+
b: Individual = rel.get_object_individual()
|
|
233
|
+
role: str = rel.get_role_name()
|
|
234
|
+
return self.get_variable(a, b, role)
|
|
235
|
+
|
|
236
|
+
def __get_variable_5(self, ind: Individual, restrict: Restriction) -> Variable:
|
|
237
|
+
var: Variable = self.get_variable(f"{ind}:{restrict.get_name_without_degree()}")
|
|
238
|
+
if self.show_vars.show_individuals(str(ind)):
|
|
239
|
+
self.show_vars.add_variable(var, str(var))
|
|
240
|
+
return var
|
|
241
|
+
|
|
242
|
+
def __get_variable_6(self, ind: Individual, c: Concept) -> Variable:
|
|
243
|
+
if c.type == ConceptType.HAS_VALUE:
|
|
244
|
+
assert isinstance(c, HasValueInterface)
|
|
245
|
+
|
|
246
|
+
r: str = c.role
|
|
247
|
+
b: str = str(c.value)
|
|
248
|
+
return self.get_variable(str(ind), b, r, VariableType.SEMI_CONTINUOUS)
|
|
249
|
+
return self.get_variable(ind, str(c))
|
|
250
|
+
|
|
251
|
+
def __get_variable_7(self, ind: Individual, concept_name: str) -> Variable:
|
|
252
|
+
var: Variable = self.get_variable(f"{ind}:{concept_name}")
|
|
253
|
+
if concept_name in self.crisp_concepts:
|
|
254
|
+
var.set_binary_variable()
|
|
255
|
+
if self.show_vars.show_individuals(str(ind)) or self.show_vars.show_concepts(
|
|
256
|
+
concept_name
|
|
257
|
+
):
|
|
258
|
+
self.show_vars.add_variable(var, str(var))
|
|
259
|
+
return var
|
|
260
|
+
|
|
261
|
+
def __get_variable_8(self, a: Individual, b: Individual, role: str) -> Variable:
|
|
262
|
+
return self.get_variable(a, b, role, VariableType.SEMI_CONTINUOUS)
|
|
263
|
+
|
|
264
|
+
def __get_variable_9(
|
|
265
|
+
self, a: Individual, b: Individual, role: str, v_type: VariableType
|
|
266
|
+
) -> Variable:
|
|
267
|
+
return self.get_variable(str(a), str(b), role, v_type)
|
|
268
|
+
|
|
269
|
+
def __get_variable_10(
|
|
270
|
+
self, a: str, b: str, role: str, v_type: VariableType
|
|
271
|
+
) -> Variable:
|
|
272
|
+
var_name: str = f"({a},{b}):{role}"
|
|
273
|
+
var: Variable = self.get_variable(var_name)
|
|
274
|
+
if role in self.crisp_roles:
|
|
275
|
+
var.set_binary_variable()
|
|
276
|
+
if self.show_vars.show_abstract_role_fillers(
|
|
277
|
+
role, a
|
|
278
|
+
) or self.show_vars.show_concrete_fillers(role, a):
|
|
279
|
+
self.show_vars.add_variable(var, var_name)
|
|
280
|
+
var.set_type(v_type)
|
|
281
|
+
return var
|
|
282
|
+
|
|
283
|
+
def __get_variable_11(self, ind: CreatedIndividual) -> Variable:
|
|
284
|
+
return self.get_variable(ind, VariableType.CONTINUOUS)
|
|
285
|
+
|
|
286
|
+
def __get_variable_12(self, ind: CreatedIndividual, v_type: VariableType) -> None:
|
|
287
|
+
if ind.get_parent() is None:
|
|
288
|
+
parent_name: str = "unknown_parent"
|
|
289
|
+
else:
|
|
290
|
+
parent_name: str = str(ind.get_parent())
|
|
291
|
+
feture_name: str = ind.get_role_name()
|
|
292
|
+
if feture_name is None:
|
|
293
|
+
feture_name = "unknown_feature"
|
|
294
|
+
name: str = f"{feture_name}({parent_name})"
|
|
295
|
+
if name == "unknown_feature(unknown_parent)":
|
|
296
|
+
name = str(ind)
|
|
297
|
+
|
|
298
|
+
if name in self.number_of_variables:
|
|
299
|
+
x_c: Variable = self.get_variable(name)
|
|
300
|
+
else:
|
|
301
|
+
x_c: Variable = self.get_variable(name)
|
|
302
|
+
if self.show_vars.show_concrete_fillers(feture_name, parent_name):
|
|
303
|
+
self.show_vars.add_variable(x_c, name)
|
|
304
|
+
x_c.set_type(v_type)
|
|
305
|
+
return x_c
|
|
306
|
+
|
|
307
|
+
@typing.overload
|
|
308
|
+
def has_variable(self, name: str) -> bool: ...
|
|
309
|
+
|
|
310
|
+
@typing.overload
|
|
311
|
+
def has_variable(self, ass: Assertion) -> bool: ...
|
|
312
|
+
|
|
313
|
+
def has_variable(self, *args) -> bool:
|
|
314
|
+
assert len(args) == 1
|
|
315
|
+
if isinstance(args[0], str):
|
|
316
|
+
return self.__has_variable_1(*args)
|
|
317
|
+
elif isinstance(args[0], Assertion):
|
|
318
|
+
return self.__has_variable_2(*args)
|
|
319
|
+
else:
|
|
320
|
+
raise ValueError
|
|
321
|
+
|
|
322
|
+
def __has_variable_1(self, name: str) -> bool:
|
|
323
|
+
return name in self.number_of_variables
|
|
324
|
+
|
|
325
|
+
def __has_variable_2(self, ass: Assertion) -> bool:
|
|
326
|
+
return self.has_variable(ass.get_name_without_degree())
|
|
327
|
+
|
|
328
|
+
@typing.overload
|
|
329
|
+
def get_nominal_variable(self, i1: str) -> Variable: ...
|
|
330
|
+
|
|
331
|
+
@typing.overload
|
|
332
|
+
def get_nominal_variable(self, i1: str, i2: str) -> Variable: ...
|
|
333
|
+
|
|
334
|
+
def get_nominal_variable(self, *args) -> Variable:
|
|
335
|
+
assert len(args) in [1, 2]
|
|
336
|
+
assert isinstance(args[0], str)
|
|
337
|
+
if len(args) == 1:
|
|
338
|
+
return self.__get_nominal_variable_1(*args)
|
|
339
|
+
else:
|
|
340
|
+
assert isinstance(args[1], str)
|
|
341
|
+
return self.__get_nominal_variable_2(*args)
|
|
342
|
+
|
|
343
|
+
def __get_nominal_variable_1(self, i1: str) -> Variable:
|
|
344
|
+
return self.get_nominal_variable(i1, i1)
|
|
345
|
+
|
|
346
|
+
def __get_nominal_variable_2(self, i1: str, i2: str) -> Variable:
|
|
347
|
+
var_name = f"{i1}:{{ {i2} }}"
|
|
348
|
+
v: Variable = self.get_variable(var_name)
|
|
349
|
+
v.set_type(VariableType.BINARY)
|
|
350
|
+
return v
|
|
351
|
+
|
|
352
|
+
def exists_nominal_variable(self, i: str) -> bool:
|
|
353
|
+
var_name: str = f"{i}:{{ {i} }}"
|
|
354
|
+
return var_name in list(map(str, self.variables))
|
|
355
|
+
|
|
356
|
+
def get_negated_nominal_variable(self, i1: str, i2: str) -> Variable:
|
|
357
|
+
var_name: str = f"{i1}: not {{ {i2} }}"
|
|
358
|
+
flag: bool = var_name in list(map(str, self.variables))
|
|
359
|
+
v: Variable = self.get_variable(var_name)
|
|
360
|
+
if not flag:
|
|
361
|
+
v.set_type(VariableType.BINARY)
|
|
362
|
+
not_v: Variable = self.get_nominal_variable(i1, i2)
|
|
363
|
+
self.add_new_constraint(
|
|
364
|
+
Expression(1.0, Term(-1.0, v), Term(-1.0, not_v)), InequalityType.EQUAL
|
|
365
|
+
)
|
|
366
|
+
return v
|
|
367
|
+
|
|
368
|
+
@typing.overload
|
|
369
|
+
def add_new_constraint(
|
|
370
|
+
self, expr: Expression, constraint_type: InequalityType
|
|
371
|
+
) -> None: ...
|
|
372
|
+
|
|
373
|
+
@typing.overload
|
|
374
|
+
def add_new_constraint(self, x: Variable, n: float) -> None: ...
|
|
375
|
+
|
|
376
|
+
@typing.overload
|
|
377
|
+
def add_new_constraint(self, ass: Assertion, n: float) -> None: ...
|
|
378
|
+
|
|
379
|
+
@typing.overload
|
|
380
|
+
def add_new_constraint(self, x: Variable, d: Degree) -> None: ...
|
|
381
|
+
|
|
382
|
+
@typing.overload
|
|
383
|
+
def add_new_constraint(self, ass: Assertion) -> None: ...
|
|
384
|
+
|
|
385
|
+
@typing.overload
|
|
386
|
+
def add_new_constraint(
|
|
387
|
+
self, expr: Expression, constraint_type: InequalityType, degree: Degree
|
|
388
|
+
) -> None: ...
|
|
389
|
+
|
|
390
|
+
@typing.overload
|
|
391
|
+
def add_new_constraint(
|
|
392
|
+
self, expr: Expression, constraint_type: InequalityType, n: float
|
|
393
|
+
) -> None: ...
|
|
394
|
+
|
|
395
|
+
def add_new_constraint(self, *args) -> None:
|
|
396
|
+
assert len(args) in [1, 2, 3]
|
|
397
|
+
if len(args) == 1:
|
|
398
|
+
assert isinstance(args[0], Assertion)
|
|
399
|
+
self.__add_new_constraint_5(*args)
|
|
400
|
+
elif len(args) == 2:
|
|
401
|
+
if isinstance(args[0], Expression) and isinstance(args[1], InequalityType):
|
|
402
|
+
self.__add_new_constraint_1(*args)
|
|
403
|
+
elif isinstance(args[0], Variable) and isinstance(
|
|
404
|
+
args[1], constants.NUMBER
|
|
405
|
+
):
|
|
406
|
+
self.__add_new_constraint_2(*args)
|
|
407
|
+
elif isinstance(args[0], Assertion) and isinstance(
|
|
408
|
+
args[1], constants.NUMBER
|
|
409
|
+
):
|
|
410
|
+
self.__add_new_constraint_3(*args)
|
|
411
|
+
elif isinstance(args[0], Variable) and isinstance(args[1], Degree):
|
|
412
|
+
self.__add_new_constraint_4(*args)
|
|
413
|
+
else:
|
|
414
|
+
raise ValueError
|
|
415
|
+
elif len(args) == 3:
|
|
416
|
+
if (
|
|
417
|
+
isinstance(args[0], Expression)
|
|
418
|
+
and isinstance(args[1], InequalityType)
|
|
419
|
+
and isinstance(args[2], Degree)
|
|
420
|
+
):
|
|
421
|
+
self.__add_new_constraint_6(*args)
|
|
422
|
+
elif (
|
|
423
|
+
isinstance(args[0], Expression)
|
|
424
|
+
and isinstance(args[1], InequalityType)
|
|
425
|
+
and isinstance(args[2], constants.NUMBER)
|
|
426
|
+
):
|
|
427
|
+
self.__add_new_constraint_7(*args)
|
|
428
|
+
else:
|
|
429
|
+
raise ValueError
|
|
430
|
+
else:
|
|
431
|
+
raise ValueError
|
|
432
|
+
|
|
433
|
+
def __add_new_constraint_1(
|
|
434
|
+
self, expr: Expression, constraint_type: InequalityType
|
|
435
|
+
) -> None:
|
|
436
|
+
self.constraints.append(Inequation(expr, constraint_type))
|
|
437
|
+
|
|
438
|
+
def __add_new_constraint_2(self, x: Variable, n: float) -> None:
|
|
439
|
+
self.add_new_constraint(
|
|
440
|
+
Expression(Term(1.0, x)),
|
|
441
|
+
InequalityType.GREATER_THAN,
|
|
442
|
+
DegreeNumeric.get_degree(n),
|
|
443
|
+
)
|
|
444
|
+
|
|
445
|
+
def __add_new_constraint_3(self, ass: Assertion, n: float) -> None:
|
|
446
|
+
self.add_new_constraint(self.get_variable(ass), n)
|
|
447
|
+
|
|
448
|
+
def __add_new_constraint_4(self, x: Variable, d: Degree) -> None:
|
|
449
|
+
self.add_new_constraint(
|
|
450
|
+
Expression(Term(1.0, x)), InequalityType.GREATER_THAN, d
|
|
451
|
+
)
|
|
452
|
+
|
|
453
|
+
def __add_new_constraint_5(self, ass: Assertion) -> None:
|
|
454
|
+
x_ass: Variable = self.get_variable(ass)
|
|
455
|
+
ass_name: str = str(x_ass)
|
|
456
|
+
deg: Degree = ass.get_lower_limit()
|
|
457
|
+
if isinstance(deg, DegreeVariable):
|
|
458
|
+
deg_name: str = str(typing.cast(DegreeVariable, deg).get_variable())
|
|
459
|
+
if ass_name == deg_name:
|
|
460
|
+
return
|
|
461
|
+
self.add_new_constraint(x_ass, deg)
|
|
462
|
+
|
|
463
|
+
def __add_new_constraint_6(
|
|
464
|
+
self, expr: Expression, constraint_type: InequalityType, degree: Degree
|
|
465
|
+
) -> None:
|
|
466
|
+
self.constraints.append(
|
|
467
|
+
degree.create_inequality_with_degree_rhs(expr, constraint_type)
|
|
468
|
+
)
|
|
469
|
+
|
|
470
|
+
def __add_new_constraint_7(
|
|
471
|
+
self, expr: Expression, constraint_type: InequalityType, n: float
|
|
472
|
+
) -> None:
|
|
473
|
+
self.add_new_constraint(expr, constraint_type, DegreeNumeric.get_degree(n))
|
|
474
|
+
|
|
475
|
+
def add_equality(self, var1: Variable, var2: Variable) -> None:
|
|
476
|
+
self.add_new_constraint(
|
|
477
|
+
Expression(Term(1.0, var1), Term(-1.0, var2)), InequalityType.EQUAL
|
|
478
|
+
)
|
|
479
|
+
|
|
480
|
+
def add_string_feature(self, role: str) -> None:
|
|
481
|
+
self.string_features.add(role)
|
|
482
|
+
|
|
483
|
+
def add_string_value(self, value: str, int_value: int) -> None:
|
|
484
|
+
self.string_values[int_value] = value
|
|
485
|
+
|
|
486
|
+
def change_variable_names(
|
|
487
|
+
self, old_name: str, new_name: str, old_is_created_individual: bool
|
|
488
|
+
) -> None:
|
|
489
|
+
old_values: list[str] = [f"{old_name},", f",{old_name}", f"{old_name}:"]
|
|
490
|
+
new_values: list[str] = [f"{new_name},", f",{new_name}", f"{new_name}:"]
|
|
491
|
+
to_process: list[Variable] = copy.deepcopy(self.variables)
|
|
492
|
+
for v1 in to_process:
|
|
493
|
+
name: str = str(v1)
|
|
494
|
+
for old_value, new_value in zip(old_values, new_values):
|
|
495
|
+
if name not in old_value:
|
|
496
|
+
continue
|
|
497
|
+
name2: str = name.replace(old_value, new_value, 1)
|
|
498
|
+
v2: Variable = self.get_variable(name2)
|
|
499
|
+
if self.check_if_replacement_is_needed(v1, old_value, v2, new_value):
|
|
500
|
+
if old_is_created_individual:
|
|
501
|
+
self.add_equality(v1, v2)
|
|
502
|
+
else:
|
|
503
|
+
a_is_b: Variable = self.get_nominal_variable(new_name, old_name)
|
|
504
|
+
self.add_new_constraint(
|
|
505
|
+
Expression(
|
|
506
|
+
1.0, Term(-1.0, a_is_b), Term(1.0, v1), Term(-1.0, v2)
|
|
507
|
+
),
|
|
508
|
+
InequalityType.GREATER_THAN,
|
|
509
|
+
)
|
|
510
|
+
|
|
511
|
+
def check_if_replacement_is_needed(
|
|
512
|
+
self, v1: Variable, s1: str, v2: Variable, s2: str
|
|
513
|
+
) -> bool:
|
|
514
|
+
name1: str = str(v1)
|
|
515
|
+
begin1: int = name1.index(s1)
|
|
516
|
+
name2: str = str(v2)
|
|
517
|
+
begin2: int = name2.index(s2)
|
|
518
|
+
if begin1 != begin2:
|
|
519
|
+
return False
|
|
520
|
+
return (
|
|
521
|
+
name1[:begin1] == name2[:begin2]
|
|
522
|
+
and name1[begin1 + len(s1) :] == name2[begin2 + len(s2) :]
|
|
523
|
+
)
|
|
524
|
+
|
|
525
|
+
@typing.overload
|
|
526
|
+
def get_ordered_permutation(self, x: list[Variable]) -> list[Variable]: ...
|
|
527
|
+
|
|
528
|
+
@typing.overload
|
|
529
|
+
def get_ordered_permutation(
|
|
530
|
+
self, x: list[Variable], z: list[list[Variable]]
|
|
531
|
+
) -> list[Variable]: ...
|
|
532
|
+
|
|
533
|
+
def get_ordered_permutation(self, *args) -> list[Variable]:
|
|
534
|
+
assert len(args) in [1, 2]
|
|
535
|
+
assert isinstance(args[0], list) and all(
|
|
536
|
+
isinstance(a, Variable) for a in args[0]
|
|
537
|
+
)
|
|
538
|
+
if len(args) == 1:
|
|
539
|
+
return self.__get_ordered_permutation_1(*args)
|
|
540
|
+
elif len(args) == 2:
|
|
541
|
+
assert isinstance(args[1], list) and all(
|
|
542
|
+
isinstance(a, Variable) for a in args[1]
|
|
543
|
+
)
|
|
544
|
+
return self.__get_ordered_permutation_2(*args)
|
|
545
|
+
else:
|
|
546
|
+
raise ValueError
|
|
547
|
+
|
|
548
|
+
def __get_ordered_permutation_1(self, x: list[Variable]) -> list[Variable]:
|
|
549
|
+
n: int = len(x)
|
|
550
|
+
z: list[list[Variable]] = [
|
|
551
|
+
[self.get_new_variable(VariableType.BINARY) for _ in range(n)]
|
|
552
|
+
for _ in range(n)
|
|
553
|
+
]
|
|
554
|
+
return self.get_ordered_permutation(x, z)
|
|
555
|
+
|
|
556
|
+
def __get_ordered_permutation_2(
|
|
557
|
+
self, x: list[Variable], z: list[list[Variable]]
|
|
558
|
+
) -> list[Variable]:
|
|
559
|
+
n: int = len(x)
|
|
560
|
+
y: list[Variable] = [
|
|
561
|
+
self.get_new_variable(VariableType.SEMI_CONTINUOUS) for _ in range(n)
|
|
562
|
+
]
|
|
563
|
+
for i in range(n - 1):
|
|
564
|
+
self.add_new_constraint(
|
|
565
|
+
Expression(Term(1.0, y[i]), Term(-1.0, y[i + 1])),
|
|
566
|
+
InequalityType.GREATER_THAN,
|
|
567
|
+
)
|
|
568
|
+
for i in range(n):
|
|
569
|
+
for j in range(n):
|
|
570
|
+
self.add_new_constraint(
|
|
571
|
+
Expression(Term(1.0, x[j]), Term(-1.0, y[i]), Term(1.0, z[i][j])),
|
|
572
|
+
InequalityType.GREATER_THAN,
|
|
573
|
+
)
|
|
574
|
+
for i in range(n):
|
|
575
|
+
for j in range(n):
|
|
576
|
+
self.add_new_constraint(
|
|
577
|
+
Expression(Term(1.0, x[j]), Term(-1.0, y[i]), Term(-1.0, z[i][j])),
|
|
578
|
+
InequalityType.LESS_THAN,
|
|
579
|
+
)
|
|
580
|
+
for i in range(n):
|
|
581
|
+
exp: Expression = Expression(1.0 - n)
|
|
582
|
+
for j in range(n):
|
|
583
|
+
exp.add_term(Term(1.0, z[i][j]))
|
|
584
|
+
self.add_new_constraint(exp, InequalityType.EQUAL)
|
|
585
|
+
|
|
586
|
+
for i in range(n):
|
|
587
|
+
exp: Expression = Expression(1.0 - n)
|
|
588
|
+
for j in range(n):
|
|
589
|
+
exp.add_term(Term(1.0, z[j][i]))
|
|
590
|
+
self.add_new_constraint(exp, InequalityType.EQUAL)
|
|
591
|
+
return y
|
|
592
|
+
|
|
593
|
+
def solve_gurobi(self, objective: Expression) -> typing.Optional[Solution]:
|
|
594
|
+
try:
|
|
595
|
+
Util.debug("Running MILP solver: Gurobi")
|
|
596
|
+
Util.debug(f"Objective function -> {objective}")
|
|
597
|
+
|
|
598
|
+
num_binary_vars: int = 0
|
|
599
|
+
num_free_vars: int = 0
|
|
600
|
+
num_integer_vars: int = 0
|
|
601
|
+
num_up_vars: int = 0
|
|
602
|
+
size: int = len(self.variables)
|
|
603
|
+
objective_value: list[float] = [0.0] * size
|
|
604
|
+
|
|
605
|
+
if objective is not None:
|
|
606
|
+
for term in objective.get_terms():
|
|
607
|
+
index = self.variables.index(term.get_var())
|
|
608
|
+
objective_value[index] += term.get_coeff()
|
|
609
|
+
|
|
610
|
+
env = gp.Env(empty=True)
|
|
611
|
+
if not ConfigReader.DEBUG_PRINT:
|
|
612
|
+
env.setParam("OutputFlag", 0)
|
|
613
|
+
env.setParam("IntFeasTol", 1e-9)
|
|
614
|
+
env.setParam("BarConvTol", 0)
|
|
615
|
+
env.start()
|
|
616
|
+
|
|
617
|
+
model = gp.Model("model", env=env)
|
|
618
|
+
vars_gurobi: list[gp.Var] = []
|
|
619
|
+
show_variable: list[bool] = [False] * size
|
|
620
|
+
|
|
621
|
+
my_vars: list[Variable] = self.show_vars.get_variables()
|
|
622
|
+
|
|
623
|
+
for i in range(size):
|
|
624
|
+
v: Variable = self.variables[i]
|
|
625
|
+
v_type: VariableType = v.get_type()
|
|
626
|
+
ov: float = objective_value[i]
|
|
627
|
+
|
|
628
|
+
Util.debug(
|
|
629
|
+
(
|
|
630
|
+
f"Variable -- "
|
|
631
|
+
f"[{v.get_lower_bound()}, {v.get_upper_bound()}] - "
|
|
632
|
+
f"Obj value = {ov} - "
|
|
633
|
+
f"Var type = {v_type.name} -- "
|
|
634
|
+
f"Var = {v}"
|
|
635
|
+
)
|
|
636
|
+
)
|
|
637
|
+
|
|
638
|
+
vars_gurobi.append(
|
|
639
|
+
model.addVar(
|
|
640
|
+
lb=v.get_lower_bound(),
|
|
641
|
+
ub=v.get_upper_bound(),
|
|
642
|
+
obj=ov,
|
|
643
|
+
vtype=v_type.name,
|
|
644
|
+
name=str(v),
|
|
645
|
+
)
|
|
646
|
+
)
|
|
647
|
+
|
|
648
|
+
if v in my_vars:
|
|
649
|
+
show_variable[i] = True
|
|
650
|
+
|
|
651
|
+
if v_type == VariableType.BINARY:
|
|
652
|
+
num_binary_vars += 1
|
|
653
|
+
elif v_type == VariableType.CONTINUOUS:
|
|
654
|
+
num_free_vars += 1
|
|
655
|
+
elif v_type == VariableType.INTEGER:
|
|
656
|
+
num_integer_vars += 1
|
|
657
|
+
elif v_type == VariableType.SEMI_CONTINUOUS:
|
|
658
|
+
num_up_vars += 1
|
|
659
|
+
|
|
660
|
+
model.update()
|
|
661
|
+
|
|
662
|
+
Util.debug(f"# constraints -> {len(self.constraints)}")
|
|
663
|
+
constraint_name: str = "constraint"
|
|
664
|
+
for i, constraint in enumerate(self.constraints):
|
|
665
|
+
curr_name: str = f"{constraint_name}_{i + 1}"
|
|
666
|
+
expr: gp.LinExpr = gp.LinExpr()
|
|
667
|
+
for term in constraint.get_terms():
|
|
668
|
+
index: int = self.variables.index(term.get_var())
|
|
669
|
+
v: gp.Var = vars_gurobi[index]
|
|
670
|
+
c: float = term.get_coeff()
|
|
671
|
+
if c == 0:
|
|
672
|
+
continue
|
|
673
|
+
expr.add(v, c)
|
|
674
|
+
|
|
675
|
+
if expr.size() == 0:
|
|
676
|
+
continue
|
|
677
|
+
|
|
678
|
+
if constraint.get_type() == InequalityType.EQUAL:
|
|
679
|
+
gp_constraint: gp.Constr = expr == constraint.get_constant()
|
|
680
|
+
elif constraint.get_type() == InequalityType.LESS_THAN:
|
|
681
|
+
gp_constraint: gp.Constr = expr <= constraint.get_constant()
|
|
682
|
+
elif constraint.get_type() == InequalityType.GREATER_THAN:
|
|
683
|
+
gp_constraint: gp.Constr = expr >= constraint.get_constant()
|
|
684
|
+
|
|
685
|
+
model.addConstr(gp_constraint, curr_name)
|
|
686
|
+
Util.debug(f"{curr_name}: {gp_constraint}")
|
|
687
|
+
|
|
688
|
+
model.update()
|
|
689
|
+
model.optimize()
|
|
690
|
+
|
|
691
|
+
model.write(os.path.join(constants.RESULTS_PATH, "model.lp"))
|
|
692
|
+
model.write(os.path.join(constants.RESULTS_PATH, "solution.json"))
|
|
693
|
+
|
|
694
|
+
Util.debug(f"Model:")
|
|
695
|
+
sol: Solution = None
|
|
696
|
+
if model.Status == GRB.INFEASIBLE and ConfigReader.RELAX_MILP:
|
|
697
|
+
self.__handle_model_infeasibility(model)
|
|
698
|
+
|
|
699
|
+
if model.Status == GRB.INFEASIBLE:
|
|
700
|
+
sol = Solution(False)
|
|
701
|
+
else:
|
|
702
|
+
for i in range(size):
|
|
703
|
+
if ConfigReader.DEBUG_PRINT or show_variable[i]:
|
|
704
|
+
name: str = vars_gurobi[i].VarName
|
|
705
|
+
value: float = round(vars_gurobi[i].X, 6)
|
|
706
|
+
if self.PRINT_VARIABLES:
|
|
707
|
+
Util.debug(f"{name} = {value}")
|
|
708
|
+
if self.PRINT_LABELS:
|
|
709
|
+
self.print_instance_of_labels(name, value)
|
|
710
|
+
result: float = Util.round(abs(model.ObjVal))
|
|
711
|
+
sol = Solution(result)
|
|
712
|
+
|
|
713
|
+
model.printQuality()
|
|
714
|
+
model.printStats()
|
|
715
|
+
|
|
716
|
+
Util.debug(
|
|
717
|
+
f"{constants.STAR_SEPARATOR}Statistics{constants.STAR_SEPARATOR}"
|
|
718
|
+
)
|
|
719
|
+
Util.debug("MILP problem:")
|
|
720
|
+
Util.debug(f"\t\tSemi continuous variables: {num_up_vars}")
|
|
721
|
+
Util.debug(f"\t\tBinary variables: {num_binary_vars}")
|
|
722
|
+
Util.debug(f"\t\tContinuous variables: {num_free_vars}")
|
|
723
|
+
Util.debug(f"\t\tInteger variables: {num_integer_vars}")
|
|
724
|
+
Util.debug(f"\t\tTotal variables: {len(self.variables)}")
|
|
725
|
+
Util.debug(f"\t\tConstraints: {len(self.constraints)}")
|
|
726
|
+
return sol
|
|
727
|
+
except gp.GurobiError as e:
|
|
728
|
+
Util.error(f"Error code: {e.errno}. {e.message}")
|
|
729
|
+
return None
|
|
730
|
+
|
|
731
|
+
def __handle_model_infeasibility(self, model: gp.Model) -> None:
|
|
732
|
+
model.computeIIS()
|
|
733
|
+
# Print out the IIS constraints and variables
|
|
734
|
+
Util.debug("The following constraints and variables are in the IIS:")
|
|
735
|
+
Util.debug("Constraints:")
|
|
736
|
+
for c in model.getConstrs():
|
|
737
|
+
assert isinstance(c, gp.Constr)
|
|
738
|
+
if c.IISConstr:
|
|
739
|
+
Util.debug(f"\t\t{c.ConstrName}: {model.getRow(c)} {c.Sense} {c.RHS}")
|
|
740
|
+
|
|
741
|
+
Util.debug("Variables:")
|
|
742
|
+
for v in model.getVars():
|
|
743
|
+
if v.IISLB:
|
|
744
|
+
Util.debug(f"\t\t{v.VarName} ≥ {v.LB}")
|
|
745
|
+
if v.IISUB:
|
|
746
|
+
Util.debug(f"\t\t{v.VarName} ≤ {v.UB}")
|
|
747
|
+
|
|
748
|
+
Util.debug("Relaxing the variable bounds:")
|
|
749
|
+
# relaxing only variable bounds
|
|
750
|
+
model.feasRelaxS(0, False, True, False)
|
|
751
|
+
# for relaxing variable bounds and constraint bounds use
|
|
752
|
+
# model.feasRelaxS(0, False, True, True)
|
|
753
|
+
model.optimize()
|
|
754
|
+
|
|
755
|
+
def add_crisp_concept(self, concept_name: str) -> None:
|
|
756
|
+
self.crisp_concepts.add(concept_name)
|
|
757
|
+
|
|
758
|
+
def add_crisp_role(self, role_name: str) -> None:
|
|
759
|
+
self.crisp_roles.add(role_name)
|
|
760
|
+
|
|
761
|
+
def is_crisp_concept(self, concept_name: str) -> bool:
|
|
762
|
+
return concept_name in self.crisp_concepts
|
|
763
|
+
|
|
764
|
+
def is_crisp_role(self, role_name: str) -> bool:
|
|
765
|
+
return role_name in self.crisp_roles
|
|
766
|
+
|
|
767
|
+
def set_binary_variables(self) -> None:
|
|
768
|
+
for v in self.variables:
|
|
769
|
+
if v.get_datatype_filler_type() or v.get_type() in (
|
|
770
|
+
VariableType.CONTINUOUS,
|
|
771
|
+
VariableType.INTEGER,
|
|
772
|
+
):
|
|
773
|
+
continue
|
|
774
|
+
v.set_binary_variable()
|
|
775
|
+
|
|
776
|
+
def get_name_for_integer(self, i: int) -> typing.Optional[str]:
|
|
777
|
+
for name, i2 in self.number_of_variables.items():
|
|
778
|
+
if i == i2:
|
|
779
|
+
return name
|
|
780
|
+
return None
|
|
781
|
+
|
|
782
|
+
def get_number_for_assertion(self, ass: Assertion) -> int:
|
|
783
|
+
return self.number_of_variables.get(str(self.get_variable(ass)))
|
|
784
|
+
|
|
785
|
+
def add_contradiction(self) -> None:
|
|
786
|
+
self.constraints.clear()
|
|
787
|
+
self.add_new_constraint(Expression(1.0), InequalityType.EQUAL)
|