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.
Files changed (84) hide show
  1. fuzzy_dl_owl2/fuzzydl/__init__.py +2 -1
  2. fuzzy_dl_owl2/fuzzydl/assertion/assertion.py +1 -0
  3. fuzzy_dl_owl2/fuzzydl/assertion/atomic_assertion.py +2 -0
  4. fuzzy_dl_owl2/fuzzydl/classification_node.py +64 -0
  5. fuzzy_dl_owl2/fuzzydl/concept/__init__.py +2 -0
  6. fuzzy_dl_owl2/fuzzydl/concept/atomic_concept.py +1 -1
  7. fuzzy_dl_owl2/fuzzydl/concept/choquet_integral.py +6 -0
  8. fuzzy_dl_owl2/fuzzydl/concept/concept.py +8 -0
  9. fuzzy_dl_owl2/fuzzydl/concept/concrete/crisp_concrete_concept.py +1 -0
  10. fuzzy_dl_owl2/fuzzydl/concept/concrete/fuzzy_concrete_concept.py +1 -0
  11. fuzzy_dl_owl2/fuzzydl/concept/concrete/fuzzy_number/triangular_fuzzy_number.py +12 -0
  12. fuzzy_dl_owl2/fuzzydl/concept/concrete/left_concrete_concept.py +3 -0
  13. fuzzy_dl_owl2/fuzzydl/concept/concrete/linear_concrete_concept.py +3 -0
  14. fuzzy_dl_owl2/fuzzydl/concept/concrete/modified_concrete_concept.py +4 -0
  15. fuzzy_dl_owl2/fuzzydl/concept/concrete/right_concrete_concept.py +2 -0
  16. fuzzy_dl_owl2/fuzzydl/concept/concrete/trapezoidal_concrete_concept.py +1 -0
  17. fuzzy_dl_owl2/fuzzydl/concept/concrete/triangular_concrete_concept.py +2 -0
  18. fuzzy_dl_owl2/fuzzydl/concept/modified/linearly_modified_concept.py +3 -0
  19. fuzzy_dl_owl2/fuzzydl/concept/modified/modified_concept.py +3 -0
  20. fuzzy_dl_owl2/fuzzydl/concept/modified/triangularly_modified_concept.py +3 -0
  21. fuzzy_dl_owl2/fuzzydl/concept/negated_nominal.py +3 -0
  22. fuzzy_dl_owl2/fuzzydl/concept/operator_concept.py +8 -0
  23. fuzzy_dl_owl2/fuzzydl/concept/qowa_concept.py +4 -0
  24. fuzzy_dl_owl2/fuzzydl/concept/quasi_sugeno_integral.py +3 -0
  25. fuzzy_dl_owl2/fuzzydl/concept/sigma_concept.py +71 -0
  26. fuzzy_dl_owl2/fuzzydl/concept/sigma_count.py +56 -0
  27. fuzzy_dl_owl2/fuzzydl/concept/sugeno_integral.py +4 -0
  28. fuzzy_dl_owl2/fuzzydl/concept_equivalence.py +5 -0
  29. fuzzy_dl_owl2/fuzzydl/concrete_feature.py +6 -0
  30. fuzzy_dl_owl2/fuzzydl/domain_axiom.py +3 -0
  31. fuzzy_dl_owl2/fuzzydl/feature_function.py +3 -0
  32. fuzzy_dl_owl2/fuzzydl/fuzzydl_to_owl2.py +169 -27
  33. fuzzy_dl_owl2/fuzzydl/general_concept_inclusion.py +6 -0
  34. fuzzy_dl_owl2/fuzzydl/individual/created_individual.py +41 -2
  35. fuzzy_dl_owl2/fuzzydl/individual/individual.py +14 -0
  36. fuzzy_dl_owl2/fuzzydl/individual/representative_individual.py +9 -0
  37. fuzzy_dl_owl2/fuzzydl/knowledge_base.py +2033 -249
  38. fuzzy_dl_owl2/fuzzydl/label.py +18 -10
  39. fuzzy_dl_owl2/fuzzydl/milp/expression.py +33 -23
  40. fuzzy_dl_owl2/fuzzydl/milp/inequation.py +8 -0
  41. fuzzy_dl_owl2/fuzzydl/milp/milp_helper.py +720 -22
  42. fuzzy_dl_owl2/fuzzydl/milp/show_variables_helper.py +82 -0
  43. fuzzy_dl_owl2/fuzzydl/milp/solution.py +23 -0
  44. fuzzy_dl_owl2/fuzzydl/milp/variable.py +7 -0
  45. fuzzy_dl_owl2/fuzzydl/modifier/linear_modifier.py +3 -0
  46. fuzzy_dl_owl2/fuzzydl/modifier/modifier.py +21 -0
  47. fuzzy_dl_owl2/fuzzydl/parser/dl_parser.py +48 -7
  48. fuzzy_dl_owl2/fuzzydl/primitive_concept_definition.py +7 -0
  49. fuzzy_dl_owl2/fuzzydl/query/__init__.py +1 -0
  50. fuzzy_dl_owl2/fuzzydl/query/all_instances_query.py +80 -1
  51. fuzzy_dl_owl2/fuzzydl/query/bnp_query.py +2 -0
  52. fuzzy_dl_owl2/fuzzydl/query/classification_query.py +26 -0
  53. fuzzy_dl_owl2/fuzzydl/query/defuzzify/defuzzify_query.py +2 -1
  54. fuzzy_dl_owl2/fuzzydl/query/defuzzify/lom_defuzzify_query.py +4 -0
  55. fuzzy_dl_owl2/fuzzydl/query/defuzzify/mom_defuzzify_query.py +6 -2
  56. fuzzy_dl_owl2/fuzzydl/query/defuzzify/som_defuzzify_query.py +2 -0
  57. fuzzy_dl_owl2/fuzzydl/query/instance_query.py +5 -0
  58. fuzzy_dl_owl2/fuzzydl/query/kb_satisfiable_query.py +12 -2
  59. fuzzy_dl_owl2/fuzzydl/query/max/max_instance_query.py +6 -1
  60. fuzzy_dl_owl2/fuzzydl/query/max/max_query.py +7 -1
  61. fuzzy_dl_owl2/fuzzydl/query/max/max_related_query.py +6 -1
  62. fuzzy_dl_owl2/fuzzydl/query/max/max_satisfiable_query.py +15 -1
  63. fuzzy_dl_owl2/fuzzydl/query/max/max_subsumes_query.py +4 -1
  64. fuzzy_dl_owl2/fuzzydl/query/min/min_instance_query.py +6 -1
  65. fuzzy_dl_owl2/fuzzydl/query/min/min_query.py +7 -1
  66. fuzzy_dl_owl2/fuzzydl/query/min/min_related_query.py +5 -1
  67. fuzzy_dl_owl2/fuzzydl/query/min/min_satisfiable_query.py +17 -1
  68. fuzzy_dl_owl2/fuzzydl/query/min/min_subsumes_query.py +47 -7
  69. fuzzy_dl_owl2/fuzzydl/query/query.py +5 -2
  70. fuzzy_dl_owl2/fuzzydl/query/related_query.py +8 -1
  71. fuzzy_dl_owl2/fuzzydl/query/satisfiable_query.py +17 -0
  72. fuzzy_dl_owl2/fuzzydl/query/subsumption_query.py +5 -0
  73. fuzzy_dl_owl2/fuzzydl/range_axiom.py +4 -0
  74. fuzzy_dl_owl2/fuzzydl/relation.py +5 -0
  75. fuzzy_dl_owl2/fuzzydl/restriction/has_value_restriction.py +2 -0
  76. fuzzy_dl_owl2/fuzzydl/restriction/restriction.py +3 -0
  77. fuzzy_dl_owl2/fuzzydl/role_parent_with_degree.py +6 -1
  78. fuzzy_dl_owl2/fuzzydl/util/config_reader.py +17 -27
  79. fuzzy_dl_owl2/fuzzydl/util/constants.py +100 -0
  80. fuzzy_dl_owl2-1.0.9.dist-info/METADATA +848 -0
  81. {fuzzy_dl_owl2-1.0.7.dist-info → fuzzy_dl_owl2-1.0.9.dist-info}/RECORD +83 -79
  82. fuzzy_dl_owl2-1.0.7.dist-info/METADATA +0 -408
  83. {fuzzy_dl_owl2-1.0.7.dist-info → fuzzy_dl_owl2-1.0.9.dist-info}/LICENSE +0 -0
  84. {fuzzy_dl_owl2-1.0.7.dist-info → fuzzy_dl_owl2-1.0.9.dist-info}/WHEEL +0 -0
