/// <summary> /// SymmetricPropertyEntailment implements data entailments based on 'owl:SymmetricProperty' axiom: /// ((F1 P F2) AND (P TYPE SYMMETRICPROPERTY)) => (F2 P F1) /// </summary> internal static RDFOntologyReasonerReport SymmetricPropertyEntailmentExec(RDFOntology ontology) { var report = new RDFOntologyReasonerReport(); //Calculate the set of available properties on which to perform the reasoning (exclude BASE properties and not-symmetric properties) var availableprops = ontology.Model.PropertyModel.Where(prop => !RDFOntologyChecker.CheckReservedProperty(prop) && prop.IsSymmetricProperty()).ToList(); foreach (var p in availableprops) { //Filter the assertions using the current property (F1 P F2) var pAsns = ontology.Data.Relations.Assertions.SelectEntriesByPredicate(p); //Iterate those assertions foreach (var pAsn in pAsns) { //Taxonomy-check for securing inference consistency if (pAsn.TaxonomyObject.IsFact()) { //Create the inference as a taxonomy entry var sem_inf = new RDFOntologyTaxonomyEntry(pAsn.TaxonomyObject, p, pAsn.TaxonomySubject).SetInference(RDFSemanticsEnums.RDFOntologyInferenceType.Reasoner); //Add the inference to the ontology and to the report if (ontology.Data.Relations.Assertions.AddEntry(sem_inf)) { report.AddEvidence(new RDFOntologyReasonerEvidence(RDFSemanticsEnums.RDFOntologyReasonerEvidenceCategory.Data, "SymmetricPropertyEntailment", sem_inf)); } } } } return(report); }
/// <summary> /// Adds the "aFact -> objectProperty -> bFact" relation to the data /// </summary> public RDFOntologyData AddAssertionRelation(RDFOntologyFact aFact, RDFOntologyObjectProperty objectProperty, RDFOntologyFact bFact) { if (aFact != null && objectProperty != null && bFact != null) { //Enforce preliminary check on usage of BASE properties if (!RDFOntologyChecker.CheckReservedProperty(objectProperty)) { //Enforce taxonomy checks before adding the assertion //Creation of transitive cycles is not allowed (OWL-DL) if (RDFOntologyChecker.CheckTransitiveAssertionCompatibility(this, aFact, objectProperty, bFact)) { this.Relations.Assertions.AddEntry(new RDFOntologyTaxonomyEntry(aFact, objectProperty, bFact)); } else { //Raise warning event to inform the user: Assertion relation cannot be added to the data because it violates the taxonomy transitive consistency RDFSemanticsEvents.RaiseSemanticsWarning(String.Format("Assertion relation between fact '{0}' and fact '{1}' with transitive property '{2}' cannot be added to the data because it would violate the taxonomy consistency (transitive cycle detected).", aFact, bFact, objectProperty)); } } else { //Raise warning event to inform the user: Assertion relation cannot be added to the data because usage of BASE reserved properties compromises the taxonomy consistency RDFSemanticsEvents.RaiseSemanticsWarning(String.Format("Assertion relation between fact '{0}' and fact '{1}' cannot be added to the data because usage of BASE reserved properties compromises the taxonomy consistency.", aFact, bFact)); } } return(this); }
/// <summary> /// Adds the "ontologyFact -> rdf:type -> ontologyClass" relation to the data. /// </summary> public RDFOntologyData AddClassTypeRelation(RDFOntologyFact ontologyFact, RDFOntologyClass ontologyClass) { if (ontologyFact != null && ontologyClass != null) { //Enforce preliminary check on usage of BASE classes if (!RDFOntologyChecker.CheckReservedClass(ontologyClass)) { //Enforce taxonomy checks before adding the ClassType relation if (RDFOntologyChecker.CheckClassTypeCompatibility(ontologyClass)) { this.Relations.ClassType.AddEntry(new RDFOntologyTaxonomyEntry(ontologyFact, RDFVocabulary.RDF.TYPE.ToRDFOntologyObjectProperty(), ontologyClass)); } else { //Raise warning event to inform the user: ClassType relation cannot be added to the data because only plain classes can be explicitly assigned as class types of facts RDFSemanticsEvents.RaiseSemanticsWarning(String.Format("ClassType relation between fact '{0}' and class '{1}' cannot be added to the data because only plain classes can be explicitly assigned as class types of facts.", ontologyFact, ontologyClass)); } } else { //Raise warning event to inform the user: ClassType relation cannot be added to the data because usage of BASE reserved classes compromises the taxonomy consistency RDFSemanticsEvents.RaiseSemanticsWarning(String.Format("ClassType relation between fact '{0}' and class '{1}' cannot be added to the data because because usage of BASE reserved classes compromises the taxonomy consistency.", ontologyFact, ontologyClass)); } } return(this); }
/// <summary> /// EquivalentPropertyTransitivity implements structural entailments based on 'owl:EquivalentProperty' taxonomy: /// ((P1 EQUIVALENTPROPERTY P2) AND (P2 EQUIVALENTPROPERTY P3)) => (P1 EQUIVALENTPROPERTY P3) /// </summary> internal static RDFOntologyReasonerReport EquivalentPropertyTransitivityExec(RDFOntology ontology) { var report = new RDFOntologyReasonerReport(); var equivProperty = RDFVocabulary.OWL.EQUIVALENT_PROPERTY.ToRDFOntologyObjectProperty(); //Calculate the set of available properties on which to perform the reasoning (exclude BASE properties and annotation properties) var availableprops = ontology.Model.PropertyModel.Where(prop => !RDFOntologyChecker.CheckReservedProperty(prop) && !prop.IsAnnotationProperty()).ToList(); foreach (var p in availableprops) { //Enlist the equivalent properties of the current property var equivprops = ontology.Model.PropertyModel.GetEquivalentPropertiesOf(p); foreach (var ep in equivprops) { //Create the inference as a taxonomy entry var sem_infA = new RDFOntologyTaxonomyEntry(p, equivProperty, ep).SetInference(RDFSemanticsEnums.RDFOntologyInferenceType.Reasoner); var sem_infB = new RDFOntologyTaxonomyEntry(ep, equivProperty, p).SetInference(RDFSemanticsEnums.RDFOntologyInferenceType.Reasoner); //Add the inference to the ontology and to the report if (ontology.Model.PropertyModel.Relations.EquivalentProperty.AddEntry(sem_infA)) { report.AddEvidence(new RDFOntologyReasonerEvidence(RDFSemanticsEnums.RDFOntologyReasonerEvidenceCategory.PropertyModel, "EquivalentPropertyTransitivity", sem_infA)); } if (ontology.Model.PropertyModel.Relations.EquivalentProperty.AddEntry(sem_infB)) { report.AddEvidence(new RDFOntologyReasonerEvidence(RDFSemanticsEnums.RDFOntologyReasonerEvidenceCategory.PropertyModel, "EquivalentPropertyTransitivity", sem_infB)); } } } return(report); }
/// <summary> /// "DomainEntailment (rdfs2) implements structural entailments based on 'rdfs:domain' taxonomy:" /// "((F1 P F2) AND (P RDFS:DOMAIN C)) => (F1 RDF:TYPE C)" /// </summary> internal static RDFOntologyReasonerReport DomainEntailmentExec(RDFOntology ontology) { var report = new RDFOntologyReasonerReport(); var type = RDFVocabulary.RDF.TYPE.ToRDFOntologyObjectProperty(); //Calculate the set of available properties on which to perform the reasoning (exclude BASE properties and annotation properties) var availableprops = ontology.Model.PropertyModel.Where(prop => !RDFOntologyChecker.CheckReservedProperty(prop) && !prop.IsAnnotationProperty()).ToList(); foreach (var p in availableprops) { if (p.Domain != null) { //Filter the assertions using the current property (F1 P1 F2) var pAsns = ontology.Data.Relations.Assertions.SelectEntriesByPredicate(p); //Iterate the related assertions foreach (var pAsn in pAsns) { //Create the inference as a taxonomy entry var sem_inf = new RDFOntologyTaxonomyEntry(pAsn.TaxonomySubject, type, p.Domain).SetInference(RDFSemanticsEnums.RDFOntologyInferenceType.Reasoner); //Add the inference to the ontology and to the report if (ontology.Data.Relations.ClassType.AddEntry(sem_inf)) { report.AddEvidence(new RDFOntologyReasonerEvidence(RDFSemanticsEnums.RDFOntologyReasonerEvidenceCategory.Data, "DomainEntailment", sem_inf)); } } } } return(report); }
/// <summary> /// ClassTypeEntailment (rdfs9) implements structural entailments based on 'rdf:type' taxonomy: /// ((F TYPE C1) AND (C1 SUBCLASSOF C2)) => (F TYPE C2) /// ((F TYPE C1) AND (C1 EQUIVALENTCLASS C2)) => (F TYPE C2) /// </summary> internal static RDFOntologyReasonerReport ClassTypeEntailmentExec(RDFOntology ontology) { var report = new RDFOntologyReasonerReport(); var type = RDFVocabulary.RDF.TYPE.ToRDFOntologyObjectProperty(); //Calculate the set of available classes on which to perform the reasoning (exclude BASE classes and literal-compatible classes) var availableclasses = ontology.Model.ClassModel.Where(cls => !RDFOntologyChecker.CheckReservedClass(cls) && !ontology.Model.ClassModel.CheckIsLiteralCompatible(cls)); foreach (var c in availableclasses) { //Enlist the members of the current class var clsMembers = ontology.GetMembersOfNonLiteralCompatibleClass(c); foreach (var f in clsMembers) { //Create the inference as a taxonomy entry var sem_inf = new RDFOntologyTaxonomyEntry(f, type, c).SetInference(RDFSemanticsEnums.RDFOntologyInferenceType.Reasoner); //Add the inference to the ontology and to the report if (ontology.Data.Relations.ClassType.AddEntry(sem_inf)) { report.AddEvidence(new RDFOntologyReasonerEvidence(RDFSemanticsEnums.RDFOntologyReasonerEvidenceCategory.Data, "ClassTypeEntailment", sem_inf)); } } } return(report); }
/// <summary> /// SubPropertyTransitivity (rdfs5) implements structural entailments based on 'rdfs:subPropertyOf' taxonomy: /// ((P1 SUBPROPERTYOF P2) AND (P2 SUBPROPERTYOF P3)) => (P1 SUBPROPERTYOF P3) /// ((P1 SUBPROPERTYOF P2) AND (P2 EQUIVALENTPROPERTY P3)) => (P1 SUBPROPERTYOF P3) /// ((P1 EQUIVALENTPROPERTY P2) AND (P2 SUBPROPERTYOF P3)) => (P1 SUBPROPERTYOF P3) /// </summary> internal static RDFOntologyReasonerReport SubPropertyTransitivityExec(RDFOntology ontology) { var report = new RDFOntologyReasonerReport(); var subPropertyOf = RDFVocabulary.RDFS.SUB_PROPERTY_OF.ToRDFOntologyObjectProperty(); //Calculate the set of available properties on which to perform the reasoning (exclude BASE properties and annotation properties) var availableprops = ontology.Model.PropertyModel.Where(prop => !RDFOntologyChecker.CheckReservedProperty(prop) && !prop.IsAnnotationProperty()).ToList(); foreach (var p in availableprops) { //Enlist the superproperties of the current property var superprops = ontology.Model.PropertyModel.GetSuperPropertiesOf(p); foreach (var sp in superprops) { //Create the inference as a taxonomy entry var sem_inf = new RDFOntologyTaxonomyEntry(p, subPropertyOf, sp).SetInference(RDFSemanticsEnums.RDFOntologyInferenceType.Reasoner); //Add the inference to the ontology and to the report if (ontology.Model.PropertyModel.Relations.SubPropertyOf.AddEntry(sem_inf)) { report.AddEvidence(new RDFOntologyReasonerEvidence(RDFSemanticsEnums.RDFOntologyReasonerEvidenceCategory.PropertyModel, "SubPropertyTransitivity", sem_inf)); } } } return(report); }
/// <summary> /// Adds the "aFact -> owl:differentFrom -> bFact" relation to the data /// </summary> public RDFOntologyData AddDifferentFromRelation(RDFOntologyFact aFact, RDFOntologyFact bFact) { if (aFact != null && bFact != null && !aFact.Equals(bFact)) { //Enforce taxonomy checks before adding the DifferentFrom relation if (RDFOntologyChecker.CheckDifferentFromCompatibility(this, aFact, bFact)) { this.Relations.DifferentFrom.AddEntry(new RDFOntologyTaxonomyEntry(aFact, RDFVocabulary.OWL.DIFFERENT_FROM.ToRDFOntologyObjectProperty(), bFact)); this.Relations.DifferentFrom.AddEntry(new RDFOntologyTaxonomyEntry(bFact, RDFVocabulary.OWL.DIFFERENT_FROM.ToRDFOntologyObjectProperty(), aFact).SetInference(RDFSemanticsEnums.RDFOntologyInferenceType.API)); } else { //Raise warning event to inform the user: DifferentFrom relation cannot be added to the data because it violates the taxonomy consistency RDFSemanticsEvents.RaiseSemanticsWarning(String.Format("DifferentFrom relation between fact '{0}' and fact '{1}' cannot be added to the data because it violates the taxonomy consistency.", aFact, bFact)); } } return(this); }
/// <summary> /// Adds the "ontologyFact -> datatypeProperty -> ontologyLiteral" relation to the data /// </summary> public RDFOntologyData AddAssertionRelation(RDFOntologyFact ontologyFact, RDFOntologyDatatypeProperty datatypeProperty, RDFOntologyLiteral ontologyLiteral) { if (ontologyFact != null && datatypeProperty != null && ontologyLiteral != null) { //Enforce preliminary check on usage of BASE properties if (!RDFOntologyChecker.CheckReservedProperty(datatypeProperty)) { this.Relations.Assertions.AddEntry(new RDFOntologyTaxonomyEntry(ontologyFact, datatypeProperty, ontologyLiteral)); this.AddLiteral(ontologyLiteral); } else { //Raise warning event to inform the user: Assertion relation cannot be added to the data because usage of BASE reserved properties compromises the taxonomy consistency RDFSemanticsEvents.RaiseSemanticsWarning(String.Format("Assertion relation between fact '{0}' and literal '{1}' cannot be added to the data because usage of BASE reserved properties compromises the taxonomy consistency.", ontologyFact, ontologyLiteral)); } } return(this); }
/// <summary> /// TransitivePropertyEntailment implements data entailments based on 'owl:TransitiveProperty' axiom: /// ((F1 P F2) AND (F2 P F3) AND (P TYPE TRANSITIVEPROPERTY)) => (F1 P F3) /// </summary> internal static RDFOntologyReasonerReport TransitivePropertyEntailmentExec(RDFOntology ontology) { var report = new RDFOntologyReasonerReport(); var transPropCache = new Dictionary <Int64, RDFOntologyData>(); //Calculate the set of available properties on which to perform the reasoning (exclude BASE properties and not-transitive properties) var availableprops = ontology.Model.PropertyModel.Where(prop => !RDFOntologyChecker.CheckReservedProperty(prop) && prop.IsTransitiveProperty()).ToList(); foreach (var p in availableprops) { //Filter the assertions using the current property (F1 P F2) var pAsns = ontology.Data.Relations.Assertions.SelectEntriesByPredicate(p); //Iterate those assertions foreach (var pAsn in pAsns) { //Taxonomy-check for securing inference consistency if (pAsn.TaxonomyObject.IsFact()) { if (!transPropCache.ContainsKey(pAsn.TaxonomySubject.PatternMemberID)) { transPropCache.Add(pAsn.TaxonomySubject.PatternMemberID, ontology.Data.GetTransitiveAssertionsOf((RDFOntologyFact)pAsn.TaxonomySubject, (RDFOntologyObjectProperty)p)); } foreach (var te in transPropCache[pAsn.TaxonomySubject.PatternMemberID]) { //Create the inference as a taxonomy entry var sem_inf = new RDFOntologyTaxonomyEntry(pAsn.TaxonomySubject, p, te).SetInference(RDFSemanticsEnums.RDFOntologyInferenceType.Reasoner); //Add the inference to the ontology and to the report if (ontology.Data.Relations.Assertions.AddEntry(sem_inf)) { report.AddEvidence(new RDFOntologyReasonerEvidence(RDFSemanticsEnums.RDFOntologyReasonerEvidenceCategory.Data, "TransitivePropertyEntailment", sem_inf)); } } } } transPropCache.Clear(); } return(report); }
/// <summary> /// InverseOfEntailment implements data entailments based on 'owl:inverseOf' taxonomy: /// ((F1 P1 F2) AND (P1 INVERSEOF P2)) => (F2 P2 F1) /// </summary> internal static RDFOntologyReasonerReport InverseOfEntailmentExec(RDFOntology ontology) { var report = new RDFOntologyReasonerReport(); //Calculate the set of available properties on which to perform the reasoning (exclude BASE properties and annotation/datatype properties) var availableprops = ontology.Model.PropertyModel.Where(prop => !RDFOntologyChecker.CheckReservedProperty(prop) && prop.IsObjectProperty()).ToList(); foreach (var p1 in availableprops) { //Filter the assertions using the current property (F1 P1 F2) var p1Asns = ontology.Data.Relations.Assertions.SelectEntriesByPredicate(p1); //Enlist the inverse properties of the current property var inverseprops = ontology.Model.PropertyModel.GetInversePropertiesOf((RDFOntologyObjectProperty)p1); foreach (var p2 in inverseprops) { //Iterate the compatible assertions foreach (var p1Asn in p1Asns) { //Taxonomy-check for securing inference consistency if (p2.IsObjectProperty() && p1Asn.TaxonomyObject.IsFact()) { //Create the inference as a taxonomy entry var sem_inf = new RDFOntologyTaxonomyEntry(p1Asn.TaxonomyObject, p2, p1Asn.TaxonomySubject).SetInference(RDFSemanticsEnums.RDFOntologyInferenceType.Reasoner); //Add the inference to the ontology and to the report if (ontology.Data.Relations.Assertions.AddEntry(sem_inf)) { report.AddEvidence(new RDFOntologyReasonerEvidence(RDFSemanticsEnums.RDFOntologyReasonerEvidenceCategory.Data, "InverseOfEntailment", sem_inf)); } } } } } return(report); }
/// <summary> /// Enlists the classes to which the lens fact directly (or indirectly, if inference is requested) belongs /// </summary> public List <(bool, RDFOntologyClass)> ClassTypes(bool enableInference) { List <(bool, RDFOntologyClass)> result = new List <(bool, RDFOntologyClass)>(); //First-level enlisting of class types foreach (RDFOntologyTaxonomyEntry sf in this.Ontology.Data.Relations.ClassType.SelectEntriesBySubject(this.OntologyFact).Where(te => !te.IsInference())) { result.Add((false, (RDFOntologyClass)sf.TaxonomyObject)); } //Inference-enabled discovery of class types if (enableInference) { //Skip already enlisted classes and also reserved/literal-compatible classes var availableclasses = this.Ontology.Model.ClassModel.Where(cls => !result.Any(res => res.Item2.Equals(cls)) && !RDFOntologyChecker.CheckReservedClass(cls) && !RDFOntologyHelper.CheckIsLiteralCompatibleClass(this.Ontology.Model.ClassModel, cls)); var membersCache = new Dictionary <long, RDFOntologyData>(); //Evaluate enumerations foreach (var e in availableclasses.Where(cls => cls.IsEnumerateClass())) { if (!membersCache.ContainsKey(e.PatternMemberID)) { membersCache.Add(e.PatternMemberID, this.Ontology.GetMembersOfEnumerate((RDFOntologyEnumerateClass)e)); } if (membersCache[e.PatternMemberID].Facts.ContainsKey(this.OntologyFact.PatternMemberID)) { result.Add((true, e)); } } //Evaluate restrictions foreach (var r in availableclasses.Where(cls => cls.IsRestrictionClass())) { if (!membersCache.ContainsKey(r.PatternMemberID)) { membersCache.Add(r.PatternMemberID, this.Ontology.GetMembersOfRestriction((RDFOntologyRestriction)r)); } if (membersCache[r.PatternMemberID].Facts.ContainsKey(this.OntologyFact.PatternMemberID)) { result.Add((true, r)); } } //Evaluate simple classes foreach (var c in availableclasses.Where(cls => cls.IsSimpleClass())) { if (!membersCache.ContainsKey(c.PatternMemberID)) { membersCache.Add(c.PatternMemberID, this.Ontology.GetMembersOfClass(c)); } if (membersCache[c.PatternMemberID].Facts.ContainsKey(this.OntologyFact.PatternMemberID)) { result.Add((true, c)); } } //Evaluate composite classes foreach (var c in availableclasses.Where(cls => cls.IsCompositeClass())) { if (!membersCache.ContainsKey(c.PatternMemberID)) { membersCache.Add(c.PatternMemberID, this.Ontology.GetMembersOfComposite(c, membersCache)); } if (membersCache[c.PatternMemberID].Facts.ContainsKey(this.OntologyFact.PatternMemberID)) { result.Add((true, c)); } } } return(result); }