Repository: dice-group/owlapy (language: python)

Issue:
DL Syntax Parsing error for nominals 
```py
from owlapy.parser import DLSyntaxParser



namespace = "http://www.benchmark.org/family#"
parser = DLSyntaxParser(namespace)

expression = "∃ hasParent.{F8F137 , F5M63 , F6F77}"
target_concept = parser.parse_expression(expression)
```

throws the following error:
`Rule 'pn_chars' didn't match at ' , F5M63 , F6F77}'`
DL Syntax Parsing error for nominals 
```py
from owlapy.parser import DLSyntaxParser



namespace = "http://www.benchmark.org/family#"
parser = DLSyntaxParser(namespace)

expression = "∃ hasParent.{F8F137 , F5M63 , F6F77}"
target_concept = parser.parse_expression(expression)
```

throws the following error:
`Rule 'pn_chars' didn't match at ' , F5M63 , F6F77}'`
Direct and Inverse Mappings Owlapy objects into DL syntax in string and Manchester systax string
Previously, 
we use the comma in [an Enumaration of Individuals](https://www.w3.org/TR/owl2-syntax/#Enumeration_of_Individuals) to seperate individuals in the DL syntax. 
Yet, such usage can lead to confusion as the meaning of comman does not indicate AND or OR,e.g. `"∃ hasParent.{F8F137 , F5M63 , F6F77}"`

```python
C = OWLObjectOneOf((OWLNamedIndividual("http://example.com/example#a"), OWLNamedIndividual("http://example.com/example#b")))
assert renderer.render(C)=="{a ⊔ b}"
```
This idea of using logical and/or also traltes to OWLDataOneOf as shown below
```python
c = OWLDataSomeValuesFrom(property=has_age,
                           filler=OWLDataIntersectionOf([OWLDataOneOf([OWLLiteral(32.5), OWLLiteral(4.5)]),
                                                         IntegerOWLDatatype]))
rendered_c = renderer.render(c)
self.assertEqual(c, parser.parse_expression(rendered_c))
self.assertEqual(rendered_c, "∃ hasAge.({32.5 ⊔ 4.5} ⊓ xsd:integer)")
```


## Issues to be fixed in this branch

### 1
During refactoring, found the following test
```python
c = OWLDataAllValuesFrom(property=has_age, filler=OWLDataUnionOf([owl_datatype_min_max_inclusive_restriction(40, 80), IntegerOWLDatatype]))
rendered_c = renderer.render(c)
self.assertEqual(c, parser.parse_expression(rendered_c))
self.assertEqual(rendered_c, "∀ hasAge.(xsd:integer[≥ 40 , ≤ 80] ⊔ xsd:integer)")
```
Meaning of xsd:integer[≥ 40 , ≤ 80] is also unclear. Could you please replace the the comma with logical AND @alkidbaci ?


### 2
test_owlapy_render.py and test_owlapy_parser.py should be included in test_owlapy_conversions.py
could you take care of it @LckyLke 

### 3
C and CC must be equal right ? @alkidbaci @LckyLke ?
```python
C = OWLObjectOneOf((OWLNamedIndividual("http://example.com/example#a"), OWLNamedIndividual("http://example.com/example#b")))
rendered_c = renderer.render(C)
assert rendered_c=="{a ⊔ b}" or rendered_c=="{b ⊔ a}"
print(rendered_c)
CC = OWLObjectOneOf((OWLNamedIndividual("http://example.com/example#b"), OWLNamedIndividual("http://example.com/example#a")))
print(C==CC)
```
This problem is caused by the usage of tuple instead of a set.

- [1] @alkidbaci 
- [2] done
- [3] done 
Refactoring on owl reasoners and some fixes/improvements
## Refactoring/fixes related with issue #79 and #91
- `AbstractOWLReasonerEx` is merged into `AbstractOWLReasoner`.
- `OntologyReasoner` **is removed**. Logic transfered to `FastInstancChekerReasoner`.
- `FastInstancChekerReasoner` renamed to `StructuralReasoner`.
- Updated documentation in accordance.
- Documentation is no longer published when pushing to _develop_ branch.
- Added `is_modified` attribute for `Ontology` class which indicates if an ontology is modified, i.e. axioms are added or removed after this ontology was initialized.
- `StructuralReasoner` will disable caching and reset if ontology modification is detected in order to avoid inconsistencies. 
- Changed operator to logical _AND_ for rendering and parsing **facet restrictions.**

- Updated tests in accordance with the changes.

Rendering owl_datatype_min_max_inclusive_restriction
Could you ensure that the
```python
from owlapy.render import DLSyntaxObjectRenderer
from owlapy.parser import DLSyntaxParser
from owlapy.owl_property import OWLObjectProperty
from owlapy.iri import IRI
from owlapy.owl_data_ranges import OWLDataUnionOf
from owlapy.providers import owl_datatype_min_max_inclusive_restriction
from owlapy.owl_literal import IntegerOWLDatatype
from owlapy.class_expression import OWLDataAllValuesFrom

NS = "http://www.benchmark.org/family#"
parser = DLSyntaxParser(NS)
renderer = DLSyntaxObjectRenderer()
has_age = OWLObjectProperty(IRI(NS, 'hasAge'))
c = OWLDataAllValuesFrom(property=has_age, filler=OWLDataUnionOf([owl_datatype_min_max_inclusive_restriction(40, 80), IntegerOWLDatatype]))
rendered_c = renderer.render(c) # ∀ hasAge.(xsd:integer[≥ 40 , ≤ 80] ⊔ xsd:integer)
```
Could you ensure that we obtain ∀ hasAge.(xsd:integer[≥ 40 ⊓  ≤ 80] ⊔ xsd:integer) after the rendering?



Discussion / hints:

Fix patch:
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index 10bf2fc9..35d249f7 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -4,7 +4,6 @@ on:
   push:
     branches:
      - main
-     - develop
      - documentation # just for testing
   pull_request:
 
diff --git a/README.md b/README.md
index 352faa24..9eb842a7 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 # OWLAPY
 [![Coverage](https://img.shields.io/badge/coverage-78%25-green)](https://dice-group.github.io/owlapy/usage/further_resources.html#coverage-report)
-[![Pypi](https://img.shields.io/badge/pypi-1.3.1-blue)](https://pypi.org/project/owlapy/1.3.1/)
-[![Docs](https://img.shields.io/badge/documentation-1.3.1-yellow)](https://dice-group.github.io/owlapy/usage/main.html)
+[![Pypi](https://img.shields.io/badge/pypi-1.3.2-blue)](https://pypi.org/project/owlapy/1.3.2/)
+[![Docs](https://img.shields.io/badge/documentation-1.3.2-yellow)](https://dice-group.github.io/owlapy/usage/main.html)
 
 ![OWLAPY](docs/_static/images/owlapy_logo.png)
 
diff --git a/docs/conf.py b/docs/conf.py
index 2c38198a..9e37f605 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -13,7 +13,7 @@
 
 project = 'OWLAPY'
 author = 'Ontolearn Team'
-release = '1.3.1'
+release = '1.3.2'
 
 # -- General configuration ---------------------------------------------------
 # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
diff --git a/docs/index.rst b/docs/index.rst
index 083391bc..1ab21468 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -14,6 +14,6 @@ Welcome to OWLAPY!
    usage/usage_examples
    usage/ontologies
    usage/reasoner
-   usage/owlapi_adaptor
+   usage/owlapi_synchronization
    usage/further_resources
    autoapi/owlapy/index
\ No newline at end of file
diff --git a/docs/usage/further_resources.md b/docs/usage/further_resources.md
index 46a55f2a..57df4007 100644
--- a/docs/usage/further_resources.md
+++ b/docs/usage/further_resources.md
@@ -26,34 +26,38 @@ The coverage report is generated using [coverage.py](https://coverage.readthedoc
 ```
 Name                                                 Stmts   Miss  Cover   Missing
 ----------------------------------------------------------------------------------
-owlapy/__init__.py                                       4      0   100%
-owlapy/class_expression/__init__.py                      8      0   100%
-owlapy/class_expression/class_expression.py             34      2    94%   58, 62
-owlapy/class_expression/nary_boolean_expression.py      24      0   100%
+owlapy/__init__.py                                       6      0   100%
+owlapy/abstracts/__init__.py                             3      0   100%
+owlapy/abstracts/abstract_owl_ontology.py               16      1    94%   151
+owlapy/abstracts/abstract_owl_ontology_manager.py       10      1    90%   24
+owlapy/abstracts/abstract_owl_reasoner.py               49     10    80%   409-417, 439, 464
+owlapy/class_expression/__init__.py                      9      0   100%
+owlapy/class_expression/class_expression.py             34      3    91%   58, 62, 103
+owlapy/class_expression/nary_boolean_expression.py      25      0   100%
 owlapy/class_expression/owl_class.py                    33      1    97%   44
-owlapy/class_expression/restriction.py                 313     26    92%   41, 49, 68, 71, 89, 170, 245-246, 302, 305, 335, 340, 343, 426, 451, 499, 502, 579-580, 616, 659, 662, 700, 703, 751, 823
-owlapy/converter.py                                    397    189    52%   52-68, 75-76, 79, 82, 152, 157, 169, 176, 184, 246-257, 264-282, 294, 304-307, 313-359, 366-387, 394-401, 417-420, 431, 451, 460-481, 489-491, 498-511, 515-521, 525-548, 552-555, 559-560, 564-576, 580-587, 591-592, 620, 624-628
-owlapy/iri.py                                           79      7    91%   54, 69, 82, 97, 128, 133, 150
+owlapy/class_expression/restriction.py                 313     27    91%   41, 49, 68, 71, 89, 171, 245-246, 303, 336, 342, 345, 419, 430, 439, 456, 502, 505, 582-583, 620, 663, 666, 706, 709, 758, 830
+owlapy/converter.py                                    420    174    59%   52-68, 75-76, 79, 82, 152, 157, 169, 176, 184, 277, 294, 304-307, 313-359, 366-387, 394-401, 417-420, 431, 451, 460-481, 489-491, 498-511, 515-521, 525-548, 552-555, 559-560, 564-576, 580-587, 591-592, 621, 625-629
+owlapy/iri.py                                           79      6    92%   54, 69, 82, 97, 128, 133
 owlapy/meta_classes.py                                  11      0   100%
 owlapy/namespaces.py                                    27      3    89%   36, 40, 43
-owlapy/owl_annotation.py                                17      4    76%   17, 25, 43, 51
-owlapy/owl_axiom.py                                    518    157    70%   36, 39, 42, 45, 59, 111-113, 116, 136-138, 141, 144, 147-150, 153, 182-184, 187, 190, 193, 196-200, 203, 253-256, 259-261, 264, 288, 291, 294, 332-335, 338-340, 343, 398-401, 404-406, 409, 533-536, 539, 561-563, 566, 569, 572, 575, 578-581, 584, 620-623, 626, 645-648, 652, 656, 674-675, 683, 692, 695-697, 700, 711, 733-737, 745, 753, 761, 764-766, 769, 786-788, 791, 794, 797-800, 803, 822-824, 827, 830, 833-836, 839, 858-860, 863, 866, 869-872, 875, 905-908, 911, 982-985, 988, 1018, 1044, 1071-1073, 1076, 1091, 1103, 1116, 1129, 1142, 1157, 1172, 1185-1187, 1190, 1208, 1227-1230, 1233, 1254-1257, 1260
+owlapy/owl_annotation.py                                16      4    75%   16, 24, 42, 50
+owlapy/owl_axiom.py                                    519    130    75%   39, 42, 45, 59, 111-113, 116, 136-138, 141, 144, 147-150, 153, 182-184, 187, 190, 193, 196-200, 203, 253-256, 261, 288, 291, 294, 332-335, 338-340, 343, 398-401, 404-406, 409, 536, 561-563, 566, 569, 572, 575, 578-581, 584, 623, 645-648, 652, 656, 674-675, 683, 692, 695-697, 700, 711, 734-738, 746, 754, 762, 765-767, 770, 787-789, 792, 795, 798-801, 804, 823-825, 828, 831, 834-837, 840, 859-861, 864, 867, 870-873, 876, 909, 986, 1019, 1045, 1074, 1077, 1092, 1104, 1117, 1130, 1173, 1186-1188, 1191, 1209
 owlapy/owl_data_ranges.py                               40      1    98%   46
 owlapy/owl_datatype.py                                  20      2    90%   33-34
 owlapy/owl_individual.py                                20      1    95%   37
-owlapy/owl_literal.py                                  286     73    74%   49, 77, 86, 90, 99, 103, 112, 116, 125, 129, 138, 142, 151, 155, 164, 169, 173, 203, 208, 217, 221, 244, 247-249, 252, 258, 262, 288, 293, 302, 306, 311, 323, 329, 332-334, 337, 340, 346, 350, 355, 373, 376-378, 381, 387, 391, 415, 418-420, 423, 429, 433, 454, 459, 462-464, 467, 473, 477, 489-491, 494, 497-499, 502
-owlapy/owl_object.py                                    27      4    85%   24, 79-81
-owlapy/owl_ontology.py                                 391     40    90%   86, 97-100, 103, 109-111, 249, 292-295, 304, 312, 329, 341, 345, 358, 371, 376, 379-381, 384, 423, 433, 449-450, 473-474, 553-554, 595, 599, 603, 629, 736, 742, 750
-owlapy/owl_ontology_manager.py                         568    167    71%   48, 140, 151, 155, 168-169, 177, 200, 208-211, 312-318, 341-350, 355-376, 396, 466, 469, 474-496, 501-511, 521-527, 539, 542-543, 583, 588-593, 603, 608, 625, 634-645, 650-665, 676, 681, 691, 703, 707, 743, 749, 760, 766, 771-795, 800-807, 825-831, 850, 853, 859-862, 888
+owlapy/owl_literal.py                                  286     66    77%   49, 77, 86, 90, 99, 103, 112, 116, 125, 129, 138, 142, 151, 155, 164, 169, 173, 203, 208, 217, 221, 244, 247-249, 258, 262, 288, 293, 302, 306, 311, 323, 329, 332-334, 337, 340, 346, 350, 355, 373, 378, 387, 391, 415, 420, 429, 433, 454, 459, 462-464, 467, 473, 477, 489-491, 494, 497-499, 502
+owlapy/owl_object.py                                    29      4    86%   26, 81-83
+owlapy/owl_ontology.py                                1000    222    78%   99, 110-113, 116, 124, 142-148, 171, 179-182, 283-289, 312-321, 326-347, 367, 437, 440, 445-467, 472-482, 492-498, 510, 513-514, 554, 559-564, 574, 579, 596, 605-616, 621-636, 647, 652, 662, 674, 678, 714, 720, 731, 737, 742-766, 771-778, 807, 822-823, 841-844, 853, 861, 878, 890, 894, 907, 920, 928-929, 936-937, 942, 951-956, 963, 966-968, 971, 988, 992-993, 1017, 1020, 1023, 1026, 1029, 1036, 1074, 1083-1086, 1089-1092, 1097, 1100, 1140, 1150, 1166-1167, 1190-1191, 1270-1271, 1312, 1316, 1320, 1346, 1453, 1459, 1467
+owlapy/owl_ontology_manager.py                          66     19    71%   26, 37, 41, 54-55, 63, 82, 85-89, 100-103, 112, 129-133
 owlapy/owl_property.py                                  69     11    84%   17, 24, 32, 40, 67, 76, 126, 158, 162, 174, 193
-owlapy/owl_reasoner.py                                 841    175    79%   452-455, 572, 584-586, 591-597, 604, 653-659, 665-669, 727-734, 760, 795-799, 825-828, 856-858, 860-862, 871, 884-886, 888-890, 897, 902-904, 924, 928-929, 942-944, 965, 1010-1012, 1113, 1121, 1124, 1127, 1130, 1133, 1136, 1139, 1142, 1145, 1160-1162, 1168, 1172, 1175, 1178, 1181, 1184, 1187, 1193, 1196, 1210, 1240-1243, 1251-1290, 1305, 1318-1328, 1353-1356, 1372, 1386, 1456-1460, 1488, 1498-1502, 1510-1514, 1555-1561, 1573, 1632, 1635, 1638, 1641, 1644, 1647, 1650, 1653, 1657, 1661, 1665, 1668, 1671, 1674, 1677, 1680, 1683, 1687, 1691, 1694, 1697
-owlapy/owlapi_adaptor.py                               130     65    50%   18, 74-76, 91-96, 110-115, 151-152, 164-165, 179-180, 195-196, 214, 232, 251, 271, 287, 305, 320, 333, 346, 361, 376, 390, 404, 419, 434, 450, 454-483, 511
-owlapy/owlapi_mapper.py                                103     14    86%   35, 51, 72, 76, 80, 84, 88, 133-136, 141, 145, 149
-owlapy/parser.py                                       371     16    96%   316, 327, 400-401, 416, 577, 618, 656, 667, 721, 723, 751-752, 763, 779-780
+owlapy/owl_reasoner.py                                 845    131    84%   170, 182-184, 189-195, 202, 251-257, 263-265, 308-315, 341, 376-380, 406-409, 437-439, 441-443, 452, 465-467, 469-471, 478, 483-485, 505, 509-510, 523-525, 546, 591-593, 607-609, 627-628, 639-642, 645, 651, 675-684, 696, 701, 705, 753-756, 861-865, 887, 894, 904-908, 916-920, 961-967, 979, 1100-1102, 1202, 1334, 1349, 1364, 1506-1527, 1558, 1590
+owlapy/owlapi_mapper.py                                357     62    83%   30, 106, 125-126, 193-200, 206-209, 218, 222, 229, 236, 240, 244, 248, 252, 256, 260, 264, 268, 272, 276, 280, 285, 291, 295, 299, 312, 328, 340, 350, 361, 366, 376, 381, 398, 416, 431, 436, 442, 447, 451, 456, 461, 466, 471-479, 508-509
+owlapy/parser.py                                       371     12    97%   316, 327, 400-401, 416, 656, 667, 751-752, 763, 779-780
 owlapy/providers.py                                     38      3    92%   41, 54, 56
-owlapy/render.py                                       290     46    84%   79-114, 143-158, 176, 180, 186, 206, 222, 231, 236, 241, 375, 379, 386, 405, 421, 430, 435, 440
-owlapy/utils.py                                        766    227    70%   164, 168, 172, 178, 184-188, 192-196, 200, 204, 208, 214, 218, 222, 226, 230, 236, 242, 248, 252, 256, 260, 264-267, 271-274, 278, 285, 300-302, 305-314, 317, 320, 323, 326, 329, 333-339, 343, 354, 358, 362, 366, 370, 374-378, 382-386, 390-394, 398-402, 406, 410, 414-419, 423-428, 432-437, 441, 445, 449-453, 457-461, 465-469, 473-477, 481-485, 489, 493-497, 501, 505-510, 514-519, 523-528, 532, 536-540, 545, 554, 558, 562, 566, 570, 574, 578, 582-587, 591-597, 601, 605, 609, 614, 619, 624, 628, 632, 636, 640, 644-647, 651-654, 658, 662, 666, 671, 676, 681, 685, 736, 740, 746, 748, 751, 753, 796, 852, 866-868, 877, 919-920, 940, 1039, 1044, 1049, 1071, 1075, 1083, 1087, 1092, 1164-1182, 1195-1197, 1202-1206
-owlapy/vocab.py                                         92      4    96%   32, 35, 113-114
+owlapy/render.py                                       289     43    85%   78-113, 142-157, 175, 179, 185, 221, 230, 235, 240, 374, 378, 420, 429, 434, 439
+owlapy/static_funcs.py                                  33     19    42%   21-26, 31-42, 57-59
+owlapy/utils.py                                        794    304    62%   30-31, 54-58, 75-86, 229, 233, 237, 243, 249-253, 257-261, 265, 269, 273, 279, 283, 287, 291, 295, 301, 307, 313, 317, 321, 325, 329-332, 336-339, 343, 350, 365-367, 370-379, 382, 385, 388, 391, 394, 398-404, 408, 419, 423, 427, 431, 435, 439-443, 447-451, 455-459, 463-467, 471, 475, 479-484, 488-493, 497-502, 506, 510, 514-518, 522-526, 530-534, 538-542, 546-550, 554, 558-562, 566, 570-575, 579-584, 588-593, 597, 601-605, 610, 619, 623, 627, 631, 635, 639, 643, 647-652, 656-662, 666, 670, 674, 679, 684, 689, 693, 697, 701, 705, 709-712, 716-719, 723, 727, 731, 736, 741, 746, 750, 799, 801, 803, 805, 807, 811, 813, 816, 818, 835, 861, 917, 931-933, 941-942, 962, 984-985, 1005, 1042-1043, 1058-1059, 1076-1104, 1109, 1114, 1123-1152, 1157, 1162-1164, 1229-1247, 1260-1262, 1267-1271
+owlapy/vocab.py                                         92      3    97%   32, 113-114
 ----------------------------------------------------------------------------------
-TOTAL                                                 5517   1238    78%
+TOTAL                                                 5919   1263    79%
 ```
\ No newline at end of file
diff --git a/docs/usage/main.md b/docs/usage/main.md
index 2cf8cac5..36b77c2b 100644
--- a/docs/usage/main.md
+++ b/docs/usage/main.md
@@ -1,6 +1,6 @@
 # About owlapy
 
-**Version:** owlapy 1.3.1
+**Version:** owlapy 1.3.2
 
 **GitHub repository:** [https://github.com/dice-group/owlapy](https://github.com/dice-group/owlapy)
 
diff --git a/docs/usage/ontologies.md b/docs/usage/ontologies.md
index 73d2477d..6d9cfc47 100644
--- a/docs/usage/ontologies.md
+++ b/docs/usage/ontologies.md
@@ -154,7 +154,7 @@ onto.add_axiom(dp_assertion_axiom)
 ```
 
 [OWLLiteral](owlapy.owl_literal.OWLLiteral) is a class that represents the literal values in
-Owlapy. We have stored the integer literal value of '18' in the variable `literal_17`.
+Owlapy. We have stored the integer literal value of '17' in the variable `literal_17`.
 Then we construct the `OWLDataPropertyAssertionAxiom` by passing as the first argument, the 
 individual `heinz`, as the second argument the data property `hasAge_dp`, and the third 
 argument the literal value `literal_17`. Finally, add it to the ontology by using `add_axiom` 
diff --git a/docs/usage/owlapi_adaptor.md b/docs/usage/owlapi_synchronization.md
similarity index 100%
rename from docs/usage/owlapi_adaptor.md
rename to docs/usage/owlapi_synchronization.md
diff --git a/docs/usage/reasoner.md b/docs/usage/reasoner.md
index 59bd898b..63373410 100644
--- a/docs/usage/reasoner.md
+++ b/docs/usage/reasoner.md
@@ -6,93 +6,78 @@ component is required.
 For this guide we will also consider the 'father' ontology that we slightly described [here](ontologies.md):
 
 ```python
+from owlapy.iri import IRI
 from owlapy.owl_ontology_manager import OntologyManager
 
 manager = OntologyManager()
 onto = manager.load_ontology(IRI.create("KGs/Family/father.owl"))
 ```
 
-In our Owlapy library, we provide several **reasoners** to choose
-from:
+In our Owlapy library, we provide two main reasoner classes:
 
-- [**OntologyReasoner**](owlapy.owl_reasoner.OntologyReasoner)
 
-    Or differently Structural Reasoner, is the base reasoner in Owlapy. The functionalities
-  of this reasoner are limited. It does not provide full reasoning in _ALCH_. Furthermore,
-  it has no support for instances of complex class expressions, which is covered by the
-  other reasoners (SyncReasoner and FIC). This reasoner is used as
-  a base reasoner for FIC which overwrites the `instances` method. 
-  We recommend using the other reasoners for any reasoning tasks.
+- [**StructuralReasoner**](owlapy.owl_reasoner.StructuralReasoner) (What used to be FastInstanceCheckerReasoner )
 
-    **Initialization:**
+    Structural Reasoner is the base reasoner in Owlapy. This reasoner works 
+   under CWA/PCWA and the base library used for it is _owlready2_. The functionalities
+  of this reasoner are limited and may be incomplete. It does not provide full reasoning in _ALCH_. 
+  It provides support for finding instance of complex class expression.
+  It has a cache storing system that allows for faster execution of some reasoning functionalities.
 
-   ```python
-   from owlapy.owl_reasoner import OntologyReasoner
-   
-   structural_reasoner = OntologyReasoner(onto)
-   ```
+    **Initialization:**
 
-    The structural reasoner requires an ontology ([OWLOntology](owlapy.owl_ontology.OWLOntology)).
+    ```python
+    from owlapy.owl_reasoner import StructuralReasoner
     
+    structural_reasoner = StructuralReasoner(onto, property_cache = True, negation_default = True, sub_properties = False)
+    ```
+  The structural reasoner requires an ontology ([AbstractOWLOntology](owlapy.abstracts.AbstractOWLOntology)).
+  `property_cache` specifies whether to cache property values. This
+  requires more memory, but it speeds up the reasoning processes. If `negation_default` argument is set
+  to `True` the missing facts in the ontology means false. The argument
+    `sub_properties` is another boolean argument to specify whether you want to take sub properties in consideration
+  for `instances()` method.
 
 
 - [**SyncReasoner**](owlapy.owl_reasoner.SyncReasoner)
-
-    Can perform full reasoning in _ALCH_ due to the use of reasoners from 
-  owlapi like HermiT, Pellet, etc. and provides support for
-  complex class expression instances (when using the method `instances`). 
+  
+  SyncReasoner is a class that serves as a 'syncing' class 
+  between our framework and reasoners in _owlapi_. It
+  can perform full reasoning in _ALCH_ due to the use of reasoners from 
+  powerful reasoners like HermiT, Pellet, etc. 
   SyncReasoner is more useful when your main goal is reasoning over the ontology,
-  and you are familiarized with the java reasoners (HermiT, Pellet, ...).
+  and you are familiarized with the java reasoners (HermiT, Pellet, JFact, Openllet, ...).
 
     **Initialization:**
 
     ```python
     from owlapy.owl_reasoner import SyncReasoner
     
-    sync_reasoner = SyncReasoner(ontology_path="KGs/Mutagenesis/mutagenesis.owl", reasoner="HermiT")
+    sync_reasoner = SyncReasoner(ontology="KGs/Mutagenesis/mutagenesis.owl", reasoner="HermiT")
     ```
     
-    Sync Reasoner is made available by [owlapi adaptor](owlapi_adaptor.md) and requires the ontology path
-    together with a reasoner name from the possible set of reasoners: `"Hermit"`, `"Pellet"`, `"JFact"`, `"Openllet"`.
-
-
-- [**FastInstanceCheckerReasoner**](owlapy.owl_reasoner.FastInstanceCheckerReasoner) **(FIC)**
-
-    FIC also provides support for complex class expression but the rest of the methods are the same as in
-  the base reasoner.
-  It has a cache storing system that allows for faster execution of some reasoning functionalities. Due to this
-  feature, FIC is more appropriate to be used in concept learning.
-
-    **Initialization:**
-
-    ```python
-    from owlapy.owl_reasoner import FastInstanceCheckerReasoner
-    
-    fic_reasoner = FastInstanceCheckerReasoner(onto, structural_reasoner, property_cache = True,
-                                                   negation_default = True, sub_properties = False)
-    ```
-    Besides the ontology, FIC requires a base reasoner to delegate any reasoning tasks not covered by it.
-  This base reasoner
-  can be any other reasoner in Owlapy (usually it's [OntologyReasoner](owlapy.owl_reasoner.OntologyReasoner)).
-  `property_cache` specifies whether to cache property values. This
-  requires more memory, but it speeds up the reasoning processes. If `negation_default` argument is set
-  to `True` the missing facts in the ontology means false. The argument
-    `sub_properties` is another boolean argument to specify whether you want to take sub properties in consideration
-  for `instances()` method.
+    SyncReasoner is made available by [owlapi mapper](owlapi_synchronization.md) and requires the ontology path or an
+    object of type [SyncOntology](owlapy.owl_ontology.SyncOntology),
+    together with a reasoner name from the possible set of reasoners: `"Hermit"`, `"Pellet"`, `"JFact"`, `"Openllet"`
+   `"StructuralReasoner"`.
+ 
+   
+   **Note that SyncReasoner with `reasoner` argument set to `"StructuralReasoner"` is refering to 
+   _StructuralReasoner_ implemented in owlapi. That is different from our StructuralReasoner.**
 
+  
 ## Usage of the Reasoner
 All the reasoners available in the Owlapy library inherit from the
-class: [OWLReasonerEx](owlapy.owl_reasoner.OWLReasonerEx). This class provides some 
-extra convenient methods compared to its base abstract class [OWLReasoner](owlapy.owl_reasoner.OWLReasoner).
-Further on, in this guide, we use [FastInstanceCheckerReasoner](owlapy.owl_reasoner.FastInstanceCheckerReasoner)
+class: [AbstractOWLReasoner](owlapy.abstracts.AbstractOWLReasoner).
+Further on, in this guide, we use [StructuralReasoner](owlapy.owl_reasoner.StructuralReasoner)
 to show the capabilities of a reasoner in Owlapy.
 
-As mentioned earlier we will use the _father_ dataset to give examples.
+We will proceed to use the _father_ dataset to give examples.
 
 
 ## Class Reasoning
 
-Using an [OWLOntology](owlapy.owl_ontology.OWLOntology) you can list all the classes in the signature, 
+Using an [AbstractOWLOntology](owlapy.abstracts.AbstractOWLOntology) you can list all the classes in the signature, 
 but a reasoner can give you more than that. You can get the subclasses, superclasses or the 
 equivalent classes of a class in the ontology:
 
@@ -105,9 +90,9 @@ from owlapy.iri import IRI
 namespace = "http://example.com/father#"
 male = OWLClass(IRI(namespace, "male"))
 
-male_super_classes = fic_reasoner.super_classes(male)
-male_sub_classes = fic_reasoner.sub_classes(male)
-male_equivalent_classes = fic_reasoner.equivalent_classes(male)
+male_super_classes = structural_reasoner.super_classes(male)
+male_sub_classes = structural_reasoner.sub_classes(male)
+male_equivalent_classes = structural_reasoner.equivalent_classes(male)
 ```
 
 We define the _male_ class by creating an [OWLClass](owlapy.class_expression.owl_class.OWLClass) object. The 
@@ -123,18 +108,17 @@ means that it will return only the named classes.
 >**NOTE**: The extra arguments `direct` and `only_named` are also used in other methods that reason
 upon the class, object property, or data property hierarchy.
 
->**NOTE**: SyncReasoner implements OWLReasoner where we can specify the `only_named` argument
-> in some methods but in java reasoners there is no use for such argument and therefore this
-> argument is trivial when used in SyncReasoner's methods. 
+>**NOTE**: In SyncReasoner, there is no use for the argument `only_named` as this is not
+> supported by methods in the java library owlapi. 
 
 You can get all the types of a certain individual using `types` method:
 
 <!--pytest-codeblocks:cont-->
 
 ```python
-anna = list(onto.individuals_in_signature()).pop()
+anna = list(onto.individuals_in_signature()).pop(0)
 
-anna_types = fic_reasoner.types(anna)
+anna_types = structural_reasoner.types(anna)
 ```
 
 We retrieve _anna_ as the first individual on the list of individuals 
@@ -144,7 +128,7 @@ of the 'Father' ontology. The `type` method only returns named classes.
 ## Object Properties and Data Properties Reasoning
 Owlapy reasoners offers some convenient methods for working with object properties and 
 data properties. Below we show some of them, but you can always check all the methods in the 
-[OWLReasoner](owlapy.owl_reasoner.OWLReasoner)
+[AbstractOWLReasoner](owlapy.abstracts.AbstractOWLReasoner)
 class documentation. 
 
 You can get all the object properties that an individual has by using the 
@@ -153,7 +137,7 @@ following method:
 <!--pytest-codeblocks:cont-->
 ```python
 anna = individuals[0] 
-object_properties = fic_reasoner.ind_object_properties(anna)
+object_properties = structural_reasoner.ind_object_properties(anna)
 ```
 In this example, `object_properties` contains all the object properties
 that _anna_ has, which in our case would only be _hasChild_.
@@ -162,7 +146,7 @@ Now we can get the individuals of this object property for _anna_.
 <!--pytest-codeblocks:cont-->
 ```python
 for op in object_properties:
-    object_properties_values = fic_reasoner.object_property_values(anna, op)
+    object_properties_values = structural_reasoner.object_property_values(anna, op)
     for individual in object_properties_values:
         print(individual)
 ```
@@ -190,16 +174,16 @@ from owlapy.owl_property import OWLObjectProperty
 
 hasChild = OWLObjectProperty(IRI(namespace, "hasChild"))
 
-equivalent_to_hasChild = fic_reasoner.equivalent_object_properties(hasChild)
-hasChild_sub_properties = fic_reasoner.sub_object_properties(hasChild)
+equivalent_to_hasChild = structural_reasoner.equivalent_object_properties(hasChild)
+hasChild_sub_properties = structural_reasoner.sub_object_properties(hasChild)
 ```
 
 In case you want to get the domains and ranges of an object property use the following:
 
 <!--pytest-codeblocks:cont-->
 ```python
-hasChild_domains = fic_reasoner.object_property_domains(hasChild)
-hasChild_ranges = fic_reasoner.object_property_ranges(hasChild)
+hasChild_domains = structural_reasoner.object_property_domains(hasChild)
+hasChild_ranges = structural_reasoner.object_property_ranges(hasChild)
 ```
 
 > **NOTE:** Again, you can do the same for data properties but instead of the word 'object' in the 
@@ -217,7 +201,7 @@ Let us now show a simple example by finding the instances of the class _male_ an
 
 <!--pytest-codeblocks:cont-->
 ```python
-male_individuals = fic_reasoner.instances(male)
+male_individuals = structural_reasoner.instances(male)
 for ind in male_individuals:
     print(ind)
 ```
@@ -225,7 +209,7 @@ for ind in male_individuals:
 -----------------------------------------------------------------------
 
 In this guide we covered the main functionalities of the reasoners in Owlapy. 
-In the next one, we speak about owlapi adaptor and how can make use of owlapi in owlapy.
+In the next one, we speak about owlapi synchronization and how can make use of owlapi in owlapy.
 
 
 
diff --git a/examples/ontology_reasoning.py b/examples/ontology_reasoning.py
index dd12db7f..5a015d74 100644
--- a/examples/ontology_reasoning.py
+++ b/examples/ontology_reasoning.py
@@ -4,7 +4,7 @@
 from owlapy.owl_individual import OWLNamedIndividual
 from owlapy.owl_ontology_manager import OntologyManager
 from owlapy.owl_property import OWLDataProperty, OWLObjectProperty
-from owlapy.owl_reasoner import OntologyReasoner, FastInstanceCheckerReasoner
+from owlapy.owl_reasoner import StructuralReasoner
 
 data_file = '../KGs/Test/test_ontology.owl'
 NS = 'http://www.semanticweb.org/stefan/ontologies/2023/1/untitled-ontology-11#'
@@ -126,11 +126,10 @@
 onto.add_axiom(OWLSubClassOfAxiom(R, r5Q))
 onto.add_axiom(OWLSubClassOfAxiom(ST, U))
 
-base_reasoner = OntologyReasoner(onto)
 
 # ---------------------------------------- Reasoning ----------------------------------------
 
-reasoner = FastInstanceCheckerReasoner(onto, base_reasoner)
+reasoner = StructuralReasoner(onto)
 
 # Instances
 t1 = list(reasoner.instances(N))
diff --git a/owlapy/__init__.py b/owlapy/__init__.py
index 2b3878c9..84aec36b 100644
--- a/owlapy/__init__.py
+++ b/owlapy/__init__.py
@@ -3,7 +3,7 @@
 from .converter import owl_expression_to_sparql, owl_expression_to_sparql_with_confusion_matrix
 from .owl_ontology_manager import OntologyManager
 
-__version__ = '1.3.1'
+__version__ = '1.3.2'
 
 __all__ = [
     'owl_expression_to_dl', 'owl_expression_to_manchester',
diff --git a/owlapy/abstracts/__init__.py b/owlapy/abstracts/__init__.py
index 49b5a7ab..3d223eb2 100644
--- a/owlapy/abstracts/__init__.py
+++ b/owlapy/abstracts/__init__.py
@@ -1,5 +1,4 @@
 from .abstract_owl_ontology_manager import AbstractOWLOntologyManager, AbstractOWLOntologyChange, AbstractOWLOntology
-from .abstract_owl_reasoner import AbstractOWLReasoner, AbstractOWLReasonerEx
+from .abstract_owl_reasoner import AbstractOWLReasoner
 
-__all__ = ['AbstractOWLOntologyManager', 'AbstractOWLOntologyChange', 'AbstractOWLOntology', 'AbstractOWLReasoner',
-           'AbstractOWLReasonerEx']
+__all__ = ['AbstractOWLOntologyManager', 'AbstractOWLOntologyChange', 'AbstractOWLOntology', 'AbstractOWLReasoner']
diff --git a/owlapy/abstracts/abstract_owl_reasoner.py b/owlapy/abstracts/abstract_owl_reasoner.py
index 987c3f2a..c5ba3005 100644
--- a/owlapy/abstracts/abstract_owl_reasoner.py
+++ b/owlapy/abstracts/abstract_owl_reasoner.py
@@ -377,11 +377,6 @@ class expression with respect to the imports closure of the root ontology.
         """
         pass
 
-
-class AbstractOWLReasonerEx(AbstractOWLReasoner, metaclass=ABCMeta):
-    """Extra convenience methods for OWL Reasoners"""
-
-    # default
     def data_property_ranges(self, pe: OWLDataProperty, direct: bool = False) -> Iterable[OWLDataRange]:
         """Gets the data ranges that are the direct or indirect ranges of this property with respect to the imports
         closure of the root ontology.
diff --git a/owlapy/class_expression/nary_boolean_expression.py b/owlapy/class_expression/nary_boolean_expression.py
index 0cd2a683..466c15b8 100644
--- a/owlapy/class_expression/nary_boolean_expression.py
+++ b/owlapy/class_expression/nary_boolean_expression.py
@@ -15,8 +15,11 @@ def __init__(self, operands: Iterable[OWLClassExpression]):
         Args:
             operands: Class expressions.
         """
+        # TODO: CD: Replace tuple with set
         self._operands = tuple(operands)
 
+        assert len(self._operands)>1, "OWLNaryBooleanClassExpression requires at least one operand."
+
     def operands(self) -> Iterable[OWLClassExpression]:
         # documented in parent
         yield from self._operands
@@ -26,8 +29,9 @@ def __repr__(self):
 
     def __eq__(self, other):
         if type(other) is type(self):
-            return self._operands == other._operands
-        return NotImplemented
+            return {i for i in self._operands} == { j for j in other.operands()}
+        else:
+            return False
 
     def __hash__(self):
         return hash(self._operands)
diff --git a/owlapy/class_expression/restriction.py b/owlapy/class_expression/restriction.py
index 2ccc7248..911a718a 100644
--- a/owlapy/class_expression/restriction.py
+++ b/owlapy/class_expression/restriction.py
@@ -148,7 +148,7 @@ class OWLObjectCardinalityRestriction(OWLCardinalityRestriction[OWLClassExpressi
     __slots__ = ()
 
     _property: OWLObjectPropertyExpression
-
+    # @TODO: CD: property shows the in-built function
     @abstractmethod
     def __init__(self, cardinality: int, property: OWLObjectPropertyExpression, filler: OWLClassExpression):
         super().__init__(cardinality, filler)
@@ -167,8 +167,8 @@ def __eq__(self, other):
             return self._property == other._property \
                 and self._cardinality == other._cardinality \
                 and self._filler == other._filler
-        return NotImplemented
-
+        else:
+            return False
     def __hash__(self):
         return hash((self._property, self._cardinality, self._filler))
 
@@ -288,7 +288,7 @@ class expression CE, and it contains all those individuals that are connected by
     individuals that are instances of CE. (https://www.w3.org/TR/owl2-syntax/#Universal_Quantification)"""
     __slots__ = '_property', '_filler'
     type_index: Final = 3006
-
+    # @TODO: CD: property shows the in-built function
     def __init__(self, property: OWLObjectPropertyExpression, filler: OWLClassExpression):
         super().__init__(filler)
         self._property = property
@@ -299,7 +299,8 @@ def __repr__(self):
     def __eq__(self, other):
         if type(other) is type(self):
             return self._filler == other._filler and self._property == other._property
-        return NotImplemented
+        else:
+            return False
 
     def __hash__(self):
         return hash((self._filler, self._property))
@@ -337,7 +338,8 @@ def get_property(self) -> OWLObjectPropertyExpression:
     def __eq__(self, other):
         if type(other) is type(self):
             return self._property == other._property
-        return NotImplemented
+        else:
+            return False
 
     def __hash__(self):
         return hash(self._property)
@@ -357,7 +359,7 @@ class OWLObjectHasValue(OWLHasValueRestriction[OWLIndividual], OWLObjectRestrict
 
     _property: OWLObjectPropertyExpression
     _v: OWLIndividual
-
+    # @TODO: CD: property shows the in-built function
     def __init__(self, property: OWLObjectPropertyExpression, individual: OWLIndividual):
         """
         Args:
@@ -393,13 +395,15 @@ class OWLObjectOneOf(OWLAnonymousClassExpression, HasOperands[OWLIndividual]):
     __slots__ = '_values'
     type_index: Final = 3004
 
-    def __init__(self, values: Union[OWLIndividual, Iterable[OWLIndividual]]):
+    def __init__(self, values: OWLIndividual | Iterable[OWLIndividual]):
+        #assert isinstance(values, OWLIndividual) | isinstance(values, set)
+        #    f"The input of OWLObjectOneOf must be either an OWLIndividual or a set of OWLIndividual. Currently, {type(values)}!"
         if isinstance(values, OWLIndividual):
             self._values = values,
         else:
             for _ in values:
                 assert isinstance(_, OWLIndividual)
-            self._values = tuple(values)
+            self._values = {i for i in values}
 
     def individuals(self) -> Iterable[OWLIndividual]:
         """Gets the individuals that are in the oneOf. These individuals represent the exact instances (extension)
@@ -431,7 +435,8 @@ def __hash__(self):
     def __eq__(self, other):
         if type(other) is type(self):
             return self._values == other._values
-        return NotImplemented
+        else:
+            return False
 
     def __repr__(self):
         return f'OWLObjectOneOf({self._values})'
@@ -450,8 +455,6 @@ def is_data_restriction(self) -> bool:
         # documented in parent
         return True
 
-    pass
-
 
 class OWLQuantifiedDataRestriction(OWLQuantifiedRestriction[OWLDataRange],
                                    OWLDataRestriction, metaclass=ABCMeta):
@@ -463,7 +466,7 @@ class OWLQuantifiedDataRestriction(OWLQuantifiedRestriction[OWLDataRange],
     def __init__(self, filler: OWLDataRange):
         assert isinstance(filler, OWLDataRange), "filler must be an OWLDataRange"
         self._filler = filler
-
+    # @TODO:CD: define it as @property
     def get_filler(self) -> OWLDataRange:
         # documented in parent (HasFiller)
         return self._filler
@@ -476,7 +479,7 @@ class OWLDataCardinalityRestriction(OWLCardinalityRestriction[OWLDataRange],
     __slots__ = ()
 
     _property: OWLDataPropertyExpression
-
+    # @TODO: CD: property shows the in-built function
     @abstractmethod
     def __init__(self, cardinality: int, property: OWLDataPropertyExpression, filler: OWLDataRange):
         assert isinstance(filler, OWLDataRange), "filler must be an OWLDataRange"
@@ -511,7 +514,7 @@ class OWLDataMinCardinality(OWLDataCardinalityRestriction):
     __slots__ = '_cardinality', '_filler', '_property'
 
     type_index: Final = 3015
-
+    # @TODO: CD: property shows the in-built function
     def __init__(self, cardinality: int, property: OWLDataPropertyExpression, filler: OWLDataRange):
         """
         Args:
@@ -534,7 +537,7 @@ class OWLDataMaxCardinality(OWLDataCardinalityRestriction):
     __slots__ = '_cardinality', '_filler', '_property'
 
     type_index: Final = 3017
-
+    # @TODO: CD: property shows the in-built function
     def __init__(self, cardinality: int, property: OWLDataPropertyExpression, filler: OWLDataRange):
         """
         Args:
@@ -557,7 +560,7 @@ class OWLDataExactCardinality(OWLDataCardinalityRestriction):
     __slots__ = '_cardinality', '_filler', '_property'
 
     type_index: Final = 3016
-
+    # @TODO: CD: property shows the in-built function
     def __init__(self, cardinality: int, property: OWLDataPropertyExpression, filler: OWLDataRange):
         """
         Args:
@@ -593,7 +596,7 @@ class OWLDataSomeValuesFrom(OWLQuantifiedDataRestriction):
     type_index: Final = 3012
 
     _property: OWLDataPropertyExpression
-
+    # @TODO: CD: property shows the in-built function
     def __init__(self, property: OWLDataPropertyExpression, filler: OWLDataRange):
         """Gets an OWLDataSomeValuesFrom restriction.
 
@@ -613,8 +616,8 @@ def __repr__(self):
     def __eq__(self, other):
         if type(other) is type(self):
             return self._filler == other._filler and self._property == other._property
-        return NotImplemented
-
+        else:
+            return False
     def __hash__(self):
         return hash((self._filler, self._property))
 
@@ -636,7 +639,7 @@ class OWLDataAllValuesFrom(OWLQuantifiedDataRestriction):
     type_index: Final = 3013
 
     _property: OWLDataPropertyExpression
-
+    # @TODO:CD:property shows the in-built function
     def __init__(self, property: OWLDataPropertyExpression, filler: OWLDataRange):
         """Gets an OWLDataAllValuesFrom restriction.
 
@@ -656,7 +659,8 @@ def __repr__(self):
     def __eq__(self, other):
         if type(other) is type(self):
             return self._filler == other._filler and self._property == other._property
-        return NotImplemented
+        else:
+            return False
 
     def __hash__(self):
         return hash((self._filler, self._property))
@@ -673,11 +677,13 @@ class OWLDataHasValue(OWLHasValueRestriction[OWLLiteral], OWLDataRestriction):
     (https://www.w3.org/TR/owl2-syntax/#Literal_Value_Restriction)
     """
     __slots__ = '_property'
+    # @TODO:CD:What is _v? even if it is inherited from somewhere, we should add it into docstring.
+    # @TODO:CD: We should also name the class attributes in a more meaningful manner.
 
     type_index: Final = 3014
 
     _property: OWLDataPropertyExpression
-
+    # @TODO: CD: property shows the in-built function
     def __init__(self, property: OWLDataPropertyExpression, value: OWLLiteral):
         """Gets an OWLDataHasValue restriction.
 
@@ -729,7 +735,7 @@ def __init__(self, values: Union[OWLLiteral, Iterable[OWLLiteral]]):
             for _ in values:
                 assert isinstance(_, OWLLiteral)
             self._values = tuple(values)
-
+    # TODO:CD: define it as @property as the name of the class method does not correspond to an action
     def values(self) -> Iterable[OWLLiteral]:
         """Gets the values that are in the oneOf.
 
@@ -747,8 +753,9 @@ def __hash__(self):
 
     def __eq__(self, other):
         if type(other) is type(self):
-            return self._values == other._values
-        return NotImplemented
+            return {i for i in self._values} == {j for j in other._values}
+        else:
+            return False
 
     def __repr__(self):
         return f'OWLDataOneOf({self._values})'
diff --git a/owlapy/owl_ontology.py b/owlapy/owl_ontology.py
index 683a947b..d527383e 100644
--- a/owlapy/owl_ontology.py
+++ b/owlapy/owl_ontology.py
@@ -779,11 +779,12 @@ def _(axiom: OWLDataPropertyCharacteristicAxiom, ontology: AbstractOWLOntology,
 
 
 class Ontology(AbstractOWLOntology):
-    __slots__ = '_manager', '_iri', '_world', '_onto'
+    __slots__ = '_manager', '_iri', '_world', '_onto', 'is_modified'
 
     _manager: _OM
     _onto: owlready2.Ontology
     _world: owlready2.World
+    is_modified: bool
 
     def __init__(self, manager: _OM, ontology_iri: IRI, load: bool):
         """Represents an Ontology in Ontolearn.
@@ -796,6 +797,7 @@ def __init__(self, manager: _OM, ontology_iri: IRI, load: bool):
         self._manager = manager
         self._iri = ontology_iri
         self._world = manager._world
+        self.is_modified = False
         onto = self._world.get_ontology(ontology_iri.as_str())
         if load:
             onto = onto.load()
@@ -919,6 +921,7 @@ def object_property_range_axioms(self, pe: OWLObjectProperty) -> Iterable[OWLObj
                     pass  # XXX TODO
 
     def add_axiom(self, axiom: Union[OWLAxiom, Iterable[OWLAxiom]]):
+        self.is_modified = True
         if isinstance(axiom, OWLAxiom):
             _add_axiom(axiom, self, self._world)
         else:
@@ -926,6 +929,7 @@ def add_axiom(self, axiom: Union[OWLAxiom, Iterable[OWLAxiom]]):
                 _add_axiom(ax, self, self._world)
 
     def remove_axiom(self, axiom: Union[OWLAxiom, Iterable[OWLAxiom]]):
+        self.is_modified = True
         if isinstance(axiom, OWLAxiom):
             _remove_axiom(axiom, self, self._world)
         else:
diff --git a/owlapy/owl_reasoner.py b/owlapy/owl_reasoner.py
index 5dd6998b..211460d9 100644
--- a/owlapy/owl_reasoner.py
+++ b/owlapy/owl_reasoner.py
@@ -17,7 +17,7 @@
 from owlapy.class_expression import OWLClass
 from owlapy.iri import IRI
 from owlapy.owl_axiom import OWLAxiom, OWLSubClassOfAxiom
-from owlapy.owl_data_ranges import OWLDataRange, OWLDataComplementOf, OWLDataUnionOf, OWLDataIntersectionOf
+from owlapy.owl_data_ranges import OWLDataComplementOf, OWLDataUnionOf, OWLDataIntersectionOf
 from owlapy.owl_datatype import OWLDatatype
 from owlapy.owl_object import OWLEntity
 from owlapy.owl_ontology import Ontology, _parse_concept_to_owlapy, SyncOntology
@@ -28,29 +28,91 @@
 from owlapy.owl_individual import OWLNamedIndividual
 from owlapy.owl_literal import OWLLiteral
 from owlapy.utils import LRUCache, run_with_timeout
-from owlapy.abstracts.abstract_owl_reasoner import AbstractOWLReasoner, AbstractOWLReasonerEx
+from owlapy.abstracts.abstract_owl_reasoner import AbstractOWLReasoner
 logger = logging.getLogger(__name__)
 
 _P = TypeVar('_P', bound=OWLPropertyExpression)
 
-class OntologyReasoner(AbstractOWLReasonerEx):
-    __slots__ = '_ontology', '_world'
-    # TODO: CD: We will remove owlready2 from owlapy
+
+class StructuralReasoner(AbstractOWLReasoner):
+    """Tries to check instances fast (but maybe incomplete)."""
+    __slots__ = '_ontology', '_world', \
+                '_ind_set', '_cls_to_ind', \
+                '_has_prop', 'class_cache', \
+                '_objectsomevalues_cache', '_datasomevalues_cache', '_objectcardinality_cache', \
+                '_property_cache', \
+                '_obj_prop', '_obj_prop_inv', '_data_prop', \
+                '_negation_default', '_sub_properties', \
+                '__warned'
+
     _ontology: Ontology
     _world: owlready2.World
+    _cls_to_ind: Dict[OWLClass, FrozenSet[OWLNamedIndividual]]  # Class => individuals
+    _has_prop: Mapping[Type[_P], LRUCache[_P, FrozenSet[OWLNamedIndividual]]]  # Type => Property => individuals
+    _ind_set: FrozenSet[OWLNamedIndividual]
+    # ObjectSomeValuesFrom => individuals
+    _objectsomevalues_cache: LRUCache[OWLClassExpression, FrozenSet[OWLNamedIndividual]]
+    # DataSomeValuesFrom => individuals
+    _datasomevalues_cache: LRUCache[OWLClassExpression, FrozenSet[OWLNamedIndividual]]
+    # ObjectCardinalityRestriction => individuals
+    _objectcardinality_cache: LRUCache[OWLClassExpression, FrozenSet[OWLNamedIndividual]]
+    # ObjectProperty => { individual => individuals }
+    _obj_prop: Dict[OWLObjectProperty, Mapping[OWLNamedIndividual, Set[OWLNamedIndividual]]]
+    # ObjectProperty => { individual => individuals }
+    _obj_prop_inv: Dict[OWLObjectProperty, Mapping[OWLNamedIndividual, Set[OWLNamedIndividual]]]
+    # DataProperty => { individual => literals }
+    _data_prop: Dict[OWLDataProperty, Mapping[OWLNamedIndividual, Set[OWLLiteral]]]
+    class_cache: bool
+    _property_cache: bool
+    _negation_default: bool
+    _sub_properties: bool
 
-    def __init__(self, ontology: Ontology):
-        """
-        Base reasoner in Ontolearn, used to reason in the given ontology.
+    def __init__(self, ontology: AbstractOWLOntology, *, class_cache: bool = True,
+                 property_cache: bool = True, negation_default: bool = True, sub_properties: bool = False):
+        """Fast instance checker.
 
         Args:
-            ontology: The ontology that should be used by the reasoner.
-        """
+            ontology: Ontology to use.
+            property_cache: Whether to cache property values.
+            negation_default: Whether to assume a missing fact means it is false ("closed world view").
+            sub_properties: Whether to take sub properties into account for the
+                :func:`StructuralReasoner.instances` retrieval.
+            """
         super().__init__(ontology)
         assert isinstance(ontology, Ontology)
-        self._isolated = False
-        self._ontology = ontology
         self._world = ontology._world
+        self._ontology = ontology
+        self.class_cache = class_cache
+        self._property_cache = property_cache
+        self._negation_default = negation_default
+        self._sub_properties = sub_properties
+        self.__warned = 0
+        self._init()
+
+    def _init(self, cache_size=128):
+
+        individuals = self._ontology.individuals_in_signature()
+        self._ind_set = frozenset(individuals)
+        self._objectsomevalues_cache = LRUCache(maxsize=cache_size)
+        self._datasomevalues_cache = LRUCache(maxsize=cache_size)
+        self._objectcardinality_cache = LRUCache(maxsize=cache_size)
+        if self.class_cache:
+            self._cls_to_ind = dict()
+
+        if self._property_cache:
+            self._obj_prop = dict()
+            self._obj_prop_inv = dict()
+            self._data_prop = dict()
+        else:
+            self._has_prop = MappingProxyType({
+                OWLDataProperty: LRUCache(maxsize=cache_size),
+                OWLObjectProperty: LRUCache(maxsize=cache_size),
+                OWLObjectInverseOf: LRUCache(maxsize=cache_size),
+            })
+
+    def reset(self):
+        """The reset method shall reset any cached state."""
+        self._init()
 
     def data_property_domains(self, pe: OWLDataProperty, direct: bool = False) -> Iterable[OWLClassExpression]:
         domains = {d.get_domain() for d in self.get_root_ontology().data_property_domain_axioms(pe)}
@@ -198,31 +260,11 @@ def object_property_values(self, ind: OWLNamedIndividual, pe: OWLObjectPropertyE
 
     def _instances(self, ce: OWLClassExpression, direct: bool = False) -> Iterable[OWLNamedIndividual]:
         if direct:
-            if isinstance(ce, OWLClass):
-                c_x: owlready2.ThingClass = self._world[ce.str]
-                for i in self._ontology._onto.get_instances_of(c_x):
-                    if isinstance(i, owlready2.Thing):
-                        yield OWLNamedIndividual(IRI.create(i.iri))
-            else:
-                raise NotImplementedError("instances for complex class expressions not implemented", ce)
-        else:
-            if ce.is_owl_thing():
-                yield from self._ontology.individuals_in_signature()
-            elif isinstance(ce, OWLClass):
-                c_x: owlready2.ThingClass = self._world[ce.str]
-                for i in c_x.instances(world=self._world):
-                    if isinstance(i, owlready2.Thing):
-                        yield OWLNamedIndividual(IRI.create(i.iri))
-            # elif isinstance(ce, OWLObjectSomeValuesFrom) and ce.get_filler().is_owl_thing()\
-            #         and isinstance(ce.get_property(), OWLProperty):
-            #     seen_set = set()
-            #     p_x: owlready2.ObjectProperty = self._world[ce.get_property().get_named_property().str]
-            #     for i, _ in p_x.get_relations():
-            #         if isinstance(i, owlready2.Thing) and i not in seen_set:
-            #             seen_set.add(i)
-            #             yield OWLNamedIndividual(IRI.create(i.iri))
-            else:
-                raise NotImplementedError("instances for complex class expressions not implemented", ce)
+            if not self.__warned & 2:
+                logger.warning("direct not implemented")
+                self.__warned |= 2
+        temp = self._find_instances(ce)
+        yield from temp
 
     def instances(self, ce: OWLClassExpression, direct: bool = False, timeout: int = 1000):
         return run_with_timeout(self._instances, timeout, (ce, direct))
@@ -556,188 +598,6 @@ def types(self, ind: OWLNamedIndividual, direct: bool = False) -> Iterable[OWLCl
                     yield OWLClass(IRI.create(c.iri))
                 # Anonymous classes are ignored
 
-    # Deprecated
-    # def _sync_reasoner(self, other_reasoner: BaseReasoner = None,
-    #                    infer_property_values: bool = True,
-    #                    infer_data_property_values: bool = True, debug: bool = False) -> None:
-    #     """Call Owlready2's sync_reasoner method, which spawns a Java process on a temp file to infer more.
-    #
-    #     Args:
-    #         other_reasoner: Set to BaseReasoner.PELLET (default) or BaseReasoner.HERMIT.
-    #         infer_property_values: Whether to infer property values.
-    #         infer_data_property_values: Whether to infer data property values (only for PELLET).
-    #     """
-    #     assert other_reasoner is None or isinstance(other_reasoner, BaseReasoner)
-    #     with self.get_root_ontology()._onto:
-    #         if other_reasoner == BaseReasoner.HERMIT:
-    #             owlready2.sync_reasoner_hermit(self._world, infer_property_values=infer_property_values, debug=debug)
-    #         else:
-    #             owlready2.sync_reasoner_pellet(self._world,
-    #                                            infer_property_values=infer_property_values,
-    #                                            infer_data_property_values=infer_data_property_values,
-    #                                            debug=debug)
-
-    def get_root_ontology(self) -> AbstractOWLOntology:
-        return self._ontology
-
-
-class FastInstanceCheckerReasoner(AbstractOWLReasonerEx):
-    """Tries to check instances fast (but maybe incomplete)."""
-    __slots__ = '_ontology', '_base_reasoner', \
-                '_ind_set', '_cls_to_ind', \
-                '_has_prop', \
-                '_objectsomevalues_cache', '_datasomevalues_cache', '_objectcardinality_cache', \
-                '_property_cache', \
-                '_obj_prop', '_obj_prop_inv', '_data_prop', \
-                '_negation_default', \
-                '__warned'
-
-    _ontology: AbstractOWLOntology
-    _base_reasoner: AbstractOWLReasoner
-    _cls_to_ind: Dict[OWLClass, FrozenSet[OWLNamedIndividual]]  # Class => individuals
-    _has_prop: Mapping[Type[_P], LRUCache[_P, FrozenSet[OWLNamedIndividual]]]  # Type => Property => individuals
-    _ind_set: FrozenSet[OWLNamedIndividual]
-    # ObjectSomeValuesFrom => individuals
-    _objectsomevalues_cache: LRUCache[OWLClassExpression, FrozenSet[OWLNamedIndividual]]
-    # DataSomeValuesFrom => individuals
-    _datasomevalues_cache: LRUCache[OWLClassExpression, FrozenSet[OWLNamedIndividual]]
-    # ObjectCardinalityRestriction => individuals
-    _objectcardinality_cache: LRUCache[OWLClassExpression, FrozenSet[OWLNamedIndividual]]
-    # ObjectProperty => { individual => individuals }
-    _obj_prop: Dict[OWLObjectProperty, Mapping[OWLNamedIndividual, Set[OWLNamedIndividual]]]
-    # ObjectProperty => { individual => individuals }
-    _obj_prop_inv: Dict[OWLObjectProperty, Mapping[OWLNamedIndividual, Set[OWLNamedIndividual]]]
-    # DataProperty => { individual => literals }
-    _data_prop: Dict[OWLDataProperty, Mapping[OWLNamedIndividual, Set[OWLLiteral]]]
-    _property_cache: bool
-    _negation_default: bool
-    _sub_properties: bool
-
-    def __init__(self, ontology: AbstractOWLOntology, base_reasoner: AbstractOWLReasoner, *,
-                 property_cache: bool = True, negation_default: bool = True, sub_properties: bool = False):
-        """Fast instance checker.
-
-        Args:
-            ontology: Ontology to use.
-            base_reasoner: Reasoner to get instances/types from.
-            property_cache: Whether to cache property values.
-            negation_default: Whether to assume a missing fact means it is false ("closed world view").
-            sub_properties: Whether to take sub properties into account for the
-                :func:`OWLReasoner_FastInstanceChecker.instances` retrieval.
-            """
-        super().__init__(ontology)
-        self._ontology = ontology
-        self._base_reasoner = base_reasoner
-        self._property_cache = property_cache
-        self._negation_default = negation_default
-        self._sub_properties = sub_properties
-        self.__warned = 0
-        self._init()
-
-    def _init(self, cache_size=128):
-        self._cls_to_ind = dict()
-        individuals = self._ontology.individuals_in_signature()
-        self._ind_set = frozenset(individuals)
-        self._objectsomevalues_cache = LRUCache(maxsize=cache_size)
-        self._datasomevalues_cache = LRUCache(maxsize=cache_size)
-        self._objectcardinality_cache = LRUCache(maxsize=cache_size)
-        if self._property_cache:
-            self._obj_prop = dict()
-            self._obj_prop_inv = dict()
-            self._data_prop = dict()
-        else:
-            self._has_prop = MappingProxyType({
-                OWLDataProperty: LRUCache(maxsize=cache_size),
-                OWLObjectProperty: LRUCache(maxsize=cache_size),
-                OWLObjectInverseOf: LRUCache(maxsize=cache_size),
-            })
-
-    def reset(self):
-        """The reset method shall reset any cached state."""
-        self._init()
-
-    def data_property_domains(self, pe: OWLDataProperty, direct: bool = False) -> Iterable[OWLClassExpression]:
-        yield from self._base_reasoner.data_property_domains(pe, direct=direct)
-
-    def data_property_ranges(self, pe: OWLDataProperty, direct: bool = False) -> Iterable[OWLDataRange]:
-        yield from self._base_reasoner.data_property_ranges(pe, direct=direct)
-
-    def object_property_domains(self, pe: OWLObjectProperty, direct: bool = False) -> Iterable[OWLClassExpression]:
-        yield from self._base_reasoner.object_property_domains(pe, direct=direct)
-
-    def object_property_ranges(self, pe: OWLObjectProperty, direct: bool = False) -> Iterable[OWLClassExpression]:
-        yield from self._base_reasoner.object_property_ranges(pe, direct=direct)
-
-    def equivalent_classes(self, ce: OWLClassExpression, only_named: bool = True) -> Iterable[OWLClassExpression]:
-        yield from self._base_reasoner.equivalent_classes(ce, only_named=only_named)
-
-    def disjoint_classes(self, ce: OWLClassExpression, only_named: bool = True) -> Iterable[OWLClassExpression]:
-        yield from self._base_reasoner.disjoint_classes(ce, only_named=only_named)
-
-    def different_individuals(self, ce: OWLNamedIndividual) -> Iterable[OWLNamedIndividual]:
-        yield from self._base_reasoner.different_individuals(ce)
-
-    def same_individuals(self, ce: OWLNamedIndividual) -> Iterable[OWLNamedIndividual]:
-        yield from self._base_reasoner.same_individuals(ce)
-
-    def data_property_values(self, e: OWLEntity, pe: OWLDataProperty, direct: bool = True) \
-            -> Iterable[OWLLiteral]:
-        yield from self._base_reasoner.data_property_values(e, pe, direct)
-
-    def all_data_property_values(self, pe: OWLDataProperty, direct: bool = True) -> Iterable[OWLLiteral]:
-        yield from self._base_reasoner.all_data_property_values(pe, direct)
-
-    def object_property_values(self, ind: OWLNamedIndividual, pe: OWLObjectPropertyExpression, direct: bool = True) \
-            -> Iterable[OWLNamedIndividual]:
-        yield from self._base_reasoner.object_property_values(ind, pe, direct)
-
-    def _instances(self, ce: OWLClassExpression, direct: bool = False) -> Iterable[OWLNamedIndividual]:
-        if direct:
-            if not self.__warned & 2:
-                logger.warning("direct not implemented")
-                self.__warned |= 2
-        temp = self._find_instances(ce)
-        yield from temp
-
-    def instances(self, ce: OWLClassExpression, direct: bool = False, timeout: int = 1000):
-        return run_with_timeout(self._instances, timeout, (ce, direct))
-
-    def sub_classes(self, ce: OWLClassExpression, direct: bool = False, only_named: bool = True) \
-            -> Iterable[OWLClassExpression]:
-        yield from self._base_reasoner.sub_classes(ce, direct=direct, only_named=only_named)
-
-    def super_classes(self, ce: OWLClassExpression, direct: bool = False, only_named: bool = True) \
-            -> Iterable[OWLClassExpression]:
-        yield from self._base_reasoner.super_classes(ce, direct=direct, only_named=only_named)
-
-    def types(self, ind: OWLNamedIndividual, direct: bool = False) -> Iterable[OWLClass]:
-        yield from self._base_reasoner.types(ind, direct=direct)
-
-    def equivalent_object_properties(self, dp: OWLObjectPropertyExpression) -> Iterable[OWLObjectPropertyExpression]:
-        yield from self._base_reasoner.equivalent_object_properties(dp)
-
-    def equivalent_data_properties(self, dp: OWLDataProperty) -> Iterable[OWLDataProperty]:
-        yield from self._base_reasoner.equivalent_data_properties(dp)
-
-    def disjoint_object_properties(self, dp: OWLObjectPropertyExpression) -> Iterable[OWLObjectPropertyExpression]:
-        yield from self._base_reasoner.disjoint_object_properties(dp)
-
-    def disjoint_data_properties(self, dp: OWLDataProperty) -> Iterable[OWLDataProperty]:
-        yield from self._base_reasoner.disjoint_data_properties(dp)
-
-    def sub_data_properties(self, dp: OWLDataProperty, direct: bool = False) -> Iterable[OWLDataProperty]:
-        yield from self._base_reasoner.sub_data_properties(dp=dp, direct=direct)
-
-    def super_data_properties(self, dp: OWLDataProperty, direct: bool = False) -> Iterable[OWLDataProperty]:
-        yield from self._base_reasoner.super_data_properties(dp=dp, direct=direct)
-
-    def super_object_properties(self, op: OWLObjectProperty, direct: bool = False) -> Iterable[OWLDataProperty]:
-        yield from self._base_reasoner.super_object_properties(op=op, direct=direct)
-
-    def sub_object_properties(self, op: OWLObjectPropertyExpression, direct: bool = False) \
-            -> Iterable[OWLObjectPropertyExpression]:
-        yield from self._base_reasoner.sub_object_properties(op=op, direct=direct)
-
     def get_root_ontology(self) -> AbstractOWLOntology:
         return self._ontology
 
@@ -777,7 +637,7 @@ def _lazy_cache_obj_prop(self, pe: OWLObjectPropertyExpression) -> None:
                     opc[s] |= {o}
         else:
             for s in self._ind_set:
-                individuals = set(self._base_reasoner.object_property_values(s, pe, not self._sub_properties))
+                individuals = set(self.object_property_values(s, pe, not self._sub_properties))
                 if individuals:
                     opc[s] = individuals
 
@@ -813,9 +673,9 @@ def _some_values_subject_index(self, pe: OWLPropertyExpression) -> FrozenSet[OWL
                         subs |= {OWLNamedIndividual(IRI.create(l_x.iri))}
             else:
                 if isinstance(pe, OWLDataProperty):
-                    func = self._base_reasoner.data_property_values
+                    func = self.data_property_values
                 else:
-                    func = self._base_reasoner.object_property_values
+                    func = self.object_property_values
 
                 for s in self._ind_set:
                     try:
@@ -832,7 +692,8 @@ def _find_some_values(self, pe: OWLObjectPropertyExpression, filler_inds: Set[OW
                           min_count: int = 1, max_count: Optional[int] = None) -> FrozenSet[OWLNamedIndividual]:
         """Get all individuals that have one of filler_inds as their object property value."""
         ret = set()
-
+        if self._ontology.is_modified and (self.class_cache or self._property_cache):
+            self.reset_and_disable_cache()
         if self._property_cache:
             self._lazy_cache_obj_prop(pe)
 
@@ -858,7 +719,7 @@ def _find_some_values(self, pe: OWLObjectPropertyExpression, filler_inds: Set[OW
 
             for s in subs:
                 count = 0
-                for o in self._base_reasoner.object_property_values(s, pe, not self._sub_properties):
+                for o in self.object_property_values(s, pe, not self._sub_properties):
                     if {o} & filler_inds:
                         count = count + 1
                         if max_count is None and count >= min_count:
@@ -890,7 +751,7 @@ def _lazy_cache_data_prop(self, pe: OWLDataPropertyExpression) -> None:
                     opc[s].add(o_literal)
         else:
             for s in self._ind_set:
-                values = set(self._base_reasoner.data_property_values(s, pe))
+                values = set(self.data_property_values(s, pe))
                 if len(values) > 0:
                     opc[s] = values
 
@@ -903,8 +764,13 @@ def _find_instances(self, ce: OWLClassExpression) -> FrozenSet[OWLNamedIndividua
 
     @_find_instances.register
     def _(self, c: OWLClass) -> FrozenSet[OWLNamedIndividual]:
-        self._lazy_cache_class(c)
-        return self._cls_to_ind[c]
+        if self._ontology.is_modified and (self.class_cache or self._property_cache):
+            self.reset_and_disable_cache()
+        if self.class_cache:
+            self._lazy_cache_class(c)
+            return self._cls_to_ind[c]
+        else:
+            return frozenset(self.get_instances_from_owl_class(c))
 
     @_find_instances.register
     def _(self, ce: OWLObjectUnionOf) -> FrozenSet[OWLNamedIndividual]:
@@ -1016,8 +882,9 @@ def _(self, ce: OWLDataSomeValuesFrom) -> FrozenSet[OWLNamedIndividual]:
         pe = ce.get_property()
         filler = ce.get_filler()
         assert isinstance(pe, OWLDataProperty)
-        #
 
+        if self._ontology.is_modified and (self.class_cache or self._property_cache):
+            self.reset_and_disable_cache()
         property_cache = self._property_cache
 
         if property_cache:
@@ -1035,7 +902,7 @@ def _(self, ce: OWLDataSomeValuesFrom) -> FrozenSet[OWLNamedIndividual]:
                     ind |= {s}
             else:
                 for s in subs:
-                    for lit in self._base_reasoner.data_property_values(s, pe):
+                    for lit in self.data_property_values(s, pe):
                         if lit.get_datatype() == filler:
                             ind |= {s}
                             break
@@ -1047,7 +914,7 @@ def _(self, ce: OWLDataSomeValuesFrom) -> FrozenSet[OWLNamedIndividual]:
                         ind |= {s}
             else:
                 for s in subs:
-                    for lit in self._base_reasoner.data_property_values(s, pe):
+                    for lit in self.data_property_values(s, pe):
                         if lit in values:
                             ind |= {s}
                             break
@@ -1092,7 +959,7 @@ def include(lv: OWLLiteral):
                             break
             else:
                 for s in subs:
-                    for lit in self._base_reasoner.data_property_values(s, pe):
+                    for lit in self.data_property_values(s, pe):
                         if include(lit):
                             ind |= {s}
                             break
@@ -1123,9 +990,18 @@ def _(self, ce: OWLDataHasValue) -> FrozenSet[OWLNamedIndividual]:
     def _lazy_cache_class(self, c: OWLClass) -> None:
         if c in self._cls_to_ind:
             return
-        temp = self._base_reasoner.instances(c)
+        temp = self.get_instances_from_owl_class(c)
         self._cls_to_ind[c] = frozenset(temp)
 
+    def get_instances_from_owl_class(self, c: OWLClass):
+        if c.is_owl_thing():
+            yield from self._ontology.individuals_in_signature()
+        elif isinstance(c, OWLClass):
+            c_x: owlready2.ThingClass = self._world[c.str]
+            for i in c_x.instances(world=self._world):
+                if isinstance(i, owlready2.Thing):
+                    yield OWLNamedIndividual(IRI.create(i.iri))
+
     def _retrieve_triples(self, pe: OWLPropertyExpression) -> Iterable:
         """Retrieve all subject/object pairs for the given property."""
 
@@ -1148,8 +1024,13 @@ def _retrieve_triples(self, pe: OWLPropertyExpression) -> Iterable:
             relations = chain(relations, indirect_relations)
         yield from relations
 
+    def reset_and_disable_cache(self):
+        self.class_cache = False
+        self._property_cache = False
+        self.reset()
+
 
-class SyncReasoner(AbstractOWLReasonerEx):
+class SyncReasoner(AbstractOWLReasoner):
 
     def __init__(self, ontology: Union[SyncOntology, str], reasoner="HermiT"):
         """
diff --git a/owlapy/parser.py b/owlapy/parser.py
index 06bbcc9c..58a5b5e1 100644
--- a/owlapy/parser.py
+++ b/owlapy/parser.py
@@ -55,7 +55,7 @@
     data_union = data_intersection (must_ws "or" must_ws data_intersection)*
     data_intersection = data_primary (must_ws "and" must_ws data_primary)*
     datatype_restriction = datatype_iri "[" maybe_ws facet_restrictions maybe_ws "]"
-    facet_restrictions = facet_restriction (maybe_ws "," maybe_ws facet_restriction)*
+    facet_restrictions = facet_restriction (maybe_ws "⊓" maybe_ws facet_restriction)*
     facet_restriction = facet must_ws literal
     facet = "length" / "minLength" / "maxLength" / "pattern" / "langRange"
             / "totalDigits" / "fractionDigits" / "<=" / ">=" / "<" / ">"
@@ -454,7 +454,7 @@ def generic_visit(self, node, children):
     data_union = data_intersection (must_ws "⊔" must_ws data_intersection)*
     data_intersection = data_primary (must_ws "⊓" must_ws data_primary)*
     datatype_restriction = datatype_iri "[" maybe_ws facet_restrictions maybe_ws "]"
-    facet_restrictions = facet_restriction (maybe_ws "," maybe_ws facet_restriction)*
+    facet_restrictions = facet_restriction (maybe_ws "⊓" maybe_ws facet_restriction)*
     facet_restriction = facet must_ws literal
     facet = "length" / "minLength" / "maxLength" / "pattern" / "langRange"
             / "totalDigits" / "fractionDigits" / "≥" / "≤" / "<" / ">"
diff --git a/owlapy/render.py b/owlapy/render.py
index dd71dc03..9856c5b7 100644
--- a/owlapy/render.py
+++ b/owlapy/render.py
@@ -246,7 +246,7 @@ def _(self, r: OWLObjectHasValue):
 
     @render.register
     def _(self, r: OWLObjectOneOf):
-        return "{%s}" % (" %s " % _DL_SYNTAX.COMMA).join(
+        return "{%s}" % (" %s " % _DL_SYNTAX.OR).join(
             "%s" % (self.render(_)) for _ in r.individuals())
 
     @render.register
@@ -269,7 +269,7 @@ def _(self, r: OWLFacetRestriction) -> str:
     @render.register
     def _(self, r: OWLDatatypeRestriction) -> str:
         s = [self.render(_) for _ in r.get_facet_restrictions()]
-        return "%s[%s]" % (self.render(r.get_datatype()), (" %s " % _DL_SYNTAX.COMMA).join(s))
+        return "%s[%s]" % (self.render(r.get_datatype()), (" %s " % _DL_SYNTAX.AND).join(s))
 
     @render.register
     def _(self, r: OWLDataHasValue):
@@ -463,7 +463,7 @@ def _(self, r: OWLFacetRestriction):
     @render.register
     def _(self, r: OWLDatatypeRestriction):
         s = [self.render(_) for _ in r.get_facet_restrictions()]
-        return "%s[%s]" % (self.render(r.get_datatype()), (" %s " % _MAN_SYNTAX.COMMA).join(s))
+        return "%s[%s]" % (self.render(r.get_datatype()), (" %s " % _MAN_SYNTAX.AND).join(s))
 
     @render.register
     def _(self, r: OWLDataHasValue):
diff --git a/setup.py b/setup.py
index 14e869cc..bf8d39f5 100644
--- a/setup.py
+++ b/setup.py
@@ -5,7 +5,7 @@
 setup(
     name="owlapy",
     description="OWLAPY is a Python Framework for creating and manipulating OWL Ontologies.",
-    version="1.3.1",
+    version="1.3.2",
     packages=find_packages(),
     include_package_data=True,
     package_data={'owlapy': ['jar_dependencies/*.jar'],},


Test patch:
diff --git a/tests/test_owlapy_cnf_dnf.py b/tests/test_owlapy_cnf_dnf
similarity index 100%
rename from tests/test_owlapy_cnf_dnf.py
rename to tests/test_owlapy_cnf_dnf
diff --git a/tests/test_owlapy_parser.py b/tests/test_owlapy_conversions.py
similarity index 65%
rename from tests/test_owlapy_parser.py
rename to tests/test_owlapy_conversions.py
index 5b217282..dae7373b 100644
--- a/tests/test_owlapy_parser.py
+++ b/tests/test_owlapy_conversions.py
@@ -1,28 +1,141 @@
-import unittest
 from datetime import date, datetime, timedelta, timezone
+import unittest
 
 from pandas import Timedelta
-
 from owlapy.iri import IRI
+from owlapy.owl_property import OWLObjectProperty, OWLDataProperty
 from owlapy.owl_individual import OWLNamedIndividual
-from owlapy.owl_literal import DoubleOWLDatatype, IntegerOWLDatatype, OWLLiteral
-from owlapy.owl_property import OWLObjectInverseOf, OWLObjectProperty, OWLDataProperty
+from owlapy.parser import DLSyntaxParser, ManchesterOWLSyntaxParser
+from owlapy.render import DLSyntaxObjectRenderer, ManchesterOWLSyntaxOWLObjectRenderer
+from owlapy.class_expression import OWLClass, OWLNothing,OWLObjectHasValue, OWLObjectSomeValuesFrom, OWLObjectOneOf, OWLObjectAllValuesFrom
 
-from owlapy.class_expression import OWLObjectUnionOf, OWLClass, \
-    OWLDataOneOf, OWLObjectAllValuesFrom, OWLObjectComplementOf, OWLObjectExactCardinality, \
-    OWLObjectHasSelf, OWLObjectIntersectionOf, OWLObjectMaxCardinality, OWLDataExactCardinality, \
-    OWLDataMinCardinality, OWLDataHasValue, OWLThing, OWLNothing, OWLObjectSomeValuesFrom, OWLObjectMinCardinality, \
-    OWLObjectHasValue, OWLObjectOneOf, OWLDataSomeValuesFrom, OWLDataAllValuesFrom, OWLDataMaxCardinality, \
-    OWLDatatypeRestriction, OWLFacetRestriction
+from owlapy.owl_literal import DoubleOWLDatatype, IntegerOWLDatatype, OWLLiteral, BooleanOWLDatatype
+from owlapy.class_expression import OWLDataMinCardinality, OWLObjectIntersectionOf, OWLThing, OWLObjectComplementOf, OWLObjectUnionOf, OWLObjectMinCardinality, OWLDataExactCardinality, OWLDataHasValue, OWLDataAllValuesFrom, \
+    OWLDataOneOf, OWLDataSomeValuesFrom, \
+    OWLDataMaxCardinality, OWLObjectMaxCardinality, OWLObjectExactCardinality, OWLObjectHasSelf, OWLFacetRestriction, OWLDatatypeRestriction
 
-from owlapy.owl_data_ranges import OWLDataIntersectionOf, OWLDataComplementOf, OWLDataUnionOf
-from owlapy.providers import owl_datatype_min_exclusive_restriction,\
-    owl_datatype_min_max_exclusive_restriction, owl_datatype_max_exclusive_restriction
+from owlapy.owl_property import OWLObjectInverseOf
+
+from owlapy.owl_data_ranges import OWLDataComplementOf, OWLDataIntersectionOf, OWLDataUnionOf
+from owlapy.providers import owl_datatype_max_exclusive_restriction, owl_datatype_min_exclusive_restriction, owl_datatype_min_max_exclusive_restriction, owl_datatype_min_max_inclusive_restriction
 
-from owlapy.parser import DLSyntaxParser, ManchesterOWLSyntaxParser
 from owlapy.vocab import OWLFacet
 
 
+class TestOWLConversions(unittest.TestCase):
+    def test_owlapy_to_dl_str_and_back(self):
+        NS = "http://example.com/father#"
+        renderer = DLSyntaxObjectRenderer()
+        parser = DLSyntaxParser(NS)
+        male = OWLClass(IRI.create(NS, 'male'))
+        female = OWLClass(IRI.create(NS, 'female'))
+        has_child = OWLObjectProperty(IRI(NS, 'hasChild'))
+        has_age = OWLDataProperty(IRI(NS, 'hasAge'))
+        # (1)
+        c = OWLObjectUnionOf((male, OWLObjectSomeValuesFrom(property=has_child, filler=female)))
+        rendered_c=renderer.render(c)
+        self.assertEqual(c, parser.parse_expression(rendered_c))
+        self.assertEqual(rendered_c, "male ⊔ (∃ hasChild.female)")
+        # (2)
+        c = OWLObjectComplementOf(OWLObjectIntersectionOf((female,
+                                                           OWLObjectSomeValuesFrom(property=has_child,
+                                                                                   filler=OWLThing))))
+        rendered_c = renderer.render(c)
+        self.assertEqual(c, parser.parse_expression(rendered_c))
+        self.assertEqual(rendered_c, "¬(female ⊓ (∃ hasChild.⊤))")
+        # (3)
+        c = OWLObjectSomeValuesFrom(property=has_child,
+                                    filler=OWLObjectSomeValuesFrom(property=has_child,
+                                                                   filler=OWLObjectSomeValuesFrom(property=has_child,
+                                                                                                  filler=OWLThing)))
+        rendered_c = renderer.render(c)
+        self.assertEqual(c, parser.parse_expression(rendered_c))
+        self.assertEqual(rendered_c, "∃ hasChild.(∃ hasChild.(∃ hasChild.⊤))")
+        # (4)
+        i1 = OWLNamedIndividual(IRI.create(NS, 'heinz'))
+        i2 = OWLNamedIndividual(IRI.create(NS, 'marie'))
+        c = OWLObjectOneOf({i1, i2})
+        rendered_c = renderer.render(c)
+        self.assertEqual(c, parser.parse_expression(rendered_c))
+        assert rendered_c== "{heinz ⊔ marie}" or rendered_c=="{marie ⊔ heinz}"
+        # (5)
+        c = OWLObjectHasValue(property=has_child, individual=i1)
+        rendered_c = renderer.render(c)
+        self.assertEqual(c, parser.parse_expression(rendered_c))
+        self.assertEqual(rendered_c, "∃ hasChild.{heinz}")
+        # (6)
+        c = OWLObjectMinCardinality(cardinality=2, property=has_child, filler=OWLThing)
+        rendered_c = renderer.render(c)
+        self.assertEqual(c, parser.parse_expression(rendered_c))
+        self.assertEqual(rendered_c, "≥ 2 hasChild.⊤")
+        # (7)
+        c = OWLDataSomeValuesFrom(property=has_age, filler=OWLDataComplementOf(DoubleOWLDatatype))
+        rendered_c = renderer.render(c)
+        self.assertEqual(c, parser.parse_expression(rendered_c))
+        self.assertEqual(rendered_c, "∃ hasAge.¬xsd:double")
+        # (8)
+        c = OWLDataAllValuesFrom(property=has_age, filler=OWLDataUnionOf([owl_datatype_min_max_inclusive_restriction(40, 80), IntegerOWLDatatype]))
+        rendered_c = renderer.render(c)
+        self.assertEqual(c, parser.parse_expression(rendered_c))
+        self.assertEqual(rendered_c, "∀ hasAge.(xsd:integer[≥ 40 ⊓ ≤ 80] ⊔ xsd:integer)")
+        # (9)
+        c = OWLDataSomeValuesFrom(property=has_age,
+                                   filler=OWLDataIntersectionOf([OWLDataOneOf([OWLLiteral(32.5), OWLLiteral(4.5)]),
+                                                                 IntegerOWLDatatype]))
+        rendered_c = renderer.render(c)
+        self.assertEqual(c, parser.parse_expression(rendered_c))
+        self.assertEqual(rendered_c, "∃ hasAge.({32.5 ⊔ 4.5} ⊓ xsd:integer)")
+        # (10)
+        c = OWLDataHasValue(property=has_age, value=OWLLiteral(50))
+        rendered_c = renderer.render(c)
+        self.assertEqual(c, parser.parse_expression(rendered_c))
+        self.assertEqual(rendered_c, "∃ hasAge.{50}")
+        # (11)
+        c = OWLDataExactCardinality(cardinality=1, property=has_age, filler=IntegerOWLDatatype)
+        rendered_c = renderer.render(c)
+        self.assertEqual(c, parser.parse_expression(rendered_c))
+        self.assertEqual(rendered_c, "= 1 hasAge.xsd:integer")
+        # (12)
+        c = OWLDataMaxCardinality(cardinality=4, property=has_age, filler=DoubleOWLDatatype)
+        rendered_c = renderer.render(c)
+        self.assertEqual(c, parser.parse_expression(rendered_c))
+        self.assertEqual(rendered_c, "≤ 4 hasAge.xsd:double")
+        # (13)
+        c = OWLDataMinCardinality(cardinality=7, property=has_age, filler=BooleanOWLDatatype)
+        rendered_c = renderer.render(c)
+        self.assertEqual(c, parser.parse_expression(rendered_c))
+        self.assertEqual(rendered_c, "≥ 7 hasAge.xsd:boolean")
+
+        # (14)
+        c = OWLObjectHasValue(property=has_child,
+                              individual=OWLNamedIndividual(IRI.create(NS, 'A')))
+        rendered_c=renderer.render(c)
+        self.assertEqual(c, parser.parse_expression(rendered_c))
+        self.assertEqual(rendered_c, "∃ hasChild.{A}")
+
+        # (15)
+        c = OWLObjectSomeValuesFrom(property=has_child, filler=OWLObjectOneOf([
+            OWLNamedIndividual(IRI.create(NS, 'A')),
+            OWLNamedIndividual(IRI.create(NS, 'B'))]))
+        renderer_c = renderer.render(c)
+        assert renderer_c=="∃ hasChild.{A ⊔ B}" or renderer_c== "∃ hasChild.{B ⊔ A}"
+        self.assertEqual(c, parser.parse_expression(renderer_c))
+        # (16)
+        c = OWLObjectAllValuesFrom(property=has_child, filler=OWLObjectOneOf([
+            OWLNamedIndividual(IRI.create(NS, 'A')),
+            OWLNamedIndividual(IRI.create(NS, 'B'))]))
+        renderer_c = renderer.render(c)
+        assert renderer_c=="∀ hasChild.{A ⊔ B}" or renderer_c=="∀ hasChild.{B ⊔ A}"
+        self.assertEqual(c, parser.parse_expression(renderer_c))
+
+    def test_owlapy_to_manchester_str_and_back(self):
+        # TODO
+        pass
+
+
+
+
+# parser tests
 class ManchesterOWLSyntaxParserTest(unittest.TestCase):
 
     def setUp(self):
@@ -135,7 +248,7 @@ def test_data_properties_numeric(self):
         self.assertEqual(p, c)
 
         p = self.parser.parse_expression('charge some <http://www.w3.org/2001/XMLSchema#double>'
-                                         '[> "4.4"^^xsd:double, < -32.5]')
+                                         '[> "4.4"^^xsd:double ⊓ < -32.5]')
         c = OWLDataSomeValuesFrom(self.charge, owl_datatype_min_max_exclusive_restriction(4.4, -32.5))
         self.assertEqual(p, c)
 
@@ -152,7 +265,7 @@ def test_data_properties_numeric(self):
         c = OWLDataMinCardinality(25, self.charge, filler)
         self.assertEqual(p, c)
 
-        p = self.parser.parse_expression('act exactly 11 xsd:integer[totalDigits "5"^^xsd:integer, > -100]')
+        p = self.parser.parse_expression('act exactly 11 xsd:integer[totalDigits "5"^^xsd:integer ⊓ > -100]')
         filler = OWLDatatypeRestriction(IntegerOWLDatatype, (OWLFacetRestriction(OWLFacet.TOTAL_DIGITS, 5),
                                                              OWLFacetRestriction(OWLFacet.MIN_EXCLUSIVE, -100)))
         c = OWLDataExactCardinality(11, self.act, filler)
@@ -192,14 +305,14 @@ def test_data_properties_string(self):
 
     def test_data_properties_time(self):
         p = self.parser.parse_expression('charge some <http://www.w3.org/2001/XMLSchema#date>'
-                                         '[> 2012-10-09, < "1990-01-31"^^xsd:date]')
+                                         '[> 2012-10-09 ⊓ < "1990-01-31"^^xsd:date]')
         filler = owl_datatype_min_max_exclusive_restriction(date(year=2012, month=10, day=9),
                                                             date(year=1990, month=1, day=31))
         c = OWLDataSomeValuesFrom(self.charge, filler)
         self.assertEqual(p, c)
 
         p = self.parser.parse_expression('charge exactly 10 dateTime'
-                                         '[> 2012-12-31T23:59:59Z, < 2000-01-01 01:01:01.999999]')
+                                         '[> 2012-12-31T23:59:59Z ⊓ < 2000-01-01 01:01:01.999999]')
         filler = owl_datatype_min_max_exclusive_restriction(datetime(year=2012, month=12, day=31, hour=23,
                                                                      minute=59, second=59, tzinfo=timezone.utc),
                                                             datetime(year=2000, month=1, day=1, hour=1, minute=1,
@@ -214,7 +327,7 @@ def test_data_properties_time(self):
         self.assertEqual(p, c)
 
         p = self.parser.parse_expression('charge only <http://www.w3.org/2001/XMLSchema#duration>'
-                                         '[> P10W20DT8H12M10S, < "P10M10.999999S"^^xsd:duration]')
+                                         '[> P10W20DT8H12M10S ⊓ < "P10M10.999999S"^^xsd:duration]')
         filler = owl_datatype_min_max_exclusive_restriction(Timedelta(weeks=10, days=20, hours=8, minutes=12, seconds=10),
                                                             Timedelta(minutes=10, seconds=10, microseconds=999999))
         c = OWLDataAllValuesFrom(self.charge, filler)
@@ -274,7 +387,7 @@ def test_whitespace(self):
         c = OWLDataAllValuesFrom(self.act, OWLDataOneOf((OWLLiteral(1.2), OWLLiteral(3.2))))
         self.assertEqual(p, c)
 
-        p = self.parser.parse_expression('act some (  xsd:double[  > 5f,< 4.2f \n, <  -1.8e10f  ]\t and  integer )')
+        p = self.parser.parse_expression('act some (  xsd:double[  > 5f ⊓ < 4.2f \n ⊓ <  -1.8e10f  ]\t and  integer )')
         f1 = OWLFacetRestriction(OWLFacet.MIN_EXCLUSIVE, OWLLiteral(5.0))
         f2 = OWLFacetRestriction(OWLFacet.MAX_EXCLUSIVE, OWLLiteral(4.2))
         f3 = OWLFacetRestriction(OWLFacet.MAX_EXCLUSIVE, OWLLiteral(-1.8e10))
@@ -395,7 +508,7 @@ def test_data_properties_numeric(self):
         self.assertEqual(p, c)
 
         p = self.parser.parse_expression('∃ charge.<http://www.w3.org/2001/XMLSchema#double>'
-                                         '[> "4.4"^^xsd:double, < -32.5]')
+                                         '[> "4.4"^^xsd:double ⊓ < -32.5]')
         c = OWLDataSomeValuesFrom(self.charge, owl_datatype_min_max_exclusive_restriction(4.4, -32.5))
         self.assertEqual(p, c)
 
@@ -412,7 +525,7 @@ def test_data_properties_numeric(self):
         c = OWLDataMaxCardinality(25, self.charge, filler)
         self.assertEqual(p, c)
 
-        p = self.parser.parse_expression('= 11 act.xsd:integer[totalDigits "5"^^xsd:integer, > -100]')
+        p = self.parser.parse_expression('= 11 act.xsd:integer[totalDigits "5"^^xsd:integer ⊓ > -100]')
         filler = OWLDatatypeRestriction(IntegerOWLDatatype, (OWLFacetRestriction(OWLFacet.TOTAL_DIGITS, 5),
                                                              OWLFacetRestriction(OWLFacet.MIN_EXCLUSIVE, -100)))
         c = OWLDataExactCardinality(11, self.act, filler)
@@ -452,14 +565,14 @@ def test_data_properties_string(self):
 
     def test_data_properties_time(self):
         p = self.parser.parse_expression('∃ charge.<http://www.w3.org/2001/XMLSchema#date>'
-                                         '[> 2012-10-09, < "1990-01-31"^^xsd:date]')
+                                         '[> 2012-10-09 ⊓ < "1990-01-31"^^xsd:date]')
         filler = owl_datatype_min_max_exclusive_restriction(date(year=2012, month=10, day=9),
                                                             date(year=1990, month=1, day=31))
         c = OWLDataSomeValuesFrom(self.charge, filler)
         self.assertEqual(p, c)
 
         p = self.parser.parse_expression('= 10 charge.dateTime'
-                                         '[> 2012-12-31T23:59:59Z, < 2000-01-01 01:01:01.999999]')
+                                         '[> 2012-12-31T23:59:59Z ⊓ < 2000-01-01 01:01:01.999999]')
         filler = owl_datatype_min_max_exclusive_restriction(datetime(year=2012, month=12, day=31, hour=23,
                                                                      minute=59, second=59, tzinfo=timezone.utc),
                                                             datetime(year=2000, month=1, day=1, hour=1, minute=1,
@@ -474,7 +587,7 @@ def test_data_properties_time(self):
         self.assertEqual(p, c)
 
         p = self.parser.parse_expression('∀ charge.<http://www.w3.org/2001/XMLSchema#duration>'
-                                         '[> P10W20DT8H12M10S, < "P10M10.999999S"^^xsd:duration]')
+                                         '[> P10W20DT8H12M10S ⊓ < "P10M10.999999S"^^xsd:duration]')
         filler = owl_datatype_min_max_exclusive_restriction(Timedelta(weeks=10, days=20, hours=8, minutes=12, seconds=10),
                                                             Timedelta(minutes=10, seconds=10, microseconds=999999))
         c = OWLDataAllValuesFrom(self.charge, filler)
@@ -534,10 +647,161 @@ def test_whitespace(self):
         c = OWLDataAllValuesFrom(self.act, OWLDataOneOf((OWLLiteral(1.2), OWLLiteral(3.2))))
         self.assertEqual(p, c)
 
-        p = self.parser.parse_expression('∃ act.(  xsd:double[  > 5f,< 4.2f \n, <  -1.8e10f  ]\t ⊓  integer )')
+        p = self.parser.parse_expression('∃ act.(  xsd:double[  > 5f ⊓ < 4.2f \n ⊓ <  -1.8e10f  ]\t ⊓  integer )')
         f1 = OWLFacetRestriction(OWLFacet.MIN_EXCLUSIVE, OWLLiteral(5.0))
         f2 = OWLFacetRestriction(OWLFacet.MAX_EXCLUSIVE, OWLLiteral(4.2))
         f3 = OWLFacetRestriction(OWLFacet.MAX_EXCLUSIVE, OWLLiteral(-1.8e10))
         c = OWLDataSomeValuesFrom(self.act, OWLDataIntersectionOf(
                                     (OWLDatatypeRestriction(DoubleOWLDatatype, (f1, f2, f3)), IntegerOWLDatatype)))
         self.assertEqual(p, c)
+
+
+
+class Owlapy_DLRenderer_Test(unittest.TestCase):
+    def test_ce_render(self):
+        renderer = DLSyntaxObjectRenderer()
+        NS = "http://example.com/father#"
+
+        male = OWLClass(IRI.create(NS, 'male'))
+        female = OWLClass(IRI.create(NS, 'female'))
+        has_child = OWLObjectProperty(IRI(NS, 'hasChild'))
+        has_age = OWLDataProperty(IRI(NS, 'hasAge'))
+
+        c = OWLObjectUnionOf((male, OWLObjectSomeValuesFrom(property=has_child, filler=female)))
+        r = renderer.render(c)
+        self.assertEqual(r, "male ⊔ (∃ hasChild.female)")
+        c = OWLObjectComplementOf(OWLObjectIntersectionOf((female,
+                                                           OWLObjectSomeValuesFrom(property=has_child,
+                                                                                   filler=OWLThing))))
+        r = renderer.render(c)
+        self.assertEqual(r, "¬(female ⊓ (∃ hasChild.⊤))")
+        c = OWLObjectSomeValuesFrom(property=has_child,
+                                    filler=OWLObjectSomeValuesFrom(property=has_child,
+                                                                   filler=OWLObjectSomeValuesFrom(property=has_child,
+                                                                                                  filler=OWLThing)))
+        r = renderer.render(c)
+        self.assertEqual(r, "∃ hasChild.(∃ hasChild.(∃ hasChild.⊤))")
+
+        i1 = OWLNamedIndividual(IRI.create(NS, 'heinz'))
+        i2 = OWLNamedIndividual(IRI.create(NS, 'marie'))
+        oneof = OWLObjectOneOf((i1, i2))
+        r = renderer.render(oneof)
+        assert r=="{heinz ⊔ marie}" or r=="{marie ⊔ heinz}"
+
+        hasvalue = OWLObjectHasValue(property=has_child, individual=i1)
+        r = renderer.render(hasvalue)
+        self.assertEqual(r, "∃ hasChild.{heinz}")
+
+        mincard = OWLObjectMinCardinality(cardinality=2, property=has_child, filler=OWLThing)
+        r = renderer.render(mincard)
+        self.assertEqual(r, "≥ 2 hasChild.⊤")
+
+        d = OWLDataSomeValuesFrom(property=has_age,
+                                  filler=OWLDataComplementOf(DoubleOWLDatatype))
+        r = renderer.render(d)
+        self.assertEqual(r, "∃ hasAge.¬xsd:double")
+
+        datatype_restriction = owl_datatype_min_max_inclusive_restriction(40, 80)
+
+        dr = OWLDataAllValuesFrom(property=has_age, filler=OWLDataUnionOf([datatype_restriction, IntegerOWLDatatype]))
+        r = renderer.render(dr)
+        self.assertEqual(r, "∀ hasAge.(xsd:integer[≥ 40 ⊓ ≤ 80] ⊔ xsd:integer)")
+
+        dr = OWLDataSomeValuesFrom(property=has_age,
+                                   filler=OWLDataIntersectionOf([OWLDataOneOf([OWLLiteral(32.5), OWLLiteral(4.5)]),
+                                                                 IntegerOWLDatatype]))
+        r = renderer.render(dr)
+        self.assertEqual(r, "∃ hasAge.({32.5 ⊔ 4.5} ⊓ xsd:integer)")
+
+        hasvalue = OWLDataHasValue(property=has_age, value=OWLLiteral(50))
+        r = renderer.render(hasvalue)
+        self.assertEqual(r, "∃ hasAge.{50}")
+
+        exactcard = OWLDataExactCardinality(cardinality=1, property=has_age, filler=IntegerOWLDatatype)
+        r = renderer.render(exactcard)
+        self.assertEqual(r, "= 1 hasAge.xsd:integer")
+
+        maxcard = OWLDataMaxCardinality(cardinality=4, property=has_age, filler=DoubleOWLDatatype)
+        r = renderer.render(maxcard)
+        self.assertEqual(r, "≤ 4 hasAge.xsd:double")
+
+        mincard = OWLDataMinCardinality(cardinality=7, property=has_age, filler=BooleanOWLDatatype)
+        r = renderer.render(mincard)
+        self.assertEqual(r, "≥ 7 hasAge.xsd:boolean")
+
+
+class Owlapy_ManchesterRenderer_Test(unittest.TestCase):
+    def test_ce_render(self):
+        renderer = ManchesterOWLSyntaxOWLObjectRenderer()
+        NS = "http://example.com/father#"
+
+        male = OWLClass(IRI.create(NS, 'male'))
+        female = OWLClass(IRI.create(NS, 'female'))
+        has_child = OWLObjectProperty(IRI(NS, 'hasChild'))
+        has_age = OWLDataProperty(IRI(NS, 'hasAge'))
+
+        c = OWLObjectUnionOf((male, OWLObjectSomeValuesFrom(property=has_child, filler=female)))
+        r = renderer.render(c)
+        self.assertEqual(r, "male or (hasChild some female)")
+        c = OWLObjectComplementOf(OWLObjectIntersectionOf((female,
+                                                           OWLObjectSomeValuesFrom(property=has_child,
+                                                                                   filler=OWLThing))))
+        r = renderer.render(c)
+        self.assertEqual(r, "not (female and (hasChild some Thing))")
+        c = OWLObjectSomeValuesFrom(property=has_child,
+                                    filler=OWLObjectSomeValuesFrom(property=has_child,
+                                                                   filler=OWLObjectSomeValuesFrom(property=has_child,
+                                                                                                  filler=OWLThing)))
+        r = renderer.render(c)
+        self.assertEqual(r, "hasChild some (hasChild some (hasChild some Thing))")
+
+        i1 = OWLNamedIndividual(IRI.create(NS, 'heinz'))
+        i2 = OWLNamedIndividual(IRI.create(NS, 'marie'))
+        oneof = OWLObjectOneOf((i1, i2))
+        r = renderer.render(oneof)
+        assert r == "{heinz , marie}" or r== "{marie , heinz}"
+
+        hasvalue = OWLObjectHasValue(property=has_child, individual=i1)
+        r = renderer.render(hasvalue)
+        self.assertEqual(r, "hasChild value heinz")
+
+        mincard = OWLObjectMinCardinality(cardinality=2, property=has_child, filler=OWLThing)
+        r = renderer.render(mincard)
+        self.assertEqual(r, "hasChild min 2 Thing")
+
+        d = OWLDataSomeValuesFrom(property=has_age,
+                                  filler=OWLDataComplementOf(DoubleOWLDatatype))
+        r = renderer.render(d)
+        self.assertEqual(r, "hasAge some not xsd:double")
+
+        datatype_restriction = owl_datatype_min_max_inclusive_restriction(40, 80)
+
+        dr = OWLDataAllValuesFrom(property=has_age, filler=OWLDataUnionOf([datatype_restriction, IntegerOWLDatatype]))
+        r = renderer.render(dr)
+        self.assertEqual(r, "hasAge only (xsd:integer[>= 40 and <= 80] or xsd:integer)")
+
+        dr = OWLDataSomeValuesFrom(property=has_age,
+                                   filler=OWLDataIntersectionOf([OWLDataOneOf([OWLLiteral(32.5), OWLLiteral(4.5)]),
+                                                                 IntegerOWLDatatype]))
+        r = renderer.render(dr)
+        self.assertEqual(r, "hasAge some ({32.5 , 4.5} and xsd:integer)")
+
+        hasvalue = OWLDataHasValue(property=has_age, value=OWLLiteral(50))
+        r = renderer.render(hasvalue)
+        self.assertEqual(r, "hasAge value 50")
+
+        maxcard = OWLDataExactCardinality(cardinality=1, property=has_age, filler=IntegerOWLDatatype)
+        r = renderer.render(maxcard)
+        self.assertEqual(r, "hasAge exactly 1 xsd:integer")
+
+        maxcard = OWLDataMaxCardinality(cardinality=4, property=has_age, filler=DoubleOWLDatatype)
+        r = renderer.render(maxcard)
+        self.assertEqual(r, "hasAge max 4 xsd:double")
+
+        mincard = OWLDataMinCardinality(cardinality=7, property=has_age, filler=BooleanOWLDatatype)
+        r = renderer.render(mincard)
+        self.assertEqual(r, "hasAge min 7 xsd:boolean")
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/test_owlapy_ontology_management.py b/tests/test_owlapy_ontology_management.py
index 96a3ed9f..cf8d4644 100644
--- a/tests/test_owlapy_ontology_management.py
+++ b/tests/test_owlapy_ontology_management.py
@@ -2,7 +2,7 @@
 import unittest
 
 from pandas import Timedelta
-from owlapy.owl_reasoner import FastInstanceCheckerReasoner, OntologyReasoner, SyncReasoner
+from owlapy.owl_reasoner import StructuralReasoner, SyncReasoner
 from owlapy.providers import owl_datatype_max_inclusive_restriction, owl_datatype_min_inclusive_restriction, \
                               owl_datatype_min_max_exclusive_restriction, owl_datatype_min_max_inclusive_restriction
 
@@ -36,7 +36,7 @@ def test_equivalent_classes(self):
         ns = "http://dl-learner.org/mutagenesis#"
         mgr = OntologyManager()
         onto = mgr.load_ontology(IRI.create("file://KGs/Mutagenesis/mutagenesis.owl"))
-        reasoner = OntologyReasoner(onto)
+        reasoner = StructuralReasoner(onto)
 
         atom = OWLClass(IRI(ns, 'Atom'))
         bond = OWLClass(IRI(ns, 'Bond'))
@@ -80,7 +80,7 @@ def test_sub_classes(self):
         ns = "http://dl-learner.org/mutagenesis#"
         mgr = OntologyManager()
         onto = mgr.load_ontology(IRI.create("file://KGs/Mutagenesis/mutagenesis.owl"))
-        reasoner = OntologyReasoner(onto)
+        reasoner = StructuralReasoner(onto)
 
         bond = OWLClass(IRI(ns, 'Bond'))
         ball3 = OWLClass(IRI(ns, 'Ball3'))
@@ -141,7 +141,7 @@ def test_super_classes(self):
         ns = "http://dl-learner.org/mutagenesis#"
         mgr = OntologyManager()
         onto = mgr.load_ontology(IRI.create("file://KGs/Mutagenesis/mutagenesis.owl"))
-        reasoner = OntologyReasoner(onto)
+        reasoner = StructuralReasoner(onto)
 
         bond = OWLClass(IRI(ns, 'Bond'))
         ball3 = OWLClass(IRI(ns, 'Ball3'))
@@ -203,7 +203,7 @@ def test_sub_object_properties(self):
         ns = "http://www.biopax.org/examples/glycolysis#"
         mgr = OntologyManager()
         onto = mgr.load_ontology(IRI.create("file://KGs/Biopax/biopax.owl"))
-        reasoner = OntologyReasoner(onto)
+        reasoner = StructuralReasoner(onto)
 
         participants = OWLObjectProperty(IRI.create(ns, 'PARTICIPANTS'))
         target_props = frozenset({OWLObjectProperty(IRI(ns, 'COFACTOR')),
@@ -218,7 +218,7 @@ def test_instances(self):
         ns = "http://example.com/father#"
         mgr = OntologyManager()
         onto = mgr.load_ontology(IRI.create("file://KGs/Family/father.owl"))
-        reasoner = OntologyReasoner(onto)
+        reasoner = StructuralReasoner(onto)
 
         inst = frozenset(reasoner.instances(OWLThing))
         target_inst = frozenset({OWLNamedIndividual(IRI(ns, 'anna')),
@@ -238,7 +238,7 @@ def test_types(self):
         ns = "http://example.com/father#"
         mgr = OntologyManager()
         onto = mgr.load_ontology(IRI.create("file://KGs/Family/father.owl"))
-        reasoner = OntologyReasoner(onto)
+        reasoner = StructuralReasoner(onto)
 
         types = frozenset(reasoner.types(OWLNamedIndividual(IRI.create(ns, 'stefan'))))
         target_types = frozenset({OWLThing, OWLClass(IRI(ns, 'male')), OWLClass(IRI(ns, 'person'))})
@@ -248,7 +248,7 @@ def test_object_values(self):
         ns = "http://example.com/father#"
         mgr = OntologyManager()
         onto = mgr.load_ontology(IRI.create("file://KGs/Family/father.owl"))
-        reasoner = OntologyReasoner(onto)
+        reasoner = StructuralReasoner(onto)
 
         stefan = OWLNamedIndividual(IRI.create(ns, 'stefan'))
         markus = OWLNamedIndividual(IRI.create(ns, 'markus'))
@@ -308,8 +308,7 @@ def test_data_values(self):
         ns = "http://dl-learner.org/mutagenesis#"
         mgr = OntologyManager()
         onto = mgr.load_ontology(IRI.create("file://KGs/Mutagenesis/mutagenesis.owl"))
-        base_reasoner = OntologyReasoner(onto)
-        reasoner = FastInstanceCheckerReasoner(onto, base_reasoner)
+        reasoner = StructuralReasoner(onto)
 
         d100_1 = OWLNamedIndividual(IRI.create(ns, 'd100_1'))
         charge = OWLDataProperty(IRI.create(ns, 'charge'))
@@ -338,8 +337,7 @@ def test_all_data_values(self):
         ns = "http://dl-learner.org/mutagenesis#"
         mgr = OntologyManager()
         onto = mgr.load_ontology(IRI.create("file://KGs/Mutagenesis/mutagenesis.owl"))
-        base_reasoner = OntologyReasoner(onto)
-        reasoner = FastInstanceCheckerReasoner(onto, base_reasoner)
+        reasoner = StructuralReasoner(onto)
 
         charge = OWLDataProperty(IRI.create(ns, 'charge'))
         super_charge = OWLDataProperty(IRI.create(ns, 'super_charge'))
@@ -359,8 +357,7 @@ def test_ind_object_properties(self):
         ns = "http://example.com/father#"
         mgr = OntologyManager()
         onto = mgr.load_ontology(IRI.create("file://KGs/Family/father.owl"))
-        base_reasoner = OntologyReasoner(onto)
-        reasoner = FastInstanceCheckerReasoner(onto, base_reasoner)
+        reasoner = StructuralReasoner(onto)
 
         stefan = OWLNamedIndividual(IRI.create(ns, 'stefan'))
         has_child = OWLObjectProperty(IRI.create(ns, 'hasChild'))
@@ -380,8 +377,7 @@ def test_ind_data_properties(self):
         ns = "http://dl-learner.org/mutagenesis#"
         mgr = OntologyManager()
         onto = mgr.load_ontology(IRI.create("file://KGs/Mutagenesis/mutagenesis.owl"))
-        base_reasoner = OntologyReasoner(onto)
-        reasoner = FastInstanceCheckerReasoner(onto, base_reasoner)
+        reasoner = StructuralReasoner(onto)
 
         d100_1 = OWLNamedIndividual(IRI.create(ns, 'd100_1'))
         charge = OWLDataProperty(IRI.create(ns, 'charge'))
@@ -401,7 +397,7 @@ def test_add_remove_axiom(self):
         ns = "http://example.com/father#"
         mgr = OntologyManager()
         onto = mgr.load_ontology(IRI.create("file://KGs/Family/father.owl"))
-        reasoner = OntologyReasoner(onto)
+        reasoner = StructuralReasoner(onto)
 
         markus = OWLNamedIndividual(IRI.create(ns, 'markus'))
         michelle = OWLNamedIndividual(IRI.create(ns, 'michelle'))
diff --git a/tests/test_owlapy_owl2sparql_converter.py b/tests/test_owlapy_owl2sparql_converter.py
index 477e3769..c7a702d3 100644
--- a/tests/test_owlapy_owl2sparql_converter.py
+++ b/tests/test_owlapy_owl2sparql_converter.py
@@ -5,7 +5,7 @@
 from owlapy.iri import IRI
 from owlapy.owl_property import OWLObjectProperty
 from owlapy.owl_ontology_manager import OntologyManager
-from owlapy.owl_reasoner import OntologyReasoner, FastInstanceCheckerReasoner
+from owlapy.owl_reasoner import StructuralReasoner
 from owlapy.parser import DLSyntaxParser
 from rdflib import Graph
 from owlapy.converter import Owl2SparqlConverter
@@ -95,8 +95,7 @@ def test_Single(self):
         # knowledge base - using OWLReasoner
         mgr = OntologyManager()
         onto = mgr.load_ontology(IRI.create(PATH_FAMILY))
-        base_reasoner = OntologyReasoner(onto)
-        family_kb_reasoner = FastInstanceCheckerReasoner(onto, base_reasoner=base_reasoner, negation_default=True)
+        family_kb_reasoner = StructuralReasoner(onto, negation_default=True)
 
         ce_str = "Brother"
         ce_parsed = DLSyntaxParser(namespace="http://www.benchmark.org/family#").parse_expression(expression_str=ce_str)
@@ -139,8 +138,7 @@ def test_Intersection(self):
         # knowledge base - using OWLReasoner
         mgr = OntologyManager()
         onto = mgr.load_ontology(IRI.create(PATH_FAMILY))
-        base_reasoner = OntologyReasoner(onto)
-        family_kb_reasoner = FastInstanceCheckerReasoner(onto, base_reasoner=base_reasoner, negation_default=True)
+        family_kb_reasoner = StructuralReasoner(onto, negation_default=True)
 
         ce_str = "Brother ⊓ Father"
         ce_parsed = DLSyntaxParser(namespace="http://www.benchmark.org/family#").parse_expression(expression_str=ce_str)
@@ -167,8 +165,7 @@ def test_Union(self):
         # knowledge base - using OWLReasoner
         mgr = OntologyManager()
         onto = mgr.load_ontology(IRI.create(PATH_FAMILY))
-        base_reasoner = OntologyReasoner(onto)
-        family_kb_reasoner = FastInstanceCheckerReasoner(onto, base_reasoner=base_reasoner, negation_default=True)
+        family_kb_reasoner = StructuralReasoner(onto, negation_default=True)
 
         ce_str = "Sister ⊔ Mother"
         ce_parsed = DLSyntaxParser(namespace="http://www.benchmark.org/family#").parse_expression(expression_str=ce_str)
@@ -196,8 +193,7 @@ def test_Complement(self):
         # knowledge base - using OWLReasoner
         mgr = OntologyManager()
         onto = mgr.load_ontology(IRI.create(PATH_FAMILY))
-        base_reasoner = OntologyReasoner(onto)
-        family_kb_reasoner = FastInstanceCheckerReasoner(onto, base_reasoner=base_reasoner, negation_default=True)
+        family_kb_reasoner = StructuralReasoner(onto, negation_default=True)
 
         ce_str = "¬Mother"
         ce_parsed = DLSyntaxParser(namespace="http://www.benchmark.org/family#").parse_expression(expression_str=ce_str)
@@ -225,8 +221,7 @@ def test_Exists(self):
         # knowledge base - using OWLReasoner
         mgr = OntologyManager()
         onto = mgr.load_ontology(IRI.create(PATH_FAMILY))
-        base_reasoner = OntologyReasoner(onto)
-        family_kb_reasoner = FastInstanceCheckerReasoner(onto, base_reasoner=base_reasoner, negation_default=True)
+        family_kb_reasoner = StructuralReasoner(onto, negation_default=True)
 
         ce_str = "∃hasChild.Male"
         ce_parsed = DLSyntaxParser(namespace="http://www.benchmark.org/family#").parse_expression(expression_str=ce_str)
diff --git a/tests/test_owlapy_render.py b/tests/test_owlapy_render.py
deleted file mode 100644
index cd9a1de0..00000000
--- a/tests/test_owlapy_render.py
+++ /dev/null
@@ -1,191 +0,0 @@
-import unittest
-
-from owlapy.iri import IRI
-from owlapy.owl_individual import OWLNamedIndividual
-from owlapy.owl_literal import DoubleOWLDatatype, IntegerOWLDatatype, OWLLiteral, BooleanOWLDatatype
-from owlapy.owl_property import OWLObjectProperty, OWLDataProperty
-from owlapy.class_expression import OWLDataMinCardinality, OWLObjectIntersectionOf, OWLObjectSomeValuesFrom, \
-    OWLThing, OWLObjectComplementOf, OWLObjectUnionOf, OWLObjectMinCardinality, OWLClass, \
-    OWLDataExactCardinality, OWLDataHasValue, OWLDataAllValuesFrom, \
-    OWLDataOneOf, OWLDataSomeValuesFrom, \
-    OWLDataMaxCardinality, OWLObjectHasValue, OWLObjectOneOf
-
-from owlapy.owl_data_ranges import OWLDataComplementOf, OWLDataIntersectionOf, OWLDataUnionOf
-from owlapy.providers import owl_datatype_min_max_inclusive_restriction
-from owlapy.render import DLSyntaxObjectRenderer, ManchesterOWLSyntaxOWLObjectRenderer
-
-class Owlapy_DLRenderer_Test(unittest.TestCase):
-    def test_ce_render(self):
-        renderer = DLSyntaxObjectRenderer()
-        NS = "http://example.com/father#"
-
-        male = OWLClass(IRI.create(NS, 'male'))
-        female = OWLClass(IRI.create(NS, 'female'))
-        has_child = OWLObjectProperty(IRI(NS, 'hasChild'))
-        has_age = OWLDataProperty(IRI(NS, 'hasAge'))
-
-        c = OWLObjectUnionOf((male, OWLObjectSomeValuesFrom(property=has_child, filler=female)))
-        r = renderer.render(c)
-        print(r)
-        self.assertEqual(r, "male ⊔ (∃ hasChild.female)")
-        c = OWLObjectComplementOf(OWLObjectIntersectionOf((female,
-                                                           OWLObjectSomeValuesFrom(property=has_child,
-                                                                                   filler=OWLThing))))
-        r = renderer.render(c)
-        print(r)
-        self.assertEqual(r, "¬(female ⊓ (∃ hasChild.⊤))")
-        c = OWLObjectSomeValuesFrom(property=has_child,
-                                    filler=OWLObjectSomeValuesFrom(property=has_child,
-                                                                   filler=OWLObjectSomeValuesFrom(property=has_child,
-                                                                                                  filler=OWLThing)))
-        r = renderer.render(c)
-        print(r)
-        self.assertEqual(r, "∃ hasChild.(∃ hasChild.(∃ hasChild.⊤))")
-
-        i1 = OWLNamedIndividual(IRI.create(NS, 'heinz'))
-        i2 = OWLNamedIndividual(IRI.create(NS, 'marie'))
-        oneof = OWLObjectOneOf((i1, i2))
-        r = renderer.render(oneof)
-        print(r)
-
-        self.assertEqual(r, "{heinz , marie}")
-
-        hasvalue = OWLObjectHasValue(property=has_child, individual=i1)
-        r = renderer.render(hasvalue)
-        print(r)
-        self.assertEqual(r, "∃ hasChild.{heinz}")
-
-        mincard = OWLObjectMinCardinality(cardinality=2, property=has_child, filler=OWLThing)
-        r = renderer.render(mincard)
-        print(r)
-        self.assertEqual(r, "≥ 2 hasChild.⊤")
-
-        d = OWLDataSomeValuesFrom(property=has_age,
-                                  filler=OWLDataComplementOf(DoubleOWLDatatype))
-        r = renderer.render(d)
-        print(r)
-        self.assertEqual(r, "∃ hasAge.¬xsd:double")
-
-        datatype_restriction = owl_datatype_min_max_inclusive_restriction(40, 80)
-
-        dr = OWLDataAllValuesFrom(property=has_age, filler=OWLDataUnionOf([datatype_restriction, IntegerOWLDatatype]))
-        r = renderer.render(dr)
-        print(r)
-        self.assertEqual(r, "∀ hasAge.(xsd:integer[≥ 40 , ≤ 80] ⊔ xsd:integer)")
-
-        dr = OWLDataSomeValuesFrom(property=has_age,
-                                   filler=OWLDataIntersectionOf([OWLDataOneOf([OWLLiteral(32.5), OWLLiteral(4.5)]),
-                                                                 IntegerOWLDatatype]))
-        r = renderer.render(dr)
-        print(r)
-        self.assertEqual(r, "∃ hasAge.({32.5 ⊔ 4.5} ⊓ xsd:integer)")
-
-        hasvalue = OWLDataHasValue(property=has_age, value=OWLLiteral(50))
-        r = renderer.render(hasvalue)
-        print(r)
-        self.assertEqual(r, "∃ hasAge.{50}")
-
-        exactcard = OWLDataExactCardinality(cardinality=1, property=has_age, filler=IntegerOWLDatatype)
-        r = renderer.render(exactcard)
-        print(r)
-        self.assertEqual(r, "= 1 hasAge.xsd:integer")
-
-        maxcard = OWLDataMaxCardinality(cardinality=4, property=has_age, filler=DoubleOWLDatatype)
-        r = renderer.render(maxcard)
-        print(r)
-        self.assertEqual(r, "≤ 4 hasAge.xsd:double")
-
-        mincard = OWLDataMinCardinality(cardinality=7, property=has_age, filler=BooleanOWLDatatype)
-        r = renderer.render(mincard)
-        print(r)
-        self.assertEqual(r, "≥ 7 hasAge.xsd:boolean")
-
-
-class Owlapy_ManchesterRenderer_Test(unittest.TestCase):
-    def test_ce_render(self):
-        renderer = ManchesterOWLSyntaxOWLObjectRenderer()
-        NS = "http://example.com/father#"
-
-        male = OWLClass(IRI.create(NS, 'male'))
-        female = OWLClass(IRI.create(NS, 'female'))
-        has_child = OWLObjectProperty(IRI(NS, 'hasChild'))
-        has_age = OWLDataProperty(IRI(NS, 'hasAge'))
-
-        c = OWLObjectUnionOf((male, OWLObjectSomeValuesFrom(property=has_child, filler=female)))
-        r = renderer.render(c)
-        print(r)
-        self.assertEqual(r, "male or (hasChild some female)")
-        c = OWLObjectComplementOf(OWLObjectIntersectionOf((female,
-                                                           OWLObjectSomeValuesFrom(property=has_child,
-                                                                                   filler=OWLThing))))
-        r = renderer.render(c)
-        print(r)
-        self.assertEqual(r, "not (female and (hasChild some Thing))")
-        c = OWLObjectSomeValuesFrom(property=has_child,
-                                    filler=OWLObjectSomeValuesFrom(property=has_child,
-                                                                   filler=OWLObjectSomeValuesFrom(property=has_child,
-                                                                                                  filler=OWLThing)))
-        r = renderer.render(c)
-        print(r)
-        self.assertEqual(r, "hasChild some (hasChild some (hasChild some Thing))")
-
-        i1 = OWLNamedIndividual(IRI.create(NS, 'heinz'))
-        i2 = OWLNamedIndividual(IRI.create(NS, 'marie'))
-        oneof = OWLObjectOneOf((i1, i2))
-        r = renderer.render(oneof)
-        print(r)
-        self.assertEqual(r, "{heinz , marie}")
-
-        hasvalue = OWLObjectHasValue(property=has_child, individual=i1)
-        r = renderer.render(hasvalue)
-        print(r)
-        self.assertEqual(r, "hasChild value heinz")
-
-        mincard = OWLObjectMinCardinality(cardinality=2, property=has_child, filler=OWLThing)
-        r = renderer.render(mincard)
-        print(r)
-        self.assertEqual(r, "hasChild min 2 Thing")
-
-        d = OWLDataSomeValuesFrom(property=has_age,
-                                  filler=OWLDataComplementOf(DoubleOWLDatatype))
-        r = renderer.render(d)
-        print(r)
-        self.assertEqual(r, "hasAge some not xsd:double")
-
-        datatype_restriction = owl_datatype_min_max_inclusive_restriction(40, 80)
-
-        dr = OWLDataAllValuesFrom(property=has_age, filler=OWLDataUnionOf([datatype_restriction, IntegerOWLDatatype]))
-        r = renderer.render(dr)
-        print(r)
-        self.assertEqual(r, "hasAge only (xsd:integer[>= 40 , <= 80] or xsd:integer)")
-
-        dr = OWLDataSomeValuesFrom(property=has_age,
-                                   filler=OWLDataIntersectionOf([OWLDataOneOf([OWLLiteral(32.5), OWLLiteral(4.5)]),
-                                                                 IntegerOWLDatatype]))
-        r = renderer.render(dr)
-        print(r)
-        self.assertEqual(r, "hasAge some ({32.5 , 4.5} and xsd:integer)")
-
-        hasvalue = OWLDataHasValue(property=has_age, value=OWLLiteral(50))
-        r = renderer.render(hasvalue)
-        print(r)
-        self.assertEqual(r, "hasAge value 50")
-
-        maxcard = OWLDataExactCardinality(cardinality=1, property=has_age, filler=IntegerOWLDatatype)
-        r = renderer.render(maxcard)
-        print(r)
-        self.assertEqual(r, "hasAge exactly 1 xsd:integer")
-
-        maxcard = OWLDataMaxCardinality(cardinality=4, property=has_age, filler=DoubleOWLDatatype)
-        r = renderer.render(maxcard)
-        print(r)
-        self.assertEqual(r, "hasAge max 4 xsd:double")
-
-        mincard = OWLDataMinCardinality(cardinality=7, property=has_age, filler=BooleanOWLDatatype)
-        r = renderer.render(mincard)
-        print(r)
-        self.assertEqual(r, "hasAge min 7 xsd:boolean")
-
-
-if __name__ == '__main__':
-    unittest.main()
diff --git a/tests/test_owlapy_fastinstancechecker.py b/tests/test_owlapy_structural_reasoner.py
similarity index 91%
rename from tests/test_owlapy_fastinstancechecker.py
rename to tests/test_owlapy_structural_reasoner.py
index ea0e061b..b9c08b30 100644
--- a/tests/test_owlapy_fastinstancechecker.py
+++ b/tests/test_owlapy_structural_reasoner.py
@@ -14,13 +14,13 @@
 from owlapy.owl_property import OWLObjectInverseOf, OWLObjectProperty, OWLDataProperty
 from owlready2.prop import DataProperty
 
-from owlapy.owl_reasoner import FastInstanceCheckerReasoner, OntologyReasoner
+from owlapy.owl_reasoner import StructuralReasoner
 
 from owlapy.providers import owl_datatype_min_max_inclusive_restriction, owl_datatype_min_max_exclusive_restriction, \
                              owl_datatype_max_inclusive_restriction
 
 
-class Owlapy_FastInstanceChecker_Test(unittest.TestCase):
+class Owlapy_StructuralReasoner_Test(unittest.TestCase):
     # noinspection DuplicatedCode
     def test_instances(self):
         NS = "http://example.com/father#"
@@ -31,8 +31,7 @@ def test_instances(self):
         female = OWLClass(IRI.create(NS, 'female'))
         has_child = OWLObjectProperty(IRI(NS, 'hasChild'))
 
-        base_reasoner = OntologyReasoner(onto)
-        reasoner = FastInstanceCheckerReasoner(onto, base_reasoner=base_reasoner)
+        reasoner = StructuralReasoner(onto)
 
         self.assertEqual([], list(reasoner.sub_object_properties(has_child, direct=True)))
 
@@ -82,9 +81,8 @@ def test_complement(self):
         female = OWLClass(IRI.create(NS, 'female'))
         has_child = OWLObjectProperty(IRI(NS, 'hasChild'))
 
-        base_reasoner = OntologyReasoner(onto)
-        reasoner_nd = FastInstanceCheckerReasoner(onto, base_reasoner=base_reasoner, negation_default=True)
-        reasoner_open = FastInstanceCheckerReasoner(onto, base_reasoner=base_reasoner, negation_default=False)
+        reasoner_nd = StructuralReasoner(onto, negation_default=True)
+        reasoner_open = StructuralReasoner(onto, negation_default=False)
 
         self.assertEqual(set(reasoner_nd.instances(male)), set(reasoner_nd.instances(OWLObjectComplementOf(female))))
         self.assertEqual(set(reasoner_nd.instances(female)), set(reasoner_nd.instances(OWLObjectComplementOf(male))))
@@ -108,8 +106,7 @@ def test_all_values(self):
 
         has_child = OWLObjectProperty(IRI(NS, 'hasChild'))
 
-        base_reasoner = OntologyReasoner(onto)
-        reasoner_nd = FastInstanceCheckerReasoner(onto, base_reasoner=base_reasoner, negation_default=True)
+        reasoner_nd = StructuralReasoner(onto, negation_default=True)
 
         # note, these answers are all wrong under OWA
         no_child = frozenset(reasoner_nd.instances(OWLObjectAllValuesFrom(property=has_child, filler=OWLNothing)))
@@ -125,8 +122,7 @@ def test_complement2(self):
         male = OWLClass(IRI.create(NS, 'male'))
         female = OWLClass(IRI.create(NS, 'female'))
 
-        base_reasoner = OntologyReasoner(onto)
-        reasoner_open = FastInstanceCheckerReasoner(onto, base_reasoner=base_reasoner, negation_default=False)
+        reasoner_open = StructuralReasoner(onto, negation_default=False)
 
         # Should be empty under open world assumption
         self.assertEqual(set(), set(reasoner_open.instances(OWLObjectComplementOf(female))))
@@ -141,8 +137,7 @@ def test_cardinality_restrictions(self):
         atom = OWLClass(IRI.create(NS, 'Atom'))
         has_atom = OWLObjectProperty(IRI(NS, 'hasAtom'))
 
-        base_reasoner = OntologyReasoner(onto)
-        reasoner = FastInstanceCheckerReasoner(onto, base_reasoner=base_reasoner, negation_default=True)
+        reasoner = StructuralReasoner(onto, negation_default=True)
 
         inst = frozenset(reasoner.instances(OWLObjectExactCardinality(cardinality=2,
                                                                       property=has_atom,
@@ -178,8 +173,7 @@ def test_data_properties(self):
         logp = OWLDataProperty(IRI(NS, 'logp'))
         charge = OWLDataProperty(IRI(NS, 'charge'))
 
-        base_reasoner = OntologyReasoner(onto)
-        reasoner = FastInstanceCheckerReasoner(onto, base_reasoner=base_reasoner, negation_default=True)
+        reasoner = StructuralReasoner(onto, negation_default=True)
 
         self.assertEqual([], list(reasoner.sub_data_properties(act, direct=True)))
 
@@ -274,8 +268,7 @@ class birthDateTime(DataProperty):
         michelle = OWLNamedIndividual(IRI(NS, 'michelle'))
         martin = OWLNamedIndividual(IRI(NS, 'martin'))
 
-        base_reasoner = OntologyReasoner(onto)
-        reasoner = FastInstanceCheckerReasoner(onto, base_reasoner=base_reasoner)
+        reasoner = StructuralReasoner(onto)
 
         restriction = owl_datatype_min_max_exclusive_restriction(date(year=1995, month=6, day=12),
                                                             date(year=1999, month=3, day=2))
@@ -312,8 +305,13 @@ def test_sub_property_inclusion(self):
         onto.add_axiom(OWLSubDataPropertyOfAxiom(charge, super_charge))
 
         # sub_property = True
-        base_reasoner = OntologyReasoner(onto)
-        reasoner = FastInstanceCheckerReasoner(onto, base_reasoner=base_reasoner, sub_properties=True)
+        reasoner = StructuralReasoner(onto, sub_properties=True)
+        reasoner._ontology.is_modified = False  # This is done because, for sub_properties to work as expected it needs
+                                                # _property_cache of the reasoner to be True which would normally be
+                                                # False when the ontology is modified. Info: Cache needs to be reset and
+                                                # disabled when ontolgy modification is detected because the
+                                                # cached facts may not hold anymore. Hence, setting is_modified to False
+                                                # is an excepton to check this test.
 
         # object property
         ce = OWLObjectIntersectionOf([compound, OWLObjectSomeValuesFrom(super_has_structure, benzene)])
@@ -326,8 +324,7 @@ def test_sub_property_inclusion(self):
         self.assertEqual(len(individuals), 75)
 
         # sub_property = False
-        base_reasoner = OntologyReasoner(onto)
-        reasoner = FastInstanceCheckerReasoner(onto, base_reasoner=base_reasoner, sub_properties=False)
+        reasoner = StructuralReasoner(onto, sub_properties=False)
 
         # object property
         ce = OWLObjectIntersectionOf([compound, OWLObjectSomeValuesFrom(super_has_structure, benzene)])
@@ -356,8 +353,7 @@ def test_inverse(self):
                    OWLNamedIndividual(IRI.create(ns, 'stefan')),
                    OWLNamedIndividual(IRI.create(ns, 'markus'))}
 
-        base_reasoner = OntologyReasoner(onto)
-        reasoner = FastInstanceCheckerReasoner(onto, base_reasoner=base_reasoner, sub_properties=False)
+        reasoner = StructuralReasoner(onto, sub_properties=False)
 
         expr = OWLObjectSomeValuesFrom(has_child, OWLThing)
         expr_inverse = OWLObjectSomeValuesFrom(OWLObjectInverseOf(has_child_inverse), OWLThing)
@@ -383,7 +379,7 @@ def test_inverse(self):
         self.assertEqual(parents_expr_inverse, frozenset())
 
         # True (sub properties taken into account)
-        reasoner = FastInstanceCheckerReasoner(onto, base_reasoner=base_reasoner, sub_properties=True)
+        reasoner = StructuralReasoner(onto,  sub_properties=True)
         expr = OWLObjectSomeValuesFrom(super_has_child, OWLThing)
         expr_inverse = OWLObjectSomeValuesFrom(OWLObjectInverseOf(super_has_child_inverse), OWLThing)
         parents_expr = frozenset(reasoner.instances(expr))