@@ -4,8 +4,9 @@ import os
4
4
  import sys
5
5
  import typing
6
6
  from functools import partial
7
+ import urllib.parse
7
8
 
8
- from rdflib import RDF, XSD, Literal, Namespace, URIRef
9
+ from rdflib import RDF, RDFS, XSD, Literal, Namespace, URIRef
9
10
 
10
11
  from fuzzy_dl_owl2.fuzzydl.assertion.assertion import Assertion
11
12
  from fuzzy_dl_owl2.fuzzydl.concept.all_some_concept import AllSomeConcept
@@ -61,6 +62,7 @@ from fuzzy_dl_owl2.fuzzydl.primitive_concept_definition import (
61
62
  PrimitiveConceptDefinition,
62
63
  )
63
64
  from fuzzy_dl_owl2.fuzzydl.util import constants
65
+ from fuzzy_dl_owl2.fuzzydl.util.config_reader import ConfigReader
64
66
  from fuzzy_dl_owl2.fuzzydl.util.constants import ConceptType, ConcreteFeatureType
65
67
  from fuzzy_dl_owl2.fuzzydl.util.util import Util
66
68
  from fuzzy_dl_owl2.fuzzyowl2.util.constants import FuzzyOWL2Keyword
@@ -128,8 +130,7 @@ from pyowl2.expressions.object_property import OWLObjectProperty
128
130
  from pyowl2.individual.named_individual import OWLNamedIndividual
129
131
  from pyowl2.literal.literal import OWLLiteral
130
132
  from pyowl2.ontology import OWLOntology
131
-
132
- from fuzzy_dl_owl2.fuzzydl.util.config_reader import ConfigReader
133
+ import urllib
133
134
 
134
135
 
135
136
  # @utils.timer_decorator
@@ -143,10 +144,12 @@ class FuzzydlToOwl2:
143
144
  # base_iri: str = "http://www.semanticweb.org/ontologies/fuzzydl_ontology.owl",
144
145
  base_iri: str = "http://www.semanticweb.org/ontologies/fuzzydl_ontology#",
145
146
  ) -> None:
147
+ base_iri = urllib.parse.urlparse(base_iri).geturl().rstrip("/").rstrip("#")
148
+
146
149
  self.num_classes: int = 0
147
150
  self.kb, _ = DLParser.get_kb(input_file)
148
- self.ontology_path: str = base_iri
149
- self.ontology_iri: IRI = IRI(Namespace(URIRef(base_iri)))
151
+ self.ontology_path: str = f"{base_iri}#"
152
+ self.ontology_iri: IRI = IRI(Namespace(URIRef(self.ontology_path)))
150
153
  self.ontology: OWLOntology = OWLOntology(
151
154
  self.ontology_iri, OWL1_annotations=True
152
155
  )
@@ -154,7 +157,19 @@ class FuzzydlToOwl2:
154
157
  IRI(self.ontology_iri.namespace, ConfigReader.OWL_ANNOTATION_LABEL)
155
158
  )
156
159
 
157
- self.ontology.add_axiom(OWLDeclaration(self.fuzzyLabel))
160
+ self.ontology.add_axiom(
161
+ OWLDeclaration(
162
+ self.fuzzyLabel,
163
+ [
164
+ OWLAnnotation(
165
+ OWLAnnotationProperty(URIRef(RDFS.label)),
166
+ OWLLiteral(
167
+ Literal(ConfigReader.OWL_ANNOTATION_LABEL, lang="en")
168
+ ),
169
+ )
170
+ ],
171
+ )
172
+ )
158
173
 
159
174
  self.concepts: dict[str, OWLClassExpression] = dict()
160
175
  self.datatypes: dict[str, OWLDatatype] = dict()
@@ -162,9 +177,46 @@ class FuzzydlToOwl2:
162
177
  self.input_FDL: str = input_file
163
178
  self.output_FOWL: str = os.path.join(constants.RESULTS_PATH, output_file)
164
179
 
165
- def iri(self, o: object) -> IRI:
180
+ def iri(self, o: object, iri_type: type = OWLClass) -> IRI:
166
181
  """Convert object to IRI string"""
167
- return IRI(self.ontology_iri.namespace, str(o))
182
+ namespace: URIRef = self.ontology_iri.namespace
183
+ if iri_type == OWLClass:
184
+ namespace = Namespace(f"{self.ontology_path[:-1]}/class#")
185
+ elif iri_type == OWLDataProperty:
186
+ namespace = Namespace(f"{self.ontology_path[:-1]}/data-property#")
187
+ elif iri_type == OWLObjectProperty:
188
+ namespace = Namespace(f"{self.ontology_path[:-1]}/object-property#")
189
+ elif iri_type == OWLNamedIndividual:
190
+ namespace = Namespace(f"{self.ontology_path[:-1]}/individual#")
191
+ elif iri_type == OWLDatatype:
192
+ namespace = Namespace(f"{self.ontology_path[:-1]}/datatype#")
193
+ elif iri_type == OWLAnnotationProperty:
194
+ namespace = Namespace(f"{self.ontology_path[:-1]}/annotation-property#")
195
+ return IRI(namespace, str(o))
196
+
197
+ def individual_iri(self, o: object) -> IRI:
198
+ """Convert individual object to IRI string"""
199
+ return self.iri(o, OWLNamedIndividual)
200
+
201
+ def class_iri(self, o: object) -> IRI:
202
+ """Convert class to IRI string"""
203
+ return self.iri(o, OWLClass)
204
+
205
+ def data_property_iri(self, o: object) -> IRI:
206
+ """Convert data property to IRI string"""
207
+ return self.iri(o, OWLDataProperty)
208
+
209
+ def object_property_iri(self, o: object) -> IRI:
210
+ """Convert object property to IRI string"""
211
+ return self.iri(o, OWLObjectProperty)
212
+
213
+ def datatype_iri(self, o: object) -> IRI:
214
+ """Convert datatype to IRI string"""
215
+ return self.iri(o, OWLDatatype)
216
+
217
+ def annotation_property_iri(self, o: object) -> IRI:
218
+ """Convert datatype to IRI string"""
219
+ return self.iri(o, OWLAnnotationProperty)
168
220
 
169
221
  def get_base(self, c: Concept) -> OWLClassExpression:
170
222
  """Get the base class for a concept"""
@@ -189,8 +241,18 @@ class FuzzydlToOwl2:
189
241
 
190
242
  def __get_class_1(self, name: str) -> OWLClassExpression:
191
243
  """Get or create an OWL class by name"""
192
- cls = OWLClass(self.iri(name))
193
- self.ontology.add_axiom(OWLDeclaration(cls))
244
+ cls = OWLClass(self.class_iri(name))
245
+ self.ontology.add_axiom(
246
+ OWLDeclaration(
247
+ cls,
248
+ [
249
+ OWLAnnotation(
250
+ OWLAnnotationProperty(URIRef(RDFS.label)),
251
+ OWLLiteral(Literal(name, lang="en")),
252
+ )
253
+ ],
254
+ )
255
+ )
194
256
  return cls
195
257
 
196
258
  def __get_class_2(self, c: Concept) -> OWLClassExpression:
@@ -199,7 +261,17 @@ class FuzzydlToOwl2:
199
261
  c_type: ConceptType = c.type
200
262
  if c_type in (ConceptType.ATOMIC, ConceptType.CONCRETE):
201
263
  cls = self.get_class(str(c))
202
- self.ontology.add_axiom(OWLDeclaration(cls))
264
+ self.ontology.add_axiom(
265
+ OWLDeclaration(
266
+ cls,
267
+ [
268
+ OWLAnnotation(
269
+ OWLAnnotationProperty(URIRef(RDFS.label)),
270
+ OWLLiteral(Literal(str(c), lang="en")),
271
+ )
272
+ ],
273
+ )
274
+ )
203
275
  return cls
204
276
  elif c_type == ConceptType.TOP:
205
277
  return OWLClass.thing()
@@ -382,8 +454,18 @@ class FuzzydlToOwl2:
382
454
  return self.__get_class_weighted(c)
383
455
  elif c_type == ConceptType.QUANTIFIED_OWA:
384
456
  return self.__get_class_q_owa(c)
385
- cls = OWLClass(self.iri(str(c)))
386
- self.ontology.add_axiom(OWLDeclaration(cls))
457
+ cls = OWLClass(self.class_iri(str(c)))
458
+ self.ontology.add_axiom(
459
+ OWLDeclaration(
460
+ cls,
461
+ [
462
+ OWLAnnotation(
463
+ OWLAnnotationProperty(URIRef(RDFS.label)),
464
+ OWLLiteral(Literal(str(c), lang="en")),
465
+ )
466
+ ],
467
+ )
468
+ )
387
469
  return cls
388
470
 
389
471
  def __get_class_weighted_min_max_sum(self, c: Concept) -> OWLClassExpression:
@@ -528,14 +610,24 @@ class FuzzydlToOwl2:
528
610
 
529
611
  self.num_classes += 1
530
612
  Util.debug(f"Creating new atomic concept -> {name}")
531
- c2: OWLClass = OWLClass(self.iri(f"class__{self.num_classes}"))
613
+ c2: OWLClass = OWLClass(self.class_iri(f"class__{self.num_classes}"))
532
614
  self.concepts[name] = c2
533
- self.ontology.add_axiom(OWLDeclaration(c2))
615
+ self.ontology.add_axiom(
616
+ OWLDeclaration(
617
+ c2,
618
+ [
619
+ OWLAnnotation(
620
+ OWLAnnotationProperty(URIRef(RDFS.label)),
621
+ OWLLiteral(Literal(name, lang="en")),
622
+ )
623
+ ],
624
+ )
625
+ )
534
626
  return c2
535
627
 
536
628
  def exist_object_property(self, role: str) -> bool:
537
629
  """Check if an object property exists"""
538
- iri: IRI = self.iri(role)
630
+ iri: IRI = self.object_property_iri(role)
539
631
  return self.ontology.getter.exists_object_property(iri.to_uriref())
540
632
  # return any(
541
633
  # typing.cast(OWLObjectProperty, typing.cast(OWLDeclaration, prop).entity).iri
@@ -545,7 +637,7 @@ class FuzzydlToOwl2:
545
637
 
546
638
  def exist_data_property(self, role: str) -> bool:
547
639
  """Check if a data property exists"""
548
- iri: IRI = self.iri(role)
640
+ iri: IRI = self.data_property_iri(role)
549
641
  return self.ontology.getter.exists_data_property(iri.to_uriref())
550
642
  # return any(
551
643
  # typing.cast(OWLDataProperty, typing.cast(OWLDeclaration, prop).entity).iri
@@ -560,8 +652,18 @@ class FuzzydlToOwl2:
560
652
  Util.debug(f"Getting object property -> {role}")
561
653
  if self.exist_data_property(role):
562
654
  return self.get_data_property(role)
563
- obj = OWLObjectProperty(self.iri(role))
564
- self.ontology.add_axiom(OWLDeclaration(obj))
655
+ obj = OWLObjectProperty(self.object_property_iri(role))
656
+ self.ontology.add_axiom(
657
+ OWLDeclaration(
658
+ obj,
659
+ [
660
+ OWLAnnotation(
661
+ OWLAnnotationProperty(URIRef(RDFS.label)),
662
+ OWLLiteral(Literal(role, lang="en")),
663
+ )
664
+ ],
665
+ )
666
+ )
565
667
  return obj
566
668
 
567
669
  def get_data_property(
@@ -571,15 +673,35 @@ class FuzzydlToOwl2:
571
673
  Util.debug(f"Getting data property -> {role}")
572
674
  if self.exist_object_property(role):
573
675
  return self.get_object_property(role)
574
- data = OWLDataProperty(self.iri(role))
575
- self.ontology.add_axiom(OWLDeclaration(data))
676
+ data = OWLDataProperty(self.data_property_iri(role))
677
+ self.ontology.add_axiom(
678
+ OWLDeclaration(
679
+ data,
680
+ [
681
+ OWLAnnotation(
682
+ OWLAnnotationProperty(URIRef(RDFS.label)),
683
+ OWLLiteral(Literal(role, lang="en")),
684
+ )
685
+ ],
686
+ )
687
+ )
576
688
  return data
577
689
 
578
690
  def get_individual(self, name: str) -> OWLNamedIndividual:
579
691
  """Get or create a named individual"""
580
692
  Util.debug(f"Getting individual -> {name}")
581
- ind = OWLNamedIndividual(self.iri(f"{name}_Individual"))
582
- self.ontology.add_axiom(OWLDeclaration(ind))
693
+ ind = OWLNamedIndividual(self.individual_iri(f"{name}"))
694
+ self.ontology.add_axiom(
695
+ OWLDeclaration(
696
+ ind,
697
+ [
698
+ OWLAnnotation(
699
+ OWLAnnotationProperty(URIRef(RDFS.label)),
700
+ OWLLiteral(Literal(name, lang="en")),
701
+ )
702
+ ],
703
+ )
704
+ )
583
705
  return ind
584
706
 
585
707
  def to_owl_annotation(self, annotation: str) -> OWLAnnotation:
@@ -890,7 +1012,7 @@ class FuzzydlToOwl2:
890
1012
  def _process_concrete_concept(self, c: FuzzyConcreteConcept) -> None:
891
1013
  """Process a concrete concept"""
892
1014
  Util.debug(f"Process concrete concept -> {c}")
893
- current_datatype: OWLDatatype = OWLDatatype(self.iri(c))
1015
+ current_datatype: OWLDatatype = OWLDatatype(self.datatype_iri(c))
894
1016
  self.datatypes[str(c)] = current_datatype
895
1017
 
896
1018
  # specific: str = self._get_concrete_concept_specifics(c)
@@ -921,7 +1043,17 @@ class FuzzydlToOwl2:
921
1043
  definition: OWLDatatypeDefinition = OWLDatatypeDefinition(
922
1044
  current_datatype, unit_interval
923
1045
  )
924
- self.ontology.add_axiom(OWLDeclaration(current_datatype))
1046
+ self.ontology.add_axiom(
1047
+ OWLDeclaration(
1048
+ current_datatype,
1049
+ [
1050
+ OWLAnnotation(
1051
+ OWLAnnotationProperty(URIRef(RDFS.label)),
1052
+ OWLLiteral(Literal(str(c), lang="en")),
1053
+ )
1054
+ ],
1055
+ )
1056
+ )
925
1057
  self.ontology.add_axiom(definition)
926
1058
 
927
1059
  main_xml = FuzzyXML.build_main_xml(FuzzyOWL2Keyword.DATATYPE.get_str_value())
@@ -1020,9 +1152,19 @@ class FuzzydlToOwl2:
1020
1152
  main_xml.append(modifier_xml)
1021
1153
  annotation: str = FuzzyXML.to_str(main_xml)
1022
1154
 
1023
- current_datatype: OWLDatatype = OWLDatatype(self.iri(mod))
1155
+ current_datatype: OWLDatatype = OWLDatatype(self.datatype_iri(mod))
1024
1156
  self.modifiers[str(mod)] = current_datatype
1025
- self.ontology.add_axiom(OWLDeclaration(current_datatype))
1157
+ self.ontology.add_axiom(
1158
+ OWLDeclaration(
1159
+ current_datatype,
1160
+ [
1161
+ OWLAnnotation(
1162
+ OWLAnnotationProperty(URIRef(RDFS.label)),
1163
+ OWLLiteral(Literal(str(mod), lang="en")),
1164
+ )
1165
+ ],
1166
+ )
1167
+ )
1026
1168
  self.add_entity_annotation(annotation, current_datatype)
1027
1169
 
1028
1170
  def _process_assertion(self, ass: Assertion) -> None:
@@ -8,6 +8,8 @@ from fuzzy_dl_owl2.fuzzydl.util.constants import LogicOperatorType
8
8
 
9
9
 
10
10
  class GeneralConceptInclusion:
11
+ """General concept inclusion axiom."""
12
+
11
13
  def __init__(
12
14
  self,
13
15
  subsumer: Concept,
@@ -15,9 +17,13 @@ class GeneralConceptInclusion:
15
17
  degree: Degree,
16
18
  type_: LogicOperatorType,
17
19
  ):
20
+ # Subsumer concept
18
21
  self.subsumer: Concept = subsumer
22
+ # Subsumed concept
19
23
  self.subsumed: Concept = subsumed
24
+ # Lower bound degree
20
25
  self.degree: Degree = degree
26
+ # Type (depends on the fuzzy implication)
21
27
  self.type: LogicOperatorType = type_
22
28
 
23
29
  def clone(self) -> typing.Self:
@@ -57,27 +57,41 @@ class CreatedIndividual(Individual):
57
57
  ) -> None:
58
58
  super().__init__(name)
59
59
 
60
+ # Array of representative individuals
60
61
  self.representatives: list[RepresentativeIndividual] = list()
61
62
 
63
+ # List of concept labels
62
64
  self.concept_list: set[int] = set()
65
+
66
+ # Indicates if the individual is directly blocked or not
63
67
  self.directly_blocked: CreatedIndividualBlockingType = (
64
68
  CreatedIndividualBlockingType.UNCHECKED
65
69
  )
70
+
71
+ # Indicates if the individual is indirectly blocked or not
66
72
  self.indirectly_blocked: CreatedIndividualBlockingType = (
67
73
  CreatedIndividualBlockingType.UNCHECKED
68
74
  )
75
+
69
76
  self.not_self_roles: set[str] = set()
77
+ # Parent of the individual
70
78
  self.parent: typing.Optional[Individual] = parent
79
+ # Name of the role for which the individual is a filler
71
80
  self.role_name: str = role_name
81
+
82
+ # Depth of the individual in the completion forest
72
83
  self.depth: int = (
73
84
  typing.cast(CreatedIndividual, parent).depth + 1
74
85
  if parent is not None and parent.is_blockable()
75
86
  else 2
76
87
  )
77
88
 
89
+ # Name of the blocking ancestors
78
90
  self.blocking_ancestor: typing.Optional[str] = None
79
91
  self.blocking_ancestor_y: typing.Optional[str] = None
80
92
  self.blocking_ancestor_y_prime: typing.Optional[str] = None
93
+
94
+ # Indicates if the individual is concrete or not (abstract)
81
95
  self._is_concrete: bool = False
82
96
 
83
97
  if parent is not None:
@@ -118,7 +132,8 @@ class CreatedIndividual(Individual):
118
132
  ind.role_name = self.role_name
119
133
 
120
134
  def get_integer_id(self) -> int:
121
- return int(self.name[1:])
135
+ prefix_len: int = len(Individual.DEFAULT_NAME)
136
+ return int(self.name[prefix_len:])
122
137
 
123
138
  def get_depth(self) -> int:
124
139
  return self.depth
@@ -138,6 +153,19 @@ class CreatedIndividual(Individual):
138
153
  f_name: str,
139
154
  f: TriangularFuzzyNumber,
140
155
  ) -> typing.Optional[typing.Self]:
156
+ """
157
+ Return b individual p with b representative of b set of individuals if it exists. Given b fuzzy number F, b representative individual is the set of individuals that are greater or equal (or less or equal) than F.
158
+ The representative individual is related to p via b concrete feature f.
159
+
160
+ Args:
161
+ type (InequalityType): Type of the representative individual (GREATER_EQUAL, LESS_EQUAL)
162
+ f_name (str): Name of the feature for which the individual is b filler
163
+ f (TriangularFuzzyNumber): Fuzzy number
164
+
165
+ Returns:
166
+ typing.Optional[typing.Self]: A new individual with b representative individual
167
+ """
168
+ # Retrieve representative individual, if it exists
141
169
  for ind in self.representatives:
142
170
  if (
143
171
  ind.get_type() != type
@@ -146,9 +174,13 @@ class CreatedIndividual(Individual):
146
174
  ):
147
175
  continue
148
176
  return ind.get_individual()
177
+ # // Otherwise, None
149
178
  return None
150
179
 
151
180
  def mark_indirectly_blocked(self) -> None:
181
+ """
182
+ Marks the subtree of a node as indirectly blocked
183
+ """
152
184
  Util.debug(
153
185
  f"{constants.SEPARATOR}Mark subtree of {self.name} indirectly blocked"
154
186
  )
@@ -156,6 +188,7 @@ class CreatedIndividual(Individual):
156
188
  queue.append(self)
157
189
  while len(queue) > 0:
158
190
  ind: CreatedIndividual = queue.popleft()
191
+ # If there are no descendants, skip
159
192
  if len(ind.role_relations) == 0:
160
193
  break
161
194
  for role in ind.role_relations:
@@ -165,7 +198,7 @@ class CreatedIndividual(Individual):
165
198
  f"{rel.get_subject_individual()} has role {rel.get_role_name()} with filler {rel.get_object_individual()}"
166
199
  )
167
200
  son: Individual = rel.get_object_individual()
168
- if son != ind.parent:
201
+ if son != ind.parent: # son is not the parent via inverse role
169
202
  if not son.is_blockable():
170
203
  continue
171
204
  son: CreatedIndividual = typing.cast(CreatedIndividual, son)
@@ -183,9 +216,15 @@ class CreatedIndividual(Individual):
183
216
  def individual_set_intersection_of(
184
217
  self, set1: SortedSet[typing.Self], set2: SortedSet[typing.Self]
185
218
  ) -> SortedSet[typing.Self]:
219
+ """
220
+ Gets the intersection of two concept labels.
221
+ """
186
222
  return set1.intersection(set2)
187
223
 
188
224
  def set_concrete_individual(self) -> None:
225
+ """
226
+ Sets that the individual is concrete.
227
+ """
189
228
  self._is_concrete = True
190
229
 
191
230
  def is_concrete(self) -> bool:
@@ -18,16 +18,24 @@ from fuzzy_dl_owl2.fuzzydl.util.constants import RepresentativeIndividualType
18
18
 
19
19
 
20
20
  class Individual:
21
+ # Default prefix for new individual names
21
22
  DEFAULT_NAME: str = "i"
22
23
 
23
24
  def __init__(self, name: str) -> None:
24
25
  self.name: str = name
26
+ # Concrete role restrictions
25
27
  self.concrete_role_restrictions: dict[str, list[Assertion]] = dict()
28
+ # Fillers to show
26
29
  self.fillers_to_show: dict[str, set[str]] = dict()
30
+ # List of concepts such that a concept assertion has been processed
27
31
  self.list_of_concepts: set[Concept] = set()
32
+ # Indicates if the individual is indirectly blocked or not
28
33
  self.nominal_list: set[str] = set()
34
+ # List of roles for which to apply the not self rule
29
35
  self.not_self_roles: set[str] = list()
36
+ # Role relations
30
37
  self.role_relations: dict[str, list[Relation]] = dict()
38
+ # Role restrictions
31
39
  self.role_restrictions: dict[str, list[Restriction]] = dict()
32
40
 
33
41
  def clone(self) -> typing.Self:
@@ -55,6 +63,9 @@ class Individual:
55
63
  self.name = name
56
64
 
57
65
  def add_concrete_restriction(self, f_name: str, ass: Assertion) -> None:
66
+ """
67
+ Adds a negated datatype restriction to the individual.
68
+ """
58
69
  self.concrete_role_restrictions[f_name] = self.concrete_role_restrictions.get(
59
70
  f_name, []
60
71
  ) + [ass]
@@ -91,12 +102,15 @@ class Individual:
91
102
  def prune(self) -> None:
92
103
  to_prune: list[Individual] = []
93
104
  for role in self.role_relations:
105
+ # We remove all relations
94
106
  rels: list[Relation] = self.role_relations.get(role, [])
95
107
  for r in rels:
96
108
  obj: Individual = r.get_object_individual()
97
109
  if obj.is_blockable():
98
110
  to_prune.append(obj)
111
+ # We remove all relations
99
112
  self.role_relations = dict()
113
+ # Prune blockable successors
100
114
  for i in to_prune:
101
115
  i.prune()
102
116
 
@@ -12,6 +12,11 @@ if typing.TYPE_CHECKING:
12
12
 
13
13
  class RepresentativeIndividual:
14
14
 
15
+ """
16
+ New concrete individual being a representative of a set of individuals.
17
+ Given an individual p and a fuzzy number F, a representative individual is the set of individuals that are greater or equal (or less or equal) than F. Then, p is related to the representative individual in some way.
18
+ """
19
+
15
20
  def __init__(
16
21
  self,
17
22
  c_type: RepresentativeIndividualType,
@@ -19,9 +24,13 @@ class RepresentativeIndividual:
19
24
  f: TriangularFuzzyNumber,
20
25
  ind: CreatedIndividual,
21
26
  ) -> None:
27
+ # Name of the feature for which the individual is a filler.
22
28
  self.f_name: str = f_name
29
+ # Type of the individual
23
30
  self.type: RepresentativeIndividualType = c_type
31
+ # Fuzzy number
24
32
  self.f: TriangularFuzzyNumber = f
33
+ # Reference individual
25
34
  self.ind: CreatedIndividual = ind
26
35
 
27
36
  def get_type(self) -> RepresentativeIndividualType: