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.
Files changed (167) hide show
  1. fuzzy_dl_owl2/__init__.py +2 -0
  2. fuzzy_dl_owl2/fuzzydl/__init__.py +23 -0
  3. fuzzy_dl_owl2/fuzzydl/assertion/__init__.py +2 -0
  4. fuzzy_dl_owl2/fuzzydl/assertion/assertion.py +72 -0
  5. fuzzy_dl_owl2/fuzzydl/assertion/atomic_assertion.py +19 -0
  6. fuzzy_dl_owl2/fuzzydl/concept/__init__.py +13 -0
  7. fuzzy_dl_owl2/fuzzydl/concept/all_some_concept.py +85 -0
  8. fuzzy_dl_owl2/fuzzydl/concept/approximation_concept.py +147 -0
  9. fuzzy_dl_owl2/fuzzydl/concept/atomic_concept.py +91 -0
  10. fuzzy_dl_owl2/fuzzydl/concept/choquet_integral.py +64 -0
  11. fuzzy_dl_owl2/fuzzydl/concept/concept.py +230 -0
  12. fuzzy_dl_owl2/fuzzydl/concept/concrete/__init__.py +10 -0
  13. fuzzy_dl_owl2/fuzzydl/concept/concrete/crisp_concrete_concept.py +60 -0
  14. fuzzy_dl_owl2/fuzzydl/concept/concrete/fuzzy_concrete_concept.py +63 -0
  15. fuzzy_dl_owl2/fuzzydl/concept/concrete/fuzzy_number/__init__.py +1 -0
  16. fuzzy_dl_owl2/fuzzydl/concept/concrete/fuzzy_number/triangular_fuzzy_number.py +127 -0
  17. fuzzy_dl_owl2/fuzzydl/concept/concrete/left_concrete_concept.py +70 -0
  18. fuzzy_dl_owl2/fuzzydl/concept/concrete/linear_concrete_concept.py +70 -0
  19. fuzzy_dl_owl2/fuzzydl/concept/concrete/modified_concrete_concept.py +66 -0
  20. fuzzy_dl_owl2/fuzzydl/concept/concrete/right_concrete_concept.py +70 -0
  21. fuzzy_dl_owl2/fuzzydl/concept/concrete/trapezoidal_concrete_concept.py +96 -0
  22. fuzzy_dl_owl2/fuzzydl/concept/concrete/triangular_concrete_concept.py +89 -0
  23. fuzzy_dl_owl2/fuzzydl/concept/ext_threshold_concept.py +77 -0
  24. fuzzy_dl_owl2/fuzzydl/concept/has_value_concept.py +51 -0
  25. fuzzy_dl_owl2/fuzzydl/concept/implies_concept.py +144 -0
  26. fuzzy_dl_owl2/fuzzydl/concept/interface/__init__.py +6 -0
  27. fuzzy_dl_owl2/fuzzydl/concept/interface/has_concept_interface.py +17 -0
  28. fuzzy_dl_owl2/fuzzydl/concept/interface/has_concepts_interface.py +18 -0
  29. fuzzy_dl_owl2/fuzzydl/concept/interface/has_role_concept_interface.py +14 -0
  30. fuzzy_dl_owl2/fuzzydl/concept/interface/has_role_interface.py +15 -0
  31. fuzzy_dl_owl2/fuzzydl/concept/interface/has_value_interface.py +21 -0
  32. fuzzy_dl_owl2/fuzzydl/concept/interface/has_weighted_concepts_interface.py +29 -0
  33. fuzzy_dl_owl2/fuzzydl/concept/modified/__init__.py +3 -0
  34. fuzzy_dl_owl2/fuzzydl/concept/modified/linearly_modified_concept.py +32 -0
  35. fuzzy_dl_owl2/fuzzydl/concept/modified/modified_concept.py +59 -0
  36. fuzzy_dl_owl2/fuzzydl/concept/modified/triangularly_modified_concept.py +33 -0
  37. fuzzy_dl_owl2/fuzzydl/concept/negated_nominal.py +42 -0
  38. fuzzy_dl_owl2/fuzzydl/concept/operator_concept.py +707 -0
  39. fuzzy_dl_owl2/fuzzydl/concept/owa_concept.py +57 -0
  40. fuzzy_dl_owl2/fuzzydl/concept/qowa_concept.py +62 -0
  41. fuzzy_dl_owl2/fuzzydl/concept/quasi_sugeno_integral.py +46 -0
  42. fuzzy_dl_owl2/fuzzydl/concept/self_concept.py +45 -0
  43. fuzzy_dl_owl2/fuzzydl/concept/string_concept.py +35 -0
  44. fuzzy_dl_owl2/fuzzydl/concept/sugeno_integral.py +83 -0
  45. fuzzy_dl_owl2/fuzzydl/concept/threshold_concept.py +81 -0
  46. fuzzy_dl_owl2/fuzzydl/concept/truth_concept.py +83 -0
  47. fuzzy_dl_owl2/fuzzydl/concept/value_concept.py +67 -0
  48. fuzzy_dl_owl2/fuzzydl/concept/weighted_concept.py +55 -0
  49. fuzzy_dl_owl2/fuzzydl/concept/weighted_max_concept.py +63 -0
  50. fuzzy_dl_owl2/fuzzydl/concept/weighted_min_concept.py +57 -0
  51. fuzzy_dl_owl2/fuzzydl/concept/weighted_sum_concept.py +62 -0
  52. fuzzy_dl_owl2/fuzzydl/concept/weighted_sum_zero_concept.py +62 -0
  53. fuzzy_dl_owl2/fuzzydl/concept_equivalence.py +20 -0
  54. fuzzy_dl_owl2/fuzzydl/concrete_feature.py +94 -0
  55. fuzzy_dl_owl2/fuzzydl/degree/__init__.py +4 -0
  56. fuzzy_dl_owl2/fuzzydl/degree/degree.py +79 -0
  57. fuzzy_dl_owl2/fuzzydl/degree/degree_expression.py +57 -0
  58. fuzzy_dl_owl2/fuzzydl/degree/degree_numeric.py +57 -0
  59. fuzzy_dl_owl2/fuzzydl/degree/degree_variable.py +54 -0
  60. fuzzy_dl_owl2/fuzzydl/domain_axiom.py +8 -0
  61. fuzzy_dl_owl2/fuzzydl/exception/__init__.py +2 -0
  62. fuzzy_dl_owl2/fuzzydl/exception/fuzzy_ontology_exception.py +4 -0
  63. fuzzy_dl_owl2/fuzzydl/exception/inconsistent_ontology_exception.py +4 -0
  64. fuzzy_dl_owl2/fuzzydl/feature_function.py +148 -0
  65. fuzzy_dl_owl2/fuzzydl/fuzzydl_to_owl2.py +920 -0
  66. fuzzy_dl_owl2/fuzzydl/fuzzydl_to_owl2_java.py +953 -0
  67. fuzzy_dl_owl2/fuzzydl/general_concept_inclusion.py +82 -0
  68. fuzzy_dl_owl2/fuzzydl/individual/__init__.py +3 -0
  69. fuzzy_dl_owl2/fuzzydl/individual/created_individual.py +219 -0
  70. fuzzy_dl_owl2/fuzzydl/individual/individual.py +113 -0
  71. fuzzy_dl_owl2/fuzzydl/individual/representative_individual.py +37 -0
  72. fuzzy_dl_owl2/fuzzydl/knowledge_base.py +9037 -0
  73. fuzzy_dl_owl2/fuzzydl/label.py +32 -0
  74. fuzzy_dl_owl2/fuzzydl/milp/__init__.py +7 -0
  75. fuzzy_dl_owl2/fuzzydl/milp/expression.py +186 -0
  76. fuzzy_dl_owl2/fuzzydl/milp/inequation.py +55 -0
  77. fuzzy_dl_owl2/fuzzydl/milp/milp_helper.py +787 -0
  78. fuzzy_dl_owl2/fuzzydl/milp/show_variables_helper.py +151 -0
  79. fuzzy_dl_owl2/fuzzydl/milp/solution.py +45 -0
  80. fuzzy_dl_owl2/fuzzydl/milp/term.py +76 -0
  81. fuzzy_dl_owl2/fuzzydl/milp/variable.py +89 -0
  82. fuzzy_dl_owl2/fuzzydl/modifier/__init__.py +3 -0
  83. fuzzy_dl_owl2/fuzzydl/modifier/linear_modifier.py +76 -0
  84. fuzzy_dl_owl2/fuzzydl/modifier/modifier.py +39 -0
  85. fuzzy_dl_owl2/fuzzydl/modifier/triangular_modifier.py +76 -0
  86. fuzzy_dl_owl2/fuzzydl/parser/ParserConstants.py +406 -0
  87. fuzzy_dl_owl2/fuzzydl/parser/__init__.py +1 -0
  88. fuzzy_dl_owl2/fuzzydl/parser/dl_parser.py +2029 -0
  89. fuzzy_dl_owl2/fuzzydl/parser/ebnf.lark +290 -0
  90. fuzzy_dl_owl2/fuzzydl/parser/larkx.py +70 -0
  91. fuzzy_dl_owl2/fuzzydl/primitive_concept_definition.py +81 -0
  92. fuzzy_dl_owl2/fuzzydl/query/__init__.py +14 -0
  93. fuzzy_dl_owl2/fuzzydl/query/all_instances_query.py +50 -0
  94. fuzzy_dl_owl2/fuzzydl/query/bnp_query.py +22 -0
  95. fuzzy_dl_owl2/fuzzydl/query/defuzzify/__init__.py +4 -0
  96. fuzzy_dl_owl2/fuzzydl/query/defuzzify/defuzzify_query.py +76 -0
  97. fuzzy_dl_owl2/fuzzydl/query/defuzzify/lom_defuzzify_query.py +19 -0
  98. fuzzy_dl_owl2/fuzzydl/query/defuzzify/mom_defuzzify_query.py +88 -0
  99. fuzzy_dl_owl2/fuzzydl/query/defuzzify/som_defuzzify_query.py +20 -0
  100. fuzzy_dl_owl2/fuzzydl/query/instance_query.py +19 -0
  101. fuzzy_dl_owl2/fuzzydl/query/kb_satisfiable_query.py +32 -0
  102. fuzzy_dl_owl2/fuzzydl/query/max/__init__.py +5 -0
  103. fuzzy_dl_owl2/fuzzydl/query/max/max_instance_query.py +45 -0
  104. fuzzy_dl_owl2/fuzzydl/query/max/max_query.py +31 -0
  105. fuzzy_dl_owl2/fuzzydl/query/max/max_related_query.py +45 -0
  106. fuzzy_dl_owl2/fuzzydl/query/max/max_satisfiable_query.py +73 -0
  107. fuzzy_dl_owl2/fuzzydl/query/max/max_subsumes_query.py +64 -0
  108. fuzzy_dl_owl2/fuzzydl/query/min/__init__.py +5 -0
  109. fuzzy_dl_owl2/fuzzydl/query/min/min_instance_query.py +50 -0
  110. fuzzy_dl_owl2/fuzzydl/query/min/min_query.py +31 -0
  111. fuzzy_dl_owl2/fuzzydl/query/min/min_related_query.py +57 -0
  112. fuzzy_dl_owl2/fuzzydl/query/min/min_satisfiable_query.py +80 -0
  113. fuzzy_dl_owl2/fuzzydl/query/min/min_subsumes_query.py +65 -0
  114. fuzzy_dl_owl2/fuzzydl/query/query.py +38 -0
  115. fuzzy_dl_owl2/fuzzydl/query/related_query.py +15 -0
  116. fuzzy_dl_owl2/fuzzydl/query/satisfiable_query.py +37 -0
  117. fuzzy_dl_owl2/fuzzydl/query/subsumption_query.py +20 -0
  118. fuzzy_dl_owl2/fuzzydl/range_axiom.py +7 -0
  119. fuzzy_dl_owl2/fuzzydl/relation.py +47 -0
  120. fuzzy_dl_owl2/fuzzydl/restriction/__init__.py +2 -0
  121. fuzzy_dl_owl2/fuzzydl/restriction/has_value_restriction.py +16 -0
  122. fuzzy_dl_owl2/fuzzydl/restriction/restriction.py +34 -0
  123. fuzzy_dl_owl2/fuzzydl/role_parent_with_degree.py +10 -0
  124. fuzzy_dl_owl2/fuzzydl/util/__init__.py +3 -0
  125. fuzzy_dl_owl2/fuzzydl/util/config_reader.py +56 -0
  126. fuzzy_dl_owl2/fuzzydl/util/constants.py +424 -0
  127. fuzzy_dl_owl2/fuzzydl/util/util.py +73 -0
  128. fuzzy_dl_owl2/fuzzyowl2/__init__.py +5 -0
  129. fuzzy_dl_owl2/fuzzyowl2/fuzzyowl2.py +1513 -0
  130. fuzzy_dl_owl2/fuzzyowl2/fuzzyowl2_java.py +1409 -0
  131. fuzzy_dl_owl2/fuzzyowl2/fuzzyowl2_to_fuzzydl.py +917 -0
  132. fuzzy_dl_owl2/fuzzyowl2/fuzzyowl2_to_fuzzydl_java.py +956 -0
  133. fuzzy_dl_owl2/fuzzyowl2/owl_types/__init__.py +0 -0
  134. fuzzy_dl_owl2/fuzzyowl2/owl_types/choquet_concept.py +19 -0
  135. fuzzy_dl_owl2/fuzzyowl2/owl_types/concept_definition.py +14 -0
  136. fuzzy_dl_owl2/fuzzyowl2/owl_types/fuzzy_datatype.py +22 -0
  137. fuzzy_dl_owl2/fuzzyowl2/owl_types/fuzzy_modifier.py +4 -0
  138. fuzzy_dl_owl2/fuzzyowl2/owl_types/fuzzy_nominal_concept.py +19 -0
  139. fuzzy_dl_owl2/fuzzyowl2/owl_types/fuzzy_property.py +5 -0
  140. fuzzy_dl_owl2/fuzzyowl2/owl_types/left_shoulder_function.py +17 -0
  141. fuzzy_dl_owl2/fuzzyowl2/owl_types/linear_function.py +17 -0
  142. fuzzy_dl_owl2/fuzzyowl2/owl_types/linear_modifier.py +13 -0
  143. fuzzy_dl_owl2/fuzzyowl2/owl_types/modified_concept.py +19 -0
  144. fuzzy_dl_owl2/fuzzyowl2/owl_types/modified_function.py +17 -0
  145. fuzzy_dl_owl2/fuzzyowl2/owl_types/modified_property.py +15 -0
  146. fuzzy_dl_owl2/fuzzyowl2/owl_types/owa_concept.py +19 -0
  147. fuzzy_dl_owl2/fuzzyowl2/owl_types/property_definition.py +10 -0
  148. fuzzy_dl_owl2/fuzzyowl2/owl_types/qowa_concept.py +19 -0
  149. fuzzy_dl_owl2/fuzzyowl2/owl_types/quasi_sugeno_concept.py +21 -0
  150. fuzzy_dl_owl2/fuzzyowl2/owl_types/right_shoulder_function.py +17 -0
  151. fuzzy_dl_owl2/fuzzyowl2/owl_types/sugeno_concept.py +21 -0
  152. fuzzy_dl_owl2/fuzzyowl2/owl_types/trapezoidal_function.py +25 -0
  153. fuzzy_dl_owl2/fuzzyowl2/owl_types/triangular_function.py +21 -0
  154. fuzzy_dl_owl2/fuzzyowl2/owl_types/triangular_modifer.py +21 -0
  155. fuzzy_dl_owl2/fuzzyowl2/owl_types/weighted_concept.py +19 -0
  156. fuzzy_dl_owl2/fuzzyowl2/owl_types/weighted_max_concept.py +15 -0
  157. fuzzy_dl_owl2/fuzzyowl2/owl_types/weighted_min_concept.py +15 -0
  158. fuzzy_dl_owl2/fuzzyowl2/owl_types/weighted_sum_concept.py +15 -0
  159. fuzzy_dl_owl2/fuzzyowl2/owl_types/weighted_sum_zero_concept.py +15 -0
  160. fuzzy_dl_owl2/fuzzyowl2/parser/__init__.py +1 -0
  161. fuzzy_dl_owl2/fuzzyowl2/parser/owl2_parser.py +491 -0
  162. fuzzy_dl_owl2/fuzzyowl2/util/__init__.py +1 -0
  163. fuzzy_dl_owl2/fuzzyowl2/util/constants.py +112 -0
  164. fuzzy_dl_owl2-1.0.0.dist-info/LICENSE +427 -0
  165. fuzzy_dl_owl2-1.0.0.dist-info/METADATA +299 -0
  166. fuzzy_dl_owl2-1.0.0.dist-info/RECORD +167 -0
  167. fuzzy_dl_owl2-1.0.0.dist-info/WHEEL +4 -0
@@ -0,0 +1,707 @@
1
+ import typing
2
+ from functools import partial
3
+
4
+ from fuzzy_dl_owl2.fuzzydl.concept.all_some_concept import AllSomeConcept
5
+ from fuzzy_dl_owl2.fuzzydl.concept.concept import Concept
6
+ from fuzzy_dl_owl2.fuzzydl.concept.interface.has_concepts_interface import (
7
+ HasConceptsInterface,
8
+ )
9
+ from fuzzy_dl_owl2.fuzzydl.concept.truth_concept import TruthConcept
10
+ from fuzzy_dl_owl2.fuzzydl.util import constants
11
+ from fuzzy_dl_owl2.fuzzydl.util.constants import ConceptType, FuzzyLogic
12
+
13
+
14
+ class OperatorConcept(Concept, HasConceptsInterface):
15
+ AND_OPERATORS: list[ConceptType] = [
16
+ ConceptType.AND,
17
+ ConceptType.GOEDEL_AND,
18
+ ConceptType.LUKASIEWICZ_AND,
19
+ ]
20
+
21
+ OR_OPERATORS: list[ConceptType] = [
22
+ ConceptType.OR,
23
+ ConceptType.GOEDEL_OR,
24
+ ConceptType.LUKASIEWICZ_OR,
25
+ ]
26
+
27
+ BINARY_OPERATORS: list[ConceptType] = AND_OPERATORS + OR_OPERATORS
28
+
29
+ COMPLEMENT_LAW_OPERATORS: list[ConceptType] = [
30
+ ConceptType.AND,
31
+ ConceptType.LUKASIEWICZ_AND,
32
+ ConceptType.OR,
33
+ ConceptType.LUKASIEWICZ_OR,
34
+ ]
35
+
36
+ DISTRIBUTIVE_OPERATORS: list[ConceptType] = [
37
+ ConceptType.AND,
38
+ ConceptType.OR,
39
+ ConceptType.GOEDEL_AND,
40
+ ConceptType.GOEDEL_OR,
41
+ ]
42
+
43
+ ABSORPTION_OPERATORS: list[ConceptType] = DISTRIBUTIVE_OPERATORS
44
+
45
+ ALL_OPERATORS: list[ConceptType] = BINARY_OPERATORS + [ConceptType.COMPLEMENT]
46
+
47
+ OPERATORS: dict[ConceptType, ConceptType] = {
48
+ k: v for k, v in zip(AND_OPERATORS + OR_OPERATORS, OR_OPERATORS + AND_OPERATORS)
49
+ }
50
+
51
+ def __init__(self, c_type: ConceptType, concepts: typing.Iterable[Concept]) -> None:
52
+ Concept.__init__(self, c_type, None)
53
+ HasConceptsInterface.__init__(self, concepts)
54
+
55
+ assert c_type in OperatorConcept.ALL_OPERATORS, f"Type {c_type} is not valid."
56
+
57
+ self.type: ConceptType = c_type
58
+ self.name = self.compute_name()
59
+
60
+ @property
61
+ def concepts(self) -> list[Concept]:
62
+ return self._concepts
63
+
64
+ @concepts.setter
65
+ def concepts(self, value: typing.Iterable[Concept]) -> None:
66
+ self._concepts = list(value)
67
+ self.name = self.compute_name()
68
+
69
+ def clone(self) -> Concept:
70
+ return OperatorConcept(
71
+ self.type,
72
+ [c for c in self.concepts],
73
+ )
74
+
75
+ @staticmethod
76
+ def __op(c_type: ConceptType, concepts: typing.Iterable[Concept]) -> Concept:
77
+ assert len(concepts) > 0, "You must have at least one argument"
78
+ if c_type != ConceptType.COMPLEMENT and len(concepts) == 1:
79
+ return concepts[0]
80
+ concepts: list[Concept] = list(concepts)
81
+ if c_type in OperatorConcept.BINARY_OPERATORS:
82
+ changes: bool = True
83
+ while changes:
84
+ i: int = 0
85
+ changes = False
86
+ while len(concepts) > 0 and i < len(concepts):
87
+ c: Concept = concepts[i]
88
+ if c.type == c_type:
89
+ concepts.extend(typing.cast(OperatorConcept, c).concepts)
90
+ concepts.pop(i)
91
+ changes = True
92
+ else:
93
+ i += 1
94
+ return OperatorConcept(c_type, sorted(concepts))
95
+
96
+ @staticmethod
97
+ def and_(*concepts: Concept) -> Concept:
98
+ if constants.KNOWLEDGE_BASE_SEMANTICS == FuzzyLogic.CLASSICAL:
99
+ return OperatorConcept.__op(ConceptType.AND, concepts).classic_cnf()
100
+ if constants.KNOWLEDGE_BASE_SEMANTICS == FuzzyLogic.LUKASIEWICZ:
101
+ return OperatorConcept.__op(
102
+ ConceptType.LUKASIEWICZ_AND, concepts
103
+ ).lukasiewicz_cnf()
104
+ if constants.KNOWLEDGE_BASE_SEMANTICS == FuzzyLogic.ZADEH:
105
+ return OperatorConcept.__op(ConceptType.GOEDEL_AND, concepts).goedel_cnf()
106
+
107
+ @staticmethod
108
+ def goedel_and(*concepts: Concept) -> Concept:
109
+ return OperatorConcept.__op(ConceptType.GOEDEL_AND, concepts).goedel_cnf()
110
+
111
+ @staticmethod
112
+ def lukasiewicz_and(*concepts: Concept) -> Concept:
113
+ return OperatorConcept.__op(
114
+ ConceptType.LUKASIEWICZ_AND, concepts
115
+ ).lukasiewicz_cnf()
116
+
117
+ @staticmethod
118
+ def or_(*concepts: Concept) -> Concept:
119
+ if constants.KNOWLEDGE_BASE_SEMANTICS == FuzzyLogic.CLASSICAL:
120
+ return OperatorConcept.__op(ConceptType.OR, concepts).classic_cnf()
121
+ if constants.KNOWLEDGE_BASE_SEMANTICS == FuzzyLogic.LUKASIEWICZ:
122
+ return OperatorConcept.__op(
123
+ ConceptType.LUKASIEWICZ_OR, concepts
124
+ ).lukasiewicz_cnf()
125
+ if constants.KNOWLEDGE_BASE_SEMANTICS == FuzzyLogic.ZADEH:
126
+ return OperatorConcept.__op(ConceptType.GOEDEL_OR, concepts).goedel_cnf()
127
+
128
+ @staticmethod
129
+ def goedel_or(*concepts: Concept) -> Concept:
130
+ return OperatorConcept.__op(ConceptType.GOEDEL_OR, concepts).goedel_cnf()
131
+
132
+ @staticmethod
133
+ def lukasiewicz_or(*concepts: Concept) -> Concept:
134
+ return OperatorConcept.__op(
135
+ ConceptType.LUKASIEWICZ_OR, concepts
136
+ ).lukasiewicz_cnf()
137
+
138
+ @staticmethod
139
+ def not_(concept: Concept) -> Concept:
140
+ if concept.type == ConceptType.TOP:
141
+ return TruthConcept.get_bottom()
142
+ if concept.type == ConceptType.BOTTOM:
143
+ return TruthConcept.get_top()
144
+ if concept.type != ConceptType.COMPLEMENT:
145
+ return OperatorConcept(ConceptType.COMPLEMENT, [concept])
146
+ else:
147
+ return typing.cast(OperatorConcept, concept).concepts[0]
148
+
149
+ @staticmethod
150
+ def is_or(c_type: ConceptType) -> bool:
151
+ return c_type in OperatorConcept.OR_OPERATORS
152
+
153
+ @staticmethod
154
+ def is_and(c_type: ConceptType) -> bool:
155
+ return c_type in OperatorConcept.AND_OPERATORS
156
+
157
+ @staticmethod
158
+ def is_not_type(op: Concept, c_type: ConceptType) -> bool:
159
+ if not isinstance(op, OperatorConcept):
160
+ return False
161
+ if op.type != ConceptType.COMPLEMENT:
162
+ return False
163
+ return op.concepts[0].type == c_type
164
+
165
+ @staticmethod
166
+ def is_not_fuzzy_number(op: Concept) -> bool:
167
+ return OperatorConcept.is_not_type(op, ConceptType.FUZZY_NUMBER)
168
+
169
+ @staticmethod
170
+ def is_not_concrete(op: Concept) -> bool:
171
+ return OperatorConcept.is_not_type(op, ConceptType.CONCRETE)
172
+
173
+ @staticmethod
174
+ def is_not_has_value(op: Concept) -> bool:
175
+ return OperatorConcept.is_not_type(op, ConceptType.HAS_VALUE)
176
+
177
+ @staticmethod
178
+ def is_not_goedel_implies(op: Concept) -> bool:
179
+ return OperatorConcept.is_not_type(op, ConceptType.GOEDEL_IMPLIES)
180
+
181
+ @staticmethod
182
+ def is_not_at_most_value(op: Concept) -> bool:
183
+ return OperatorConcept.is_not_type(op, ConceptType.AT_MOST_VALUE)
184
+
185
+ @staticmethod
186
+ def is_not_at_least_value(op: Concept) -> bool:
187
+ return OperatorConcept.is_not_type(op, ConceptType.AT_LEAST_VALUE)
188
+
189
+ @staticmethod
190
+ def is_not_exact_value(op: Concept) -> bool:
191
+ return OperatorConcept.is_not_type(op, ConceptType.EXACT_VALUE)
192
+
193
+ @staticmethod
194
+ def is_not_weighted(op: Concept) -> bool:
195
+ return OperatorConcept.is_not_type(op, ConceptType.WEIGHTED)
196
+
197
+ @staticmethod
198
+ def is_not_weighted_min(op: Concept) -> bool:
199
+ return OperatorConcept.is_not_type(op, ConceptType.W_MIN)
200
+
201
+ @staticmethod
202
+ def is_not_weighted_max(op: Concept) -> bool:
203
+ return OperatorConcept.is_not_type(op, ConceptType.W_MAX)
204
+
205
+ @staticmethod
206
+ def is_not_weighted_sum(op: Concept) -> bool:
207
+ return OperatorConcept.is_not_type(op, ConceptType.W_SUM)
208
+
209
+ @staticmethod
210
+ def is_not_weighted_sum_zero(op: Concept) -> bool:
211
+ return OperatorConcept.is_not_type(op, ConceptType.W_SUM_ZERO)
212
+
213
+ @staticmethod
214
+ def is_not_pos_threshold(op: Concept) -> bool:
215
+ return OperatorConcept.is_not_type(op, ConceptType.POS_THRESHOLD)
216
+
217
+ @staticmethod
218
+ def is_not_neg_threshold(op: Concept) -> bool:
219
+ return OperatorConcept.is_not_type(op, ConceptType.NEG_THRESHOLD)
220
+
221
+ @staticmethod
222
+ def is_not_ext_pos_threshold(op: Concept) -> bool:
223
+ return OperatorConcept.is_not_type(op, ConceptType.EXT_POS_THRESHOLD)
224
+
225
+ @staticmethod
226
+ def is_not_ext_neg_threshold(op: Concept) -> bool:
227
+ return OperatorConcept.is_not_type(op, ConceptType.EXT_NEG_THRESHOLD)
228
+
229
+ @staticmethod
230
+ def is_not_concrete(op: Concept) -> bool:
231
+ return OperatorConcept.is_not_type(op, ConceptType.CONCRETE)
232
+
233
+ @staticmethod
234
+ def is_not_modified(op: Concept) -> bool:
235
+ return OperatorConcept.is_not_type(op, ConceptType.MODIFIED)
236
+
237
+ @staticmethod
238
+ def is_not_owa(op: Concept) -> bool:
239
+ return OperatorConcept.is_not_type(op, ConceptType.OWA)
240
+
241
+ @staticmethod
242
+ def is_not_qowa(op: Concept) -> bool:
243
+ return OperatorConcept.is_not_type(op, ConceptType.QUANTIFIED_OWA)
244
+
245
+ @staticmethod
246
+ def is_not_choquet(op: Concept) -> bool:
247
+ return OperatorConcept.is_not_type(op, ConceptType.CHOQUET_INTEGRAL)
248
+
249
+ @staticmethod
250
+ def is_not_sugeno(op: Concept) -> bool:
251
+ return OperatorConcept.is_not_type(op, ConceptType.SUGENO_INTEGRAL)
252
+
253
+ @staticmethod
254
+ def is_not_quasi_sugeno(op: Concept) -> bool:
255
+ return OperatorConcept.is_not_type(op, ConceptType.QUASI_SUGENO_INTEGRAL)
256
+
257
+ @staticmethod
258
+ def is_not_self(op: Concept) -> bool:
259
+ return OperatorConcept.is_not_type(op, ConceptType.SELF)
260
+
261
+ @staticmethod
262
+ def is_not_zadeh_implies(op: Concept) -> bool:
263
+ return OperatorConcept.is_not_type(op, ConceptType.ZADEH_IMPLIES)
264
+
265
+ def is_concrete(self) -> bool:
266
+ if OperatorConcept.is_not_concrete(self) or OperatorConcept.is_not_fuzzy_number(
267
+ self
268
+ ):
269
+ return True
270
+ if OperatorConcept.is_not_modified(self):
271
+ return self.concepts[0].is_concrete()
272
+ return False
273
+
274
+ def is_atomic(self) -> bool:
275
+ return False
276
+
277
+ def is_complemented_atomic(self) -> bool:
278
+ return self.type == ConceptType.COMPLEMENT and (
279
+ self.concepts[0].is_atomic()
280
+ # or self.concepts[0].type
281
+ # in (ConceptType.MODIFIED, ConceptType.FUZZY_NUMBER, ConceptType.CONCRETE)
282
+ )
283
+
284
+ def get_atom(self) -> typing.Optional[typing.Self]:
285
+ return self.concepts[0] if self.type == ConceptType.COMPLEMENT else None
286
+
287
+ def get_atoms(self) -> list[typing.Self]:
288
+ if self.type == ConceptType.COMPLEMENT:
289
+ if self.is_complemented_atomic():
290
+ return [self]
291
+ else:
292
+ return self.concepts[0].get_atoms()
293
+ else:
294
+ return list.extend(*[c.get_atoms() for c in self.concepts])
295
+
296
+ def is_simplified(self) -> bool:
297
+ """
298
+ This function check if current formula is simplified, i.e., if:
299
+ - The only negated elements are literal of kind (~ A), where A is an AtomicProposition
300
+ - The OR operator is between:
301
+ - Two literals => A | B
302
+ - One literal and a AND => A | (B & C) - (A & B) | C
303
+ - Two (or more) OR => (A & B) | (C & D) | (E & F)
304
+ - The AND operator is between:
305
+ - Two literals => A & B
306
+ - One literal and a OR => A & (B | C) - (A | B) & C
307
+ - Two (or more) AND => (A | B) & (C | D) & (E | F)
308
+ - The only operators are AND, OR and NOT
309
+ """
310
+ if self.is_complemented_atomic():
311
+ return True
312
+ return all(c.type != self.type for c in self.concepts)
313
+
314
+ def de_morgan(self) -> typing.Self:
315
+ self.concepts: Concept = [c.de_morgan() for c in self._concepts]
316
+ if (
317
+ self.type == ConceptType.COMPLEMENT
318
+ and isinstance(self.concepts[0], OperatorConcept)
319
+ and self.concepts[0].type in OperatorConcept.BINARY_OPERATORS
320
+ ):
321
+ # ~(A & B) = (~A | ~B)
322
+ # ~(A | B) = (~A & ~B)
323
+ op: ConceptType = OperatorConcept.OPERATORS[self.concepts[0].type]
324
+ concepts: list[Concept] = [
325
+ (-c).de_morgan()
326
+ for c in typing.cast(OperatorConcept, self.concepts[0]).concepts
327
+ ]
328
+ return OperatorConcept(op, concepts).de_morgan()
329
+ return self
330
+
331
+ def reduce_truth_values(self) -> typing.Self:
332
+ self.concepts: list[Concept] = [c.reduce_truth_values() for c in self._concepts]
333
+ if self.type == ConceptType.COMPLEMENT and self.concepts[0].type in (
334
+ ConceptType.TOP,
335
+ ConceptType.BOTTOM,
336
+ ):
337
+ """
338
+ ~ ⊤ = ⊥
339
+ ~ ⊥ = ⊤
340
+ """
341
+ return -self.concepts[0]
342
+ elif self.type in OperatorConcept.BINARY_OPERATORS:
343
+ """
344
+ ⊤ & ⊤ = ⊤
345
+ ⊤ & A = A & ⊤ = A
346
+
347
+ ⊥ & ⊤ = ⊥
348
+ ⊥ & A = A & ⊥ = ⊥
349
+
350
+ A & ~A = ⊥
351
+ A & A = A
352
+
353
+ ⊥ | ⊥ = ⊥
354
+ ⊥ | A = A | ⊥ = A
355
+
356
+ ⊤ | ⊥ = ⊤
357
+ ⊤ | A = A | ⊤ = ⊤
358
+
359
+ A | ~A = ⊤
360
+ A | A = A
361
+ """
362
+ if OperatorConcept.is_and(self.type):
363
+ if ConceptType.BOTTOM in [c.type for c in self.concepts] or any(
364
+ -c in self.concepts for c in self.concepts
365
+ ):
366
+ return TruthConcept.get_bottom()
367
+ if self.type in OperatorConcept.ABSORPTION_OPERATORS:
368
+ self.concepts = sorted(set(self.concepts))
369
+ self.concepts = [c for c in self.concepts if c.type != ConceptType.TOP]
370
+ elif OperatorConcept.is_or(self.type):
371
+ if ConceptType.TOP in [c.type for c in self.concepts] or any(
372
+ -c in self.concepts for c in self.concepts
373
+ ):
374
+ return TruthConcept.get_top()
375
+ if self.type in OperatorConcept.ABSORPTION_OPERATORS:
376
+ self.concepts = sorted(set(self.concepts))
377
+ self.concepts = [
378
+ c for c in self.concepts if c.type != ConceptType.BOTTOM
379
+ ]
380
+ return self
381
+
382
+ def reduce_double_negation(self) -> typing.Self:
383
+ self.concepts: list[Concept] = [
384
+ c.reduce_double_negation() for c in self._concepts
385
+ ]
386
+ # ~(~A) = A
387
+ if self.type == ConceptType.COMPLEMENT:
388
+ if (
389
+ isinstance(self.concepts[0], OperatorConcept)
390
+ and self.concepts[0].type == ConceptType.COMPLEMENT
391
+ ):
392
+ return self.concepts[0].concepts[0].reduce_double_negation()
393
+ return self
394
+
395
+ def distribute(self, c_type: ConceptType) -> typing.Self:
396
+ if self.type == ConceptType.COMPLEMENT:
397
+ self.concepts: list[Concept] = [self._concepts[0].distribute(c_type)]
398
+ return self
399
+
400
+ if self.type not in OperatorConcept.DISTRIBUTIVE_OPERATORS:
401
+ return self
402
+
403
+ outer_operator = partial(OperatorConcept.__op, c_type)
404
+ inner_operator = partial(
405
+ OperatorConcept.__op, OperatorConcept.OPERATORS[c_type]
406
+ )
407
+
408
+ self.concepts: list[Concept] = [c.distribute(c_type) for c in self._concepts]
409
+ if self.type == c_type:
410
+ # A & (B | C) = (A & B) | (A & C), where A is literal of DNF clause (A = A_1 & A_2 & ... & A_n)
411
+ # (A | B) & (C | D) = ((A | B) & C) | ((A | B) & D)
412
+ # A | (B & C) = (A | B) & (A | C), where A is literal of CNF clause (A = A_1 | A_2 | ... | A_n)
413
+ # (A & B) | (C & D) = (A & B | C) & (A & B | D)
414
+ # (A | B) & C = (A & C) | (B & C), where C is literal of DNF clause (C = C_1 & C_2 & ... & C_n)
415
+ # (A & B) | C = (A | C) & (B | C), where C is literal of CNF clause (C = C_1 | C_2 | ... | C_n)
416
+ c1: list[OperatorConcept] = [
417
+ c for c in self.concepts if c.type == OperatorConcept.OPERATORS[c_type]
418
+ ]
419
+ c2: list[Concept] = [
420
+ c for c in self.concepts if c.type != OperatorConcept.OPERATORS[c_type]
421
+ ]
422
+ if len(c1) > 0:
423
+ return inner_operator(
424
+ [outer_operator(c2 + [c]) for ci in c1 for c in ci.concepts]
425
+ )
426
+ return self
427
+
428
+ def reduce_idempotency(self, is_type: typing.Callable) -> typing.Self:
429
+ self.concepts: list[Concept] = [
430
+ c.reduce_idempotency(is_type) for c in self._concepts
431
+ ]
432
+ if self.is_complemented_atomic():
433
+ return self
434
+ if self.type in OperatorConcept.ABSORPTION_OPERATORS:
435
+ self.concepts = sorted(set(self.concepts))
436
+ if TruthConcept.get_top() in self.concepts and OperatorConcept.is_or(self.type):
437
+ return TruthConcept.get_top()
438
+ elif TruthConcept.get_bottom() in self.concepts and OperatorConcept.is_and(
439
+ self.type
440
+ ):
441
+ return TruthConcept.get_bottom()
442
+ if (
443
+ self.type
444
+ in OperatorConcept.COMPLEMENT_LAW_OPERATORS
445
+ # or constants.KNOWLEDGE_BASE_SEMANTICS == FuzzyLogic.CLASSICAL
446
+ # and (OperatorConcept.is_and(self.type) or OperatorConcept.is_or(self.type))
447
+ ):
448
+ if any(-c in self.concepts for c in self.concepts):
449
+ return (
450
+ TruthConcept.get_top()
451
+ if OperatorConcept.is_or(self.type)
452
+ else TruthConcept.get_bottom()
453
+ )
454
+ self.concepts: list[Concept] = sorted(
455
+ [
456
+ a
457
+ for a in self.concepts
458
+ if a not in [TruthConcept.get_bottom(), TruthConcept.get_top()]
459
+ ]
460
+ )
461
+ if len(self.concepts) == 1:
462
+ return self.concepts[0]
463
+ return OperatorConcept.__op(self.type, self.concepts)
464
+
465
+ def reduce_quantifiers(self) -> typing.Self:
466
+ self.concepts: list[Concept] = [c.reduce_quantifiers() for c in self._concepts]
467
+ remaining_concepts: list[Concept] = []
468
+ all_groups: dict[str, list[Concept]] = dict()
469
+ some_groups: dict[str, list[Concept]] = dict()
470
+ all_reduced_concepts: list[Concept] = []
471
+ some_reduced_concepts: list[Concept] = []
472
+ for c in self.concepts:
473
+ if c.type not in (ConceptType.ALL, ConceptType.SOME):
474
+ remaining_concepts.append(c)
475
+ continue
476
+ c: AllSomeConcept = typing.cast(AllSomeConcept, c)
477
+ if c.type == ConceptType.ALL:
478
+ all_groups[c.role] = all_groups.get(c.role, []) + [c]
479
+ else:
480
+ some_groups[c.role] = some_groups.get(c.role, []) + [c]
481
+ if (
482
+ self.type in (ConceptType.AND, ConceptType.GOEDEL_AND)
483
+ or constants.KNOWLEDGE_BASE_SEMANTICS == FuzzyLogic.CLASSICAL
484
+ and OperatorConcept.is_and(self.type)
485
+ ):
486
+ if (
487
+ constants.KNOWLEDGE_BASE_SEMANTICS == FuzzyLogic.CLASSICAL
488
+ and OperatorConcept.is_and(self.type)
489
+ ):
490
+ and_: typing.Callable = OperatorConcept.and_
491
+ else:
492
+ and_: typing.Callable = OperatorConcept.goedel_and
493
+ for role in all_groups:
494
+ curr_concepts: list[AllSomeConcept] = all_groups[role]
495
+ if len(curr_concepts) == 1:
496
+ remaining_concepts.extend(curr_concepts)
497
+ continue
498
+ all_reduced_concepts.append(
499
+ AllSomeConcept.all(
500
+ role, and_(*[c.curr_concept for c in curr_concepts])
501
+ )
502
+ )
503
+ for role in some_groups:
504
+ curr_concepts: list[AllSomeConcept] = some_groups[role]
505
+ if len(curr_concepts) == 1:
506
+ remaining_concepts.extend(curr_concepts)
507
+ continue
508
+ some_reduced_concepts.extend(
509
+ [
510
+ AllSomeConcept.some(role, c.curr_concept)
511
+ for c in curr_concepts
512
+ if c.curr_concept.type != ConceptType.TOP
513
+ ]
514
+ )
515
+ return OperatorConcept.__op(
516
+ self.type,
517
+ remaining_concepts + all_reduced_concepts + some_reduced_concepts,
518
+ )
519
+
520
+ if self.type not in (ConceptType.OR, ConceptType.GOEDEL_OR) and (
521
+ constants.KNOWLEDGE_BASE_SEMANTICS != FuzzyLogic.CLASSICAL
522
+ or not OperatorConcept.is_or(self.type)
523
+ ):
524
+ return self
525
+ if (
526
+ constants.KNOWLEDGE_BASE_SEMANTICS == FuzzyLogic.CLASSICAL
527
+ and OperatorConcept.is_or(self.type)
528
+ ):
529
+ or_: typing.Callable = OperatorConcept.or_
530
+ else:
531
+ or_: typing.Callable = OperatorConcept.goedel_or
532
+
533
+ for role in all_groups:
534
+ remaining_concepts.extend(all_groups[role])
535
+
536
+ some_reduced_concepts = []
537
+ for role in some_groups:
538
+ curr_concepts: list[AllSomeConcept] = some_groups[role]
539
+ if len(curr_concepts) == 1:
540
+ remaining_concepts.extend(curr_concepts)
541
+ continue
542
+ some_reduced_concepts.append(
543
+ AllSomeConcept.some(role, or_(*[c.curr_concept for c in curr_concepts]))
544
+ )
545
+
546
+ return OperatorConcept.__op(
547
+ self.type,
548
+ remaining_concepts + all_reduced_concepts + some_reduced_concepts,
549
+ )
550
+
551
+ def normal_form(self, is_type: typing.Callable) -> typing.Self:
552
+ c_type: ConceptType = next(
553
+ filter(
554
+ is_type,
555
+ OperatorConcept.BINARY_OPERATORS,
556
+ )
557
+ )
558
+ while True:
559
+ self: Concept = self.de_morgan()
560
+ self: Concept = self.reduce_double_negation()
561
+ self: Concept = self.distribute(c_type)
562
+ self: Concept = self.reduce_idempotency(is_type)
563
+ self: Concept = self.reduce_truth_values()
564
+ self: Concept = self.reduce_quantifiers()
565
+ if self.is_simplified():
566
+ break
567
+ return self
568
+
569
+ def get_clauses(self, is_type: typing.Callable) -> list[Concept]:
570
+ if self.type == ConceptType.COMPLEMENT:
571
+ return [self]
572
+ return self.concepts
573
+
574
+ def replace(self, a: Concept, c: Concept) -> Concept:
575
+ c_type: ConceptType = c.type
576
+ replaced_concepts: list[Concept] = [ci.replace(a, c) for ci in self.concepts]
577
+ if c_type == ConceptType.AND:
578
+ return OperatorConcept.and_(replaced_concepts)
579
+ elif c_type == ConceptType.GOEDEL_AND:
580
+ return OperatorConcept.goedel_and(replaced_concepts)
581
+ elif c_type == ConceptType.LUKASIEWICZ_AND:
582
+ return OperatorConcept.lukasiewicz_and(replaced_concepts)
583
+ if c_type == ConceptType.OR:
584
+ return OperatorConcept.or_(replaced_concepts)
585
+ elif c_type == ConceptType.GOEDEL_AND:
586
+ return OperatorConcept.goedel_or(replaced_concepts)
587
+ elif c_type == ConceptType.LUKASIEWICZ_AND:
588
+ return OperatorConcept.lukasiewicz_or(replaced_concepts)
589
+ elif c_type == ConceptType.COMPLEMENT:
590
+ if self.concepts[0] == a:
591
+ return -c
592
+ return self
593
+
594
+ def compute_name(self) -> typing.Optional[str]:
595
+ concepts: str = " ".join(map(str, self.concepts))
596
+ if self.type == ConceptType.AND:
597
+ return f"(and {concepts})"
598
+ elif self.type == ConceptType.GOEDEL_AND:
599
+ return f"(g-and {concepts})"
600
+ elif self.type == ConceptType.LUKASIEWICZ_AND:
601
+ return f"(l-and {concepts})"
602
+ elif self.type == ConceptType.OR:
603
+ return f"(or {concepts})"
604
+ elif self.type == ConceptType.GOEDEL_OR:
605
+ return f"(g-or {concepts})"
606
+ elif self.type == ConceptType.LUKASIEWICZ_OR:
607
+ return f"(l-or {concepts})"
608
+ elif self.type == ConceptType.COMPLEMENT:
609
+ return f"(not {concepts})"
610
+
611
+ def compute_atomic_concepts(self) -> set[Concept]:
612
+ result: set[Concept] = set()
613
+ for c in self.concepts:
614
+ result.update(c.compute_atomic_concepts())
615
+ return result
616
+
617
+ def get_roles(self) -> set[str]:
618
+ return set().union(*[c.get_roles() for c in self.concepts])
619
+
620
+ def __neg__(self) -> Concept:
621
+ concepts: list[Concept] = [-ci for ci in self.concepts]
622
+ if self.type == ConceptType.AND:
623
+ return OperatorConcept.or_(*concepts)
624
+ elif self.type == ConceptType.GOEDEL_AND:
625
+ return OperatorConcept.goedel_or(*concepts)
626
+ elif self.type == ConceptType.LUKASIEWICZ_AND:
627
+ return OperatorConcept.lukasiewicz_or(*concepts)
628
+ elif self.type == ConceptType.OR:
629
+ return OperatorConcept.and_(*concepts)
630
+ elif self.type == ConceptType.GOEDEL_OR:
631
+ return OperatorConcept.goedel_and(*concepts)
632
+ elif self.type == ConceptType.LUKASIEWICZ_OR:
633
+ return OperatorConcept.lukasiewicz_and(*concepts)
634
+ elif self.type == ConceptType.COMPLEMENT:
635
+ return self.concepts[0]
636
+ raise NotImplementedError
637
+
638
+ def __and__(self, value: typing.Self) -> typing.Self:
639
+ if OperatorConcept.is_and(self.type):
640
+ return OperatorConcept.__op(self.type, [self, value])
641
+ elif OperatorConcept.is_or(self.type):
642
+ return OperatorConcept.__op(
643
+ OperatorConcept.OPERATORS[self.type], [self, value]
644
+ )
645
+ return OperatorConcept.and_([self, value])
646
+
647
+ def __or__(self, value: typing.Self) -> typing.Self:
648
+ if OperatorConcept.is_or(self.type):
649
+ return OperatorConcept.__op(self.type, [self, value])
650
+ elif OperatorConcept.is_and(self.type):
651
+ return OperatorConcept.__op(
652
+ OperatorConcept.OPERATORS[self.type], [self, value]
653
+ )
654
+ return OperatorConcept.or_([self, value])
655
+
656
+ def __eq__(self, value: typing.Self) -> bool:
657
+ return isinstance(value, OperatorConcept) and str(self) == str(value)
658
+
659
+ def __ne__(self, value: typing.Self) -> bool:
660
+ return not (self == value)
661
+
662
+ def __hash__(self) -> int:
663
+ return hash(str(self))
664
+
665
+
666
+ # class Not(OperatorConcept):
667
+ # def __call__(self, *args) -> typing.Self:
668
+ # return OperatorConcept.not_(args)
669
+
670
+
671
+ # class And(OperatorConcept):
672
+ # def __call__(self, *args) -> typing.Self:
673
+ # return OperatorConcept.and_(args)
674
+
675
+
676
+ # class GoedelAnd(OperatorConcept):
677
+ # def __call__(self, *args) -> typing.Self:
678
+ # return OperatorConcept.goedel_and(args)
679
+
680
+
681
+ # class LukasiewiczAnd(OperatorConcept):
682
+ # def __call__(self, *args) -> typing.Self:
683
+ # return OperatorConcept.lukasiewicz_and(args)
684
+
685
+
686
+ # class Or(OperatorConcept):
687
+ # def __call__(self, *args) -> typing.Self:
688
+ # return OperatorConcept.or_(args)
689
+
690
+
691
+ # class GoedelOr(OperatorConcept):
692
+ # def __call__(self, *args) -> typing.Self:
693
+ # return OperatorConcept.goedel_or(args)
694
+
695
+
696
+ # class LukasiewiczOr(OperatorConcept):
697
+ # def __call__(self, *args) -> typing.Self:
698
+ # return OperatorConcept.lukasiewicz_or(args)
699
+
700
+
701
+ Not = OperatorConcept.not_
702
+ And = OperatorConcept.and_
703
+ GoedelAnd = OperatorConcept.goedel_and
704
+ LukasiewiczAnd = OperatorConcept.lukasiewicz_and
705
+ Or = OperatorConcept.or_
706
+ GoedelOr = OperatorConcept.goedel_or
707
+ LukasiewiczOr = OperatorConcept.lukasiewicz_or