fuzzy-dl-owl2 1.0.5__py3-none-any.whl → 1.0.7__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.
@@ -122,26 +122,32 @@ class FeatureFunction:
122
122
  self, a: Individual, milp: MILPHelper
123
123
  ) -> typing.Optional[Expression]:
124
124
  if self.type == FeatureFunctionType.ATOMIC:
125
+ # Get the filler "b" for feature(a)
125
126
  rel_set: list[Relation] = a.role_relations.get(self.feature)
127
+ assert len(rel_set) > 0
126
128
  b: CreatedIndividual = typing.cast(
127
129
  CreatedIndividual, rel_set[0].get_object_individual()
128
130
  )
131
+ # Get the variable xB
129
132
  x_b: Variable = milp.get_variable(b)
130
133
  return Expression(Term(1.0, x_b))
131
134
  elif self.type == FeatureFunctionType.NUMBER:
132
135
  return Expression(self.n)
133
136
  elif self.type == FeatureFunctionType.PRODUCT:
137
+ assert len(self.f) == 1
134
138
  ex: Expression = self.f[0].to_expression(a, milp)
135
- return Expression.multiply_constant(ex, self.n)
139
+ return ex * self.n
136
140
  elif self.type == FeatureFunctionType.SUBTRACTION:
141
+ assert len(self.f) == 2
137
142
  ex1: Expression = self.f[0].to_expression(a, milp)
138
143
  ex2: Expression = self.f[1].to_expression(a, milp)
139
- return Expression.subtract_expressions(ex1, ex2)
144
+ return ex1 - ex2
140
145
  elif self.type == FeatureFunctionType.SUM:
146
+ assert len(self.f) >= 1
141
147
  ex1: Expression = self.f[0].to_expression(a, milp)
142
148
  for i in range(1, len(self.f)):
143
149
  ex2: Expression = self.f[i].to_expression(a, milp)
144
- ex1: Expression = Expression.add_expressions(ex1, ex2)
150
+ ex1 = ex1 + ex2
145
151
  return ex1
146
152
  return None
147
153
 
@@ -64,6 +64,7 @@ from fuzzy_dl_owl2.fuzzydl.util import constants
64
64
  from fuzzy_dl_owl2.fuzzydl.util.constants import ConceptType, ConcreteFeatureType
65
65
  from fuzzy_dl_owl2.fuzzydl.util.util import Util
66
66
  from fuzzy_dl_owl2.fuzzyowl2.util.constants import FuzzyOWL2Keyword
67
+ from fuzzy_dl_owl2.fuzzyowl2.util.fuzzy_xml import FuzzyXML
67
68
  from pyowl2.abstracts.axiom import OWLAxiom
68
69
  from pyowl2.abstracts.class_expression import OWLClassExpression
69
70
  from pyowl2.abstracts.data_range import OWLDataRange
@@ -128,6 +129,8 @@ from pyowl2.individual.named_individual import OWLNamedIndividual
128
129
  from pyowl2.literal.literal import OWLLiteral
129
130
  from pyowl2.ontology import OWLOntology
130
131
 
132
+ from fuzzy_dl_owl2.fuzzydl.util.config_reader import ConfigReader
133
+
131
134
 
132
135
  # @utils.timer_decorator
133
136
  class FuzzydlToOwl2:
@@ -148,7 +151,7 @@ class FuzzydlToOwl2:
148
151
  self.ontology_iri, OWL1_annotations=True
149
152
  )
150
153
  self.fuzzyLabel: OWLAnnotationProperty = OWLAnnotationProperty(
151
- IRI(self.ontology_iri.namespace, "fuzzyLabel")
154
+ IRI(self.ontology_iri.namespace, ConfigReader.OWL_ANNOTATION_LABEL)
152
155
  )
153
156
 
154
157
  self.ontology.add_axiom(OWLDeclaration(self.fuzzyLabel))
@@ -276,11 +279,24 @@ class FuzzydlToOwl2:
276
279
  c4: OWLClassExpression = self.get_new_atomic_class(str(c))
277
280
  c3: OWLClassExpression = self.get_base(c.c1)
278
281
  self.concepts[str(c)] = c3
279
- annotation: str = (
280
- f'<{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()} {FuzzyOWL2Keyword.FUZZY_TYPE.get_str_value()}="{FuzzyOWL2Keyword.CONCEPT.get_str_value()}">\n',
281
- f'\t<{FuzzyOWL2Keyword.CONCEPT.get_tag_name()} {FuzzyOWL2Keyword.TYPE.get_str_value()}="{FuzzyOWL2Keyword.MODIFIED.get_str_value()}" {FuzzyOWL2Keyword.MODIFIER.get_str_value()}="{self.modifiers[str(c)]}" {FuzzyOWL2Keyword.BASE.get_str_value()}="{c3}"/>\n',
282
- f"</{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()}>",
282
+
283
+ main_xml = FuzzyXML.build_main_xml(FuzzyOWL2Keyword.CONCEPT.get_str_value())
284
+ concept_xml = FuzzyXML.build_concept_xml(
285
+ FuzzyOWL2Keyword.MODIFIED.get_str_value(),
286
+ {
287
+ FuzzyOWL2Keyword.MODIFIER.get_str_value(): str(
288
+ self.modifiers[str(c)]
289
+ ),
290
+ FuzzyOWL2Keyword.BASE.get_str_value(): str(c3),
291
+ },
283
292
  )
293
+ main_xml.append(concept_xml)
294
+ annotation: str = FuzzyXML.to_str(main_xml)
295
+ # annotation: str = (
296
+ # f'<{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()} {FuzzyOWL2Keyword.FUZZY_TYPE.get_str_value()}="{FuzzyOWL2Keyword.CONCEPT.get_str_value()}">\n',
297
+ # f'\t<{FuzzyOWL2Keyword.CONCEPT.get_tag_name()} {FuzzyOWL2Keyword.TYPE.get_str_value()}="{FuzzyOWL2Keyword.MODIFIED.get_str_value()}" {FuzzyOWL2Keyword.MODIFIER.get_str_value()}="{self.modifiers[str(c)]}" {FuzzyOWL2Keyword.BASE.get_str_value()}="{c3}"/>\n',
298
+ # f"</{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()}>",
299
+ # )
284
300
  self.add_entity_annotation(annotation, c4)
285
301
  return c4
286
302
  elif c_type == ConceptType.SELF:
@@ -331,11 +347,22 @@ class FuzzydlToOwl2:
331
347
  c: WeightedConcept = typing.cast(WeightedConcept, c)
332
348
  c4: OWLClassExpression = self.get_new_atomic_class(str(c))
333
349
  c3: OWLClassExpression = self.get_base(c.c1)
334
- annotation: str = (
335
- f'<{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()} {FuzzyOWL2Keyword.FUZZY_TYPE.get_str_value()}="{FuzzyOWL2Keyword.CONCEPT.get_str_value()}">\n',
336
- f'\t<{FuzzyOWL2Keyword.CONCEPT.get_tag_name()} {FuzzyOWL2Keyword.TYPE.get_str_value()}="{FuzzyOWL2Keyword.WEIGHTED.get_str_value()}" {FuzzyOWL2Keyword.DEGREE_VALUE.get_str_value()}="{c.weight}" {FuzzyOWL2Keyword.BASE.get_str_value()}="{c3}"/>\n',
337
- f"</{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()}>",
350
+
351
+ main_xml = FuzzyXML.build_main_xml(FuzzyOWL2Keyword.CONCEPT.get_str_value())
352
+ concept_xml = FuzzyXML.build_concept_xml(
353
+ FuzzyOWL2Keyword.WEIGHTED.get_str_value(),
354
+ {
355
+ FuzzyOWL2Keyword.DEGREE_VALUE.get_str_value(): str(c.weight),
356
+ FuzzyOWL2Keyword.BASE.get_str_value(): str(c3),
357
+ },
338
358
  )
359
+ main_xml.append(concept_xml)
360
+ annotation: str = FuzzyXML.to_str(main_xml)
361
+ # annotation: str = (
362
+ # f'<{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()} {FuzzyOWL2Keyword.FUZZY_TYPE.get_str_value()}="{FuzzyOWL2Keyword.CONCEPT.get_str_value()}">\n',
363
+ # f'\t<{FuzzyOWL2Keyword.CONCEPT.get_tag_name()} {FuzzyOWL2Keyword.TYPE.get_str_value()}="{FuzzyOWL2Keyword.WEIGHTED.get_str_value()}" {FuzzyOWL2Keyword.DEGREE_VALUE.get_str_value()}="{c.weight}" {FuzzyOWL2Keyword.BASE.get_str_value()}="{c3}"/>\n',
364
+ # f"</{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()}>",
365
+ # )
339
366
  self.add_entity_annotation(annotation, c3)
340
367
  return c4
341
368
  elif c_type in (
@@ -378,16 +405,33 @@ class FuzzydlToOwl2:
378
405
  curr_concept: HasWeightedConceptsInterface = type_cast[c.type](c)
379
406
  c3: OWLClassExpression = self.get_new_atomic_class(str(curr_concept))
380
407
 
381
- annotation: str = (
382
- f'<{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()} {FuzzyOWL2Keyword.FUZZY_TYPE.get_str_value()}="{FuzzyOWL2Keyword.CONCEPT.get_str_value()}">\n',
383
- f'\t<{FuzzyOWL2Keyword.CONCEPT.get_tag_name()} {FuzzyOWL2Keyword.TYPE.get_str_value()}="{type_dict[c.type]}">\n ',
384
- )
408
+ main_xml = FuzzyXML.build_main_xml(FuzzyOWL2Keyword.CONCEPT.get_str_value())
409
+ concept_xml = FuzzyXML.build_concept_xml(type_dict[c.type])
385
410
  for i in range(len(curr_concept.concepts)):
386
411
  c5: OWLClassExpression = self.get_base(curr_concept.concepts[i])
387
- annotation += f'\t\t<{FuzzyOWL2Keyword.CONCEPT.get_tag_name()} {FuzzyOWL2Keyword.TYPE.get_str_value()}="{FuzzyOWL2Keyword.WEIGHTED.get_str_value()}" {FuzzyOWL2Keyword.DEGREE_VALUE.get_str_value()}="{curr_concept.weights[i]}" {FuzzyOWL2Keyword.BASE.get_str_value()}="{c5}" />\n'
388
- annotation: str = (
389
- f"\t</{FuzzyOWL2Keyword.CONCEPT.get_tag_name()} >\n</{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()} >"
390
- )
412
+ sub_concept_xml = FuzzyXML.build_concept_xml(
413
+ FuzzyOWL2Keyword.WEIGHTED.get_str_value(),
414
+ {
415
+ FuzzyOWL2Keyword.DEGREE_VALUE.get_str_value(): str(
416
+ curr_concept.weights[i]
417
+ ),
418
+ FuzzyOWL2Keyword.BASE.get_str_value(): str(c5),
419
+ },
420
+ )
421
+ concept_xml.append(sub_concept_xml)
422
+ main_xml.append(concept_xml)
423
+ annotation: str = FuzzyXML.to_str(main_xml)
424
+
425
+ # annotation: str = (
426
+ # f'<{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()} {FuzzyOWL2Keyword.FUZZY_TYPE.get_str_value()}="{FuzzyOWL2Keyword.CONCEPT.get_str_value()}">\n',
427
+ # f'\t<{FuzzyOWL2Keyword.CONCEPT.get_tag_name()} {FuzzyOWL2Keyword.TYPE.get_str_value()}="{type_dict[c.type]}">\n ',
428
+ # )
429
+ # for i in range(len(curr_concept.concepts)):
430
+ # c5: OWLClassExpression = self.get_base(curr_concept.concepts[i])
431
+ # annotation += f'\t\t<{FuzzyOWL2Keyword.CONCEPT.get_tag_name()} {FuzzyOWL2Keyword.TYPE.get_str_value()}="{FuzzyOWL2Keyword.WEIGHTED.get_str_value()}" {FuzzyOWL2Keyword.DEGREE_VALUE.get_str_value()}="{curr_concept.weights[i]}" {FuzzyOWL2Keyword.BASE.get_str_value()}="{c5}" />\n'
432
+ # annotation: str = (
433
+ # f"\t</{FuzzyOWL2Keyword.CONCEPT.get_tag_name()} >\n</{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()} >"
434
+ # )
391
435
  self.add_entity_annotation(annotation, c3)
392
436
  return c3
393
437
 
@@ -411,18 +455,31 @@ class FuzzydlToOwl2:
411
455
  return None
412
456
  curr_concept: HasWeightedConceptsInterface = type_cast[c.type](c)
413
457
  c4: OWLClassExpression = self.get_new_atomic_class(str(c))
414
- annotation: str = (
415
- f'<{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()} {FuzzyOWL2Keyword.FUZZY_TYPE.get_str_value()}="{FuzzyOWL2Keyword.CONCEPT.get_str_value()}">\n',
416
- f'\t<{FuzzyOWL2Keyword.CONCEPT.get_tag_name()} {FuzzyOWL2Keyword.TYPE.get_str_value()}="{type_dict[c.type]}">\n',
417
- f"\t\t<{FuzzyOWL2Keyword.WEIGHTS.get_tag_name()}>\n",
458
+
459
+ main_xml = FuzzyXML.build_main_xml(FuzzyOWL2Keyword.CONCEPT.get_str_value())
460
+ concept_xml = FuzzyXML.build_concept_xml(type_dict[c.type])
461
+ weights_xml = FuzzyXML.build_weights_xml(curr_concept.weights)
462
+ names_xml = FuzzyXML.build_names_xml(
463
+ [self.get_base(ci) for ci in curr_concept.concepts]
418
464
  )
419
- for d in curr_concept.weights:
420
- annotation += f"\t\t\t<{FuzzyOWL2Keyword.WEIGHT.get_tag_name()}>{d}</{FuzzyOWL2Keyword.WEIGHT.get_tag_name()}>\n"
421
- annotation += f"\t\t</{FuzzyOWL2Keyword.WEIGHTS.get_tag_name()}>\n\t\t<{FuzzyOWL2Keyword.CONCEPT_NAMES.get_tag_name()}>\n"
422
- for ci in curr_concept.concepts:
423
- c5: OWLClassExpression = self.get_base(ci)
424
- annotation += f"\t\t\t<{FuzzyOWL2Keyword.NAME.get_tag_name()}>{c5}</{FuzzyOWL2Keyword.NAME.get_tag_name()}>\n"
425
- annotation += f"\t\t</{FuzzyOWL2Keyword.CONCEPT_NAMES.get_tag_name()}>\n\t</{FuzzyOWL2Keyword.CONCEPT.get_tag_name()}>\n</{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()}>"
465
+ concept_xml.append(weights_xml)
466
+ concept_xml.append(names_xml)
467
+ main_xml.append(concept_xml)
468
+ annotation: str = FuzzyXML.to_str(main_xml)
469
+
470
+ # annotation: str = (
471
+ # f'<{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()} {FuzzyOWL2Keyword.FUZZY_TYPE.get_str_value()}="{FuzzyOWL2Keyword.CONCEPT.get_str_value()}">\n',
472
+ # f'\t<{FuzzyOWL2Keyword.CONCEPT.get_tag_name()} {FuzzyOWL2Keyword.TYPE.get_str_value()}="{type_dict[c.type]}">\n',
473
+ # f"\t\t<{FuzzyOWL2Keyword.WEIGHTS.get_tag_name()}>\n",
474
+ # )
475
+ # for d in curr_concept.weights:
476
+ # annotation += f"\t\t\t<{FuzzyOWL2Keyword.WEIGHT.get_tag_name()}>{d}</{FuzzyOWL2Keyword.WEIGHT.get_tag_name()}>\n"
477
+ # annotation += f"\t\t</{FuzzyOWL2Keyword.WEIGHTS.get_tag_name()}>\n\t\t<{FuzzyOWL2Keyword.CONCEPT_NAMES.get_tag_name()}>\n"
478
+ # for ci in curr_concept.concepts:
479
+ # c5: OWLClassExpression = self.get_base(ci)
480
+ # annotation += f"\t\t\t<{FuzzyOWL2Keyword.NAME.get_tag_name()}>{c5}</{FuzzyOWL2Keyword.NAME.get_tag_name()}>\n"
481
+ # annotation += f"\t\t</{FuzzyOWL2Keyword.CONCEPT_NAMES.get_tag_name()}>\n\t</{FuzzyOWL2Keyword.CONCEPT.get_tag_name()}>\n</{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()}>"
482
+
426
483
  self.add_entity_annotation(annotation, c4)
427
484
  return c4
428
485
 
@@ -438,15 +495,27 @@ class FuzzydlToOwl2:
438
495
  return None
439
496
  curr_concept: QowaConcept = type_cast[c.type](c)
440
497
  c4: OWLClassExpression = self.get_new_atomic_class(str(c))
441
- annotation: str = (
442
- f'<{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()} {FuzzyOWL2Keyword.FUZZY_TYPE.get_str_value()}="{FuzzyOWL2Keyword.CONCEPT.get_str_value()}">\n',
443
- f'\t<{FuzzyOWL2Keyword.CONCEPT.get_tag_name()} {FuzzyOWL2Keyword.TYPE.get_str_value()}="{type_dict[c.type]}" {FuzzyOWL2Keyword.QUANTIFIER.get_tag_name()}="{curr_concept.quantifier}">\n',
444
- f"\t\t<{FuzzyOWL2Keyword.CONCEPT_NAMES.get_tag_name()}>\n",
498
+
499
+ main_xml = FuzzyXML.build_main_xml(FuzzyOWL2Keyword.CONCEPT.get_str_value())
500
+ concept_xml = FuzzyXML.build_concept_xml(
501
+ type_dict[c.type],
502
+ {FuzzyOWL2Keyword.QUANTIFIER.get_str_value(): str(curr_concept.quantifier)},
503
+ )
504
+ names_xml = FuzzyXML.build_names_xml(
505
+ [self.get_base(ci) for ci in curr_concept.concepts]
445
506
  )
446
- for ci in curr_concept.concepts:
447
- c5: OWLClassExpression = self.get_base(ci)
448
- annotation += f"\t\t\t<{FuzzyOWL2Keyword.NAME.get_tag_name()}>{c5}</{FuzzyOWL2Keyword.NAME.get_tag_name()}>\n"
449
- annotation += f"\t\t</{FuzzyOWL2Keyword.CONCEPT_NAMES.get_tag_name()}>\n\t</{FuzzyOWL2Keyword.CONCEPT.get_tag_name()}>\n</{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()}>"
507
+ concept_xml.append(names_xml)
508
+ main_xml.append(concept_xml)
509
+ annotation: str = FuzzyXML.to_str(main_xml)
510
+ # annotation: str = (
511
+ # f'<{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()} {FuzzyOWL2Keyword.FUZZY_TYPE.get_str_value()}="{FuzzyOWL2Keyword.CONCEPT.get_str_value()}">\n',
512
+ # f'\t<{FuzzyOWL2Keyword.CONCEPT.get_tag_name()} {FuzzyOWL2Keyword.TYPE.get_str_value()}="{type_dict[c.type]}" {FuzzyOWL2Keyword.QUANTIFIER.get_str_value()}="{curr_concept.quantifier}">\n',
513
+ # f"\t\t<{FuzzyOWL2Keyword.CONCEPT_NAMES.get_tag_name()}>\n",
514
+ # )
515
+ # for ci in curr_concept.concepts:
516
+ # c5: OWLClassExpression = self.get_base(ci)
517
+ # annotation += f"\t\t\t<{FuzzyOWL2Keyword.NAME.get_tag_name()}>{c5}</{FuzzyOWL2Keyword.NAME.get_tag_name()}>\n"
518
+ # annotation += f"\t\t</{FuzzyOWL2Keyword.CONCEPT_NAMES.get_tag_name()}>\n\t</{FuzzyOWL2Keyword.CONCEPT.get_tag_name()}>\n</{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()}>"
450
519
  self.add_entity_annotation(annotation, c4)
451
520
  return c4
452
521
 
@@ -549,11 +618,16 @@ class FuzzydlToOwl2:
549
618
  elif isinstance(value, DegreeNumeric): # Degree object
550
619
  n = value.get_numerical_value()
551
620
 
552
- annotation_text: str = (
553
- f'<{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()} {FuzzyOWL2Keyword.FUZZY_TYPE.get_str_value()}="{FuzzyOWL2Keyword.AXIOM.get_str_value()}">\n'
554
- f'\t<{FuzzyOWL2Keyword.DEGREE_DEF.get_tag_name()} {FuzzyOWL2Keyword.DEGREE_VALUE.get_str_value()}="{n}"/>\n'
555
- f"</{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()}>"
556
- )
621
+ main_xml = FuzzyXML.build_main_xml(FuzzyOWL2Keyword.AXIOM.get_str_value())
622
+ degree_xml = FuzzyXML.build_degree_xml(n)
623
+ main_xml.append(degree_xml)
624
+ annotation_text: str = FuzzyXML.to_str(main_xml)
625
+
626
+ # annotation_text: str = (
627
+ # f'<{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()} {FuzzyOWL2Keyword.FUZZY_TYPE.get_str_value()}="{FuzzyOWL2Keyword.AXIOM.get_str_value()}">\n'
628
+ # f'\t<{FuzzyOWL2Keyword.DEGREE_DEF.get_tag_name()} {FuzzyOWL2Keyword.DEGREE_VALUE.get_str_value()}="{n}"/>\n'
629
+ # f"</{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()}>"
630
+ # )
557
631
  annotation: OWLAnnotation = self.to_owl_annotation(annotation_text)
558
632
  return set([annotation])
559
633
 
@@ -590,11 +664,17 @@ class FuzzydlToOwl2:
590
664
  logic = str(constants.KNOWLEDGE_BASE_SEMANTICS)
591
665
 
592
666
  if logic:
593
- annotation: str = (
594
- f'<{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()} {FuzzyOWL2Keyword.FUZZY_TYPE.get_str_value()}="{FuzzyOWL2Keyword.ONTOLOGY.get_str_value()}">\n'
595
- f'\t<{FuzzyOWL2Keyword.FUZZY_LOGIC.get_tag_name()} {FuzzyOWL2Keyword.LOGIC.get_str_value()}="{logic}" />\n'
596
- f"</{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()}>"
667
+ main_xml = FuzzyXML.build_main_xml(
668
+ FuzzyOWL2Keyword.ONTOLOGY.get_str_value()
597
669
  )
670
+ logic_xml = FuzzyXML.build_logic_xml(logic)
671
+ main_xml.append(logic_xml)
672
+ annotation: str = FuzzyXML.to_str(main_xml)
673
+ # annotation: str = (
674
+ # f'<{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()} {FuzzyOWL2Keyword.FUZZY_TYPE.get_str_value()}="{FuzzyOWL2Keyword.ONTOLOGY.get_str_value()}">\n'
675
+ # f'\t<{FuzzyOWL2Keyword.FUZZY_LOGIC.get_tag_name()} {FuzzyOWL2Keyword.LOGIC.get_str_value()}="{logic}" />\n'
676
+ # f"</{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()}>"
677
+ # )
598
678
  self.add_ontology_annotation(annotation)
599
679
 
600
680
  # Process concrete concepts
@@ -813,7 +893,8 @@ class FuzzydlToOwl2:
813
893
  current_datatype: OWLDatatype = OWLDatatype(self.iri(c))
814
894
  self.datatypes[str(c)] = current_datatype
815
895
 
816
- specific: str = self._get_concrete_concept_specifics(c)
896
+ # specific: str = self._get_concrete_concept_specifics(c)
897
+ specific: tuple[str, dict[str, str]] = self._get_concrete_concept_specifics(c)
817
898
 
818
899
  int_datatype: OWLDatatype = OWLDatatype(XSD.integer)
819
900
  greater_than: OWLDatatypeRestriction = OWLDatatypeRestriction(
@@ -843,45 +924,102 @@ class FuzzydlToOwl2:
843
924
  self.ontology.add_axiom(OWLDeclaration(current_datatype))
844
925
  self.ontology.add_axiom(definition)
845
926
 
846
- annotation: str = (
847
- f'<{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()} {FuzzyOWL2Keyword.FUZZY_TYPE.get_str_value()}="{FuzzyOWL2Keyword.DATATYPE.get_str_value()}">\n'
848
- f'\t<{FuzzyOWL2Keyword.DATATYPE.get_tag_name()} {FuzzyOWL2Keyword.TYPE.get_str_value()}="{specific}"/>\n'
849
- f"</{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()}>"
850
- )
927
+ main_xml = FuzzyXML.build_main_xml(FuzzyOWL2Keyword.DATATYPE.get_str_value())
928
+ datatype_xml = FuzzyXML.build_datatype_xml(specific[0], specific[1])
929
+ main_xml.append(datatype_xml)
930
+ annotation: str = FuzzyXML.to_str(main_xml)
931
+
932
+ # annotation: str = (
933
+ # f'<{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()} {FuzzyOWL2Keyword.FUZZY_TYPE.get_str_value()}="{FuzzyOWL2Keyword.DATATYPE.get_str_value()}">\n'
934
+ # f'\t<{FuzzyOWL2Keyword.DATATYPE.get_tag_name()} {FuzzyOWL2Keyword.TYPE.get_str_value()}="{specific}"/>\n'
935
+ # f"</{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()}>"
936
+ # )
851
937
  self.add_entity_annotation(annotation, current_datatype)
852
938
 
853
- def _get_concrete_concept_specifics(self, c: FuzzyConcreteConcept) -> str:
939
+ def _get_concrete_concept_specifics(
940
+ self, c: FuzzyConcreteConcept
941
+ ) -> tuple[str, dict[str, str]]:
854
942
  """Get concrete concept specific parameters"""
855
943
  if isinstance(c, CrispConcreteConcept):
856
- return f'{FuzzyOWL2Keyword.CRISP.get_str_value()}" {FuzzyOWL2Keyword.A.get_str_value()}="{c.a}" {FuzzyOWL2Keyword.B.get_str_value()}="{c.b}'
944
+ return FuzzyOWL2Keyword.CRISP.get_str_value(), {
945
+ FuzzyOWL2Keyword.A.get_str_value(): str(c.a),
946
+ FuzzyOWL2Keyword.B.get_str_value(): str(c.b),
947
+ }
857
948
  elif isinstance(c, LeftConcreteConcept):
858
- return f'{FuzzyOWL2Keyword.LEFT_SHOULDER.get_str_value()}" {FuzzyOWL2Keyword.A.get_str_value()}="{c.a}" {FuzzyOWL2Keyword.B.get_str_value()}="{c.b}'
949
+ return FuzzyOWL2Keyword.LEFT_SHOULDER.get_str_value(), {
950
+ FuzzyOWL2Keyword.A.get_str_value(): str(c.a),
951
+ FuzzyOWL2Keyword.B.get_str_value(): str(c.b),
952
+ }
859
953
  elif isinstance(c, RightConcreteConcept):
860
- return f'{FuzzyOWL2Keyword.RIGHT_SHOULDER.get_str_value()}" {FuzzyOWL2Keyword.A.get_str_value()}="{c.a}" {FuzzyOWL2Keyword.B.get_str_value()}="{c.b}'
954
+ return FuzzyOWL2Keyword.RIGHT_SHOULDER.get_str_value(), {
955
+ FuzzyOWL2Keyword.A.get_str_value(): str(c.a),
956
+ FuzzyOWL2Keyword.B.get_str_value(): str(c.b),
957
+ }
861
958
  elif isinstance(c, TriangularConcreteConcept):
862
- return f'{FuzzyOWL2Keyword.TRIANGULAR.get_str_value()}" {FuzzyOWL2Keyword.A.get_str_value()}="{c.a}" {FuzzyOWL2Keyword.B.get_str_value()}="{c.b}" {FuzzyOWL2Keyword.C.get_str_value()}="{c.c}'
959
+ return FuzzyOWL2Keyword.TRIANGULAR.get_str_value(), {
960
+ FuzzyOWL2Keyword.A.get_str_value(): str(c.a),
961
+ FuzzyOWL2Keyword.B.get_str_value(): str(c.b),
962
+ FuzzyOWL2Keyword.C.get_str_value(): str(c.c),
963
+ }
863
964
  elif isinstance(c, TrapezoidalConcreteConcept):
864
- return f'{FuzzyOWL2Keyword.TRAPEZOIDAL.get_str_value()}" {FuzzyOWL2Keyword.A.get_str_value()}="{c.a}" {FuzzyOWL2Keyword.B.get_str_value()}="{c.b}" {FuzzyOWL2Keyword.C.get_str_value()}="{c.c}" {FuzzyOWL2Keyword.D.get_str_value()}="{c.d}'
865
- return ""
965
+ return FuzzyOWL2Keyword.TRAPEZOIDAL.get_str_value(), {
966
+ FuzzyOWL2Keyword.A.get_str_value(): str(c.a),
967
+ FuzzyOWL2Keyword.B.get_str_value(): str(c.b),
968
+ FuzzyOWL2Keyword.C.get_str_value(): str(c.c),
969
+ FuzzyOWL2Keyword.D.get_str_value(): str(c.d),
970
+ }
971
+ return "", dict()
972
+
973
+ # def _get_concrete_concept_specifics(self, c: FuzzyConcreteConcept) -> str:
974
+ # """Get concrete concept specific parameters"""
975
+ # if isinstance(c, CrispConcreteConcept):
976
+ # return f'{FuzzyOWL2Keyword.CRISP.get_str_value()}" {FuzzyOWL2Keyword.A.get_str_value()}="{c.a}" {FuzzyOWL2Keyword.B.get_str_value()}="{c.b}'
977
+ # elif isinstance(c, LeftConcreteConcept):
978
+ # return f'{FuzzyOWL2Keyword.LEFT_SHOULDER.get_str_value()}" {FuzzyOWL2Keyword.A.get_str_value()}="{c.a}" {FuzzyOWL2Keyword.B.get_str_value()}="{c.b}'
979
+ # elif isinstance(c, RightConcreteConcept):
980
+ # return f'{FuzzyOWL2Keyword.RIGHT_SHOULDER.get_str_value()}" {FuzzyOWL2Keyword.A.get_str_value()}="{c.a}" {FuzzyOWL2Keyword.B.get_str_value()}="{c.b}'
981
+ # elif isinstance(c, TriangularConcreteConcept):
982
+ # return f'{FuzzyOWL2Keyword.TRIANGULAR.get_str_value()}" {FuzzyOWL2Keyword.A.get_str_value()}="{c.a}" {FuzzyOWL2Keyword.B.get_str_value()}="{c.b}" {FuzzyOWL2Keyword.C.get_str_value()}="{c.c}'
983
+ # elif isinstance(c, TrapezoidalConcreteConcept):
984
+ # return f'{FuzzyOWL2Keyword.TRAPEZOIDAL.get_str_value()}" {FuzzyOWL2Keyword.A.get_str_value()}="{c.a}" {FuzzyOWL2Keyword.B.get_str_value()}="{c.b}" {FuzzyOWL2Keyword.C.get_str_value()}="{c.c}" {FuzzyOWL2Keyword.D.get_str_value()}="{c.d}'
985
+ # return ""
866
986
 
867
987
  def _process_modifier(self, mod: Modifier) -> None:
868
988
  """Process a modifier"""
869
989
  Util.debug(f"Process modifier -> {mod}")
990
+
991
+ main_xml = FuzzyXML.build_main_xml(FuzzyOWL2Keyword.MODIFIER.get_str_value())
992
+
870
993
  if isinstance(mod, LinearModifier):
871
- annotation: str = (
872
- f'<{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()} {FuzzyOWL2Keyword.FUZZY_TYPE.get_str_value()}="{FuzzyOWL2Keyword.MODIFIER.get_str_value()}">\n'
873
- f'\t<{FuzzyOWL2Keyword.MODIFIER.get_tag_name()} {FuzzyOWL2Keyword.TYPE.get_str_value()}="{FuzzyOWL2Keyword.LINEAR.get_str_value()}" {FuzzyOWL2Keyword.C.get_str_value()}="{mod.c}"/>\n'
874
- f"</{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()}>"
994
+ modifier_xml = FuzzyXML.build_modifier_xml(
995
+ FuzzyOWL2Keyword.LINEAR.get_str_value(),
996
+ {FuzzyOWL2Keyword.C.get_str_value(): str(mod.c)},
875
997
  )
998
+ # annotation: str = (
999
+ # f'<{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()} {FuzzyOWL2Keyword.FUZZY_TYPE.get_str_value()}="{FuzzyOWL2Keyword.MODIFIER.get_str_value()}">\n'
1000
+ # f'\t<{FuzzyOWL2Keyword.MODIFIER.get_tag_name()} {FuzzyOWL2Keyword.TYPE.get_str_value()}="{FuzzyOWL2Keyword.LINEAR.get_str_value()}" {FuzzyOWL2Keyword.C.get_str_value()}="{mod.c}"/>\n'
1001
+ # f"</{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()}>"
1002
+ # )
876
1003
  elif isinstance(mod, TriangularModifier):
877
- annotation: str = (
878
- f'<{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()} {FuzzyOWL2Keyword.FUZZY_TYPE.get_str_value()}="{FuzzyOWL2Keyword.MODIFIER.get_str_value()}">\n'
879
- f'\t<{FuzzyOWL2Keyword.MODIFIER.get_tag_name()} {FuzzyOWL2Keyword.TYPE.get_str_value()}="{FuzzyOWL2Keyword.TRIANGULAR.get_str_value()}" {FuzzyOWL2Keyword.A.get_str_value()}="{mod.a}" {FuzzyOWL2Keyword.B.get_str_value()}="{mod.b}" {FuzzyOWL2Keyword.C.get_str_value()}="{mod.c}"/>\n'
880
- f"</{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()}>"
1004
+ modifier_xml = FuzzyXML.build_modifier_xml(
1005
+ FuzzyOWL2Keyword.TRIANGULAR.get_str_value(),
1006
+ {
1007
+ FuzzyOWL2Keyword.A.get_str_value(): str(mod.a),
1008
+ FuzzyOWL2Keyword.B.get_str_value(): str(mod.b),
1009
+ FuzzyOWL2Keyword.C.get_str_value(): str(mod.c),
1010
+ },
881
1011
  )
1012
+ # annotation: str = (
1013
+ # f'<{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()} {FuzzyOWL2Keyword.FUZZY_TYPE.get_str_value()}="{FuzzyOWL2Keyword.MODIFIER.get_str_value()}">\n'
1014
+ # f'\t<{FuzzyOWL2Keyword.MODIFIER.get_tag_name()} {FuzzyOWL2Keyword.TYPE.get_str_value()}="{FuzzyOWL2Keyword.TRIANGULAR.get_str_value()}" {FuzzyOWL2Keyword.A.get_str_value()}="{mod.a}" {FuzzyOWL2Keyword.B.get_str_value()}="{mod.b}" {FuzzyOWL2Keyword.C.get_str_value()}="{mod.c}"/>\n'
1015
+ # f"</{FuzzyOWL2Keyword.FUZZY_OWL_2.get_str_value()}>"
1016
+ # )
882
1017
  else:
883
1018
  raise ValueError(f"Unknown modifier type: {type(mod)}")
884
1019
 
1020
+ main_xml.append(modifier_xml)
1021
+ annotation: str = FuzzyXML.to_str(main_xml)
1022
+
885
1023
  current_datatype: OWLDatatype = OWLDatatype(self.iri(mod))
886
1024
  self.modifiers[str(mod)] = current_datatype
887
1025
  self.ontology.add_axiom(OWLDeclaration(current_datatype))
@@ -6435,6 +6435,7 @@ class DatatypeReasoner:
6435
6435
  k: list[float],
6436
6436
  type: InequalityType,
6437
6437
  ) -> None:
6438
+ # Gets fillers bi from every feature fi
6438
6439
  array: set[str] = fun.get_features()
6439
6440
  new_variable: bool = False
6440
6441
  for feature in array:
@@ -6454,21 +6455,28 @@ class DatatypeReasoner:
6454
6455
  x_fi: Variable = kb.milp.get_variable(
6455
6456
  ind, bi, feature, VariableType.BINARY
6456
6457
  )
6458
+ # (a,bi):Fi >= x_{(a,bi):Fi}
6457
6459
  IndividualHandler.add_relation(
6458
6460
  ind, feature, bi, DegreeVariable.get_degree(x_fi), kb
6459
6461
  )
6460
- x_bi: Variable = (
6461
- kb.milp.get_variable(bi, VariableType.INTEGER)
6462
- if t.get_type() == ConcreteFeatureType.INTEGER
6463
- else kb.milp.get_variable(bi, VariableType.CONTINUOUS)
6462
+ x_bi: Variable = kb.milp.get_variable(
6463
+ bi,
6464
+ (
6465
+ VariableType.INTEGER
6466
+ if t.get_type() == ConcreteFeatureType.INTEGER
6467
+ else VariableType.CONTINUOUS
6468
+ ),
6464
6469
  )
6465
- if new_variable is not None and ki is not None:
6470
+ if new_variable and ki is not None:
6466
6471
  kb.restrict_range(x_bi, x_fi, ki[0], ki[1])
6472
+ # xIsC <= xFi
6467
6473
  kb.milp.add_new_constraint(
6468
6474
  Expression(Term(1.0, x_is_c), Term(-1.0, x_fi)),
6469
6475
  InequalityType.LESS_THAN,
6470
6476
  )
6477
+ # xF \in {0,1}
6471
6478
  x_fi.set_binary_variable()
6479
+ # xB is a datatype filler
6472
6480
  x_bi.set_datatype_filler_variable()
6473
6481
  DatatypeReasoner.write_feature_equation(ind, fun, x_b, x_is_c, x_f, k, type, kb)
6474
6482
 
@@ -98,7 +98,7 @@ class Expression:
98
98
 
99
99
  def add_term(self, term: Term) -> None:
100
100
  for idx, t in enumerate(self.terms):
101
- if t == term:
101
+ if t.get_var() == term.get_var():
102
102
  self.terms[idx] = t + term
103
103
  return
104
104
  self.terms.append(term)
@@ -169,6 +169,17 @@ class Expression:
169
169
  def __truediv__(self, scalar: typing.Union[int, float]) -> typing.Self:
170
170
  return self * (1 / scalar)
171
171
 
172
+ def __hash__(self) -> int:
173
+ return hash(str(self))
174
+
175
+ def __eq__(self, value: typing.Self) -> bool:
176
+ if not isinstance(value, Expression):
177
+ return False
178
+ return len(self.terms) == len(value.terms) and all(term in value.terms for term in self.terms)
179
+
180
+ def __ne__(self, value: typing.Self) -> bool:
181
+ return not (self == value)
182
+
172
183
  def __repr__(self) -> str:
173
184
  return str(self)
174
185
 
@@ -184,5 +195,5 @@ class Expression:
184
195
  elif n == -1.0:
185
196
  parts.append(f"- {term.get_var()}")
186
197
  else:
187
- parts.append(f"{'+ ' if n >= 0 else '- '}{n} {term.get_var()}")
198
+ parts.append(f"{'+ ' if n >= 0 else '- '}{abs(n)} {term.get_var()}")
188
199
  return " ".join(parts)
@@ -43,6 +43,18 @@ class Inequation:
43
43
  assert self.type == InequalityType.GREATER_THAN
44
44
  return ">="
45
45
 
46
+ def is_zero(self) -> bool:
47
+ return all(term.get_coeff() == 0 for term in self.expr.get_terms()) and self.expr.get_constant() == 0
48
+
49
+ def __hash__(self) -> int:
50
+ return hash(str(self))
51
+
52
+ def __eq__(self, value: typing.Self) -> bool:
53
+ return self.expr == value.expr and self.type == value.type
54
+
55
+ def __ne__(self, value: typing.Self) -> bool:
56
+ return not (self == value)
57
+
46
58
  def __repr__(self) -> str:
47
59
  return str(self)
48
60