/// <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>
        /// SameAsTransitivity implements structural entailments based on 'owl:sameAs' taxonomy:
        /// ((F1 SAMEAS F2) AND (F2 SAMEAS F3)) => (F1 SAMEAS F3)
        /// </summary>
        internal static RDFOntologyReasonerReport SameAsTransitivityExec(RDFOntology ontology)
        {
            var report = new RDFOntologyReasonerReport();
            var sameAs = RDFVocabulary.OWL.SAME_AS.ToRDFOntologyObjectProperty();

            foreach (var f      in ontology.Data)
            {
                //Enlist the same facts of the current fact
                var samefacts = ontology.Data.GetSameFactsAs(f);
                foreach (var sf in samefacts)
                {
                    //Create the inference as a taxonomy entry
                    var sem_infA = new RDFOntologyTaxonomyEntry(f, sameAs, sf).SetInference(RDFSemanticsEnums.RDFOntologyInferenceType.Reasoner);
                    var sem_infB = new RDFOntologyTaxonomyEntry(sf, sameAs, f).SetInference(RDFSemanticsEnums.RDFOntologyInferenceType.Reasoner);

                    //Add the inference to the ontology and to the report
                    if (ontology.Data.Relations.SameAs.AddEntry(sem_infA))
                    {
                        report.AddEvidence(new RDFOntologyReasonerEvidence(RDFSemanticsEnums.RDFOntologyReasonerEvidenceCategory.Data, "SameAsTransitivity", sem_infA));
                    }
                    if (ontology.Data.Relations.SameAs.AddEntry(sem_infB))
                    {
                        report.AddEvidence(new RDFOntologyReasonerEvidence(RDFSemanticsEnums.RDFOntologyReasonerEvidenceCategory.Data, "SameAsTransitivity", sem_infB));
                    }
                }
            }
            return(report);
        }
        /// <summary>
        /// DifferentFromEntailment implements structural entailments based on 'owl:DifferentFrom' taxonomy:
        /// ((F1 SAMEAS F2)        AND (F2 DIFFERENTFROM F3)) => (F1 DIFFERENTFROM F3)
        /// ((F1 DIFFERENTFROM F2) AND (F2 SAMEAS F3))        => (F1 DIFFERENTFROM F3)
        /// </summary>
        internal static RDFOntologyReasonerReport DifferentFromEntailmentExec(RDFOntology ontology)
        {
            var report        = new RDFOntologyReasonerReport();
            var differentFrom = RDFVocabulary.OWL.DIFFERENT_FROM.ToRDFOntologyObjectProperty();

            foreach (var f      in ontology.Data)
            {
                //Enlist the different facts of the current fact
                var differfacts = ontology.Data.GetDifferentFactsFrom(f);
                foreach (var df in differfacts)
                {
                    //Create the inference as a taxonomy entry
                    var sem_infA = new RDFOntologyTaxonomyEntry(f, differentFrom, df).SetInference(RDFSemanticsEnums.RDFOntologyInferenceType.Reasoner);
                    var sem_infB = new RDFOntologyTaxonomyEntry(df, differentFrom, f).SetInference(RDFSemanticsEnums.RDFOntologyInferenceType.Reasoner);

                    //Add the inference to the ontology and to the report
                    if (ontology.Data.Relations.DifferentFrom.AddEntry(sem_infA))
                    {
                        report.AddEvidence(new RDFOntologyReasonerEvidence(RDFSemanticsEnums.RDFOntologyReasonerEvidenceCategory.Data, "DifferentFromEntailment", sem_infA));
                    }
                    if (ontology.Data.Relations.DifferentFrom.AddEntry(sem_infB))
                    {
                        report.AddEvidence(new RDFOntologyReasonerEvidence(RDFSemanticsEnums.RDFOntologyReasonerEvidenceCategory.Data, "DifferentFromEntailment", sem_infB));
                    }
                }
            }
            return(report);
        }
        /// <summary>
        /// DisjointWithEntailment implements structural entailments based on 'owl:DisjointWith' taxonomy:
        /// ((C1 EQUIVALENTCLASS C2) AND (C2 DISJOINTWITH C3))    => (C1 DISJOINTWITH C3)
        /// ((C1 SUBCLASSOF C2)      AND (C2 DISJOINTWITH C3))    => (C1 DISJOINTWITH C3)
        /// ((C1 DISJOINTWITH C2)    AND (C2 EQUIVALENTCLASS C3)) => (C1 DISJOINTWITH C3)
        /// </summary>
        internal static RDFOntologyReasonerReport DisjointWithEntailmentExec(RDFOntology ontology)
        {
            var report       = new RDFOntologyReasonerReport();
            var disjointWith = RDFVocabulary.OWL.DISJOINT_WITH.ToRDFOntologyObjectProperty();

            foreach (var c       in ontology.Model.ClassModel)
            {
                //Enlist the disjoint classes of the current class
                var disjclasses = ontology.Model.ClassModel.GetDisjointClassesWith(c);
                foreach (var dwc in disjclasses)
                {
                    //Create the inference as a taxonomy entry
                    var sem_infA = new RDFOntologyTaxonomyEntry(c, disjointWith, dwc).SetInference(RDFSemanticsEnums.RDFOntologyInferenceType.Reasoner);
                    var sem_infB = new RDFOntologyTaxonomyEntry(dwc, disjointWith, c).SetInference(RDFSemanticsEnums.RDFOntologyInferenceType.Reasoner);

                    //Add the inference to the ontology and to the report
                    if (ontology.Model.ClassModel.Relations.DisjointWith.AddEntry(sem_infA))
                    {
                        report.AddEvidence(new RDFOntologyReasonerEvidence(RDFSemanticsEnums.RDFOntologyReasonerEvidenceCategory.ClassModel, "DisjointWithEntailment", sem_infA));
                    }
                    if (ontology.Model.ClassModel.Relations.DisjointWith.AddEntry(sem_infB))
                    {
                        report.AddEvidence(new RDFOntologyReasonerEvidence(RDFSemanticsEnums.RDFOntologyReasonerEvidenceCategory.ClassModel, "DisjointWithEntailment", sem_infB));
                    }
                }
            }
            return(report);
        }
        /// <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>
        /// EquivalentClassTransitivity implements structural entailments based on 'owl:EquivalentClass' taxonomy:
        /// ((C1 EQUIVALENTCLASS C2) AND (C2 EQUIVALENTCLASS C3)) => (C1 EQUIVALENTCLASS C3)
        /// </summary>
        internal static RDFOntologyReasonerReport EquivalentClassTransitivityExec(RDFOntology ontology)
        {
            var report          = new RDFOntologyReasonerReport();
            var equivalentClass = RDFVocabulary.OWL.EQUIVALENT_CLASS.ToRDFOntologyObjectProperty();

            foreach (var c      in ontology.Model.ClassModel)
            {
                //Enlist the equivalent classes of the current class
                var equivclasses = ontology.Model.ClassModel.GetEquivalentClassesOf(c);
                foreach (var ec in equivclasses)
                {
                    //Create the inference as a taxonomy entry
                    var sem_infA = new RDFOntologyTaxonomyEntry(c, equivalentClass, ec).SetInference(RDFSemanticsEnums.RDFOntologyInferenceType.Reasoner);
                    var sem_infB = new RDFOntologyTaxonomyEntry(ec, equivalentClass, c).SetInference(RDFSemanticsEnums.RDFOntologyInferenceType.Reasoner);

                    //Add the inference to the ontology and to the report
                    if (ontology.Model.ClassModel.Relations.EquivalentClass.AddEntry(sem_infA))
                    {
                        report.AddEvidence(new RDFOntologyReasonerEvidence(RDFSemanticsEnums.RDFOntologyReasonerEvidenceCategory.ClassModel, "EquivalentClassTransitivity", sem_infA));
                    }
                    if (ontology.Model.ClassModel.Relations.EquivalentClass.AddEntry(sem_infB))
                    {
                        report.AddEvidence(new RDFOntologyReasonerEvidence(RDFSemanticsEnums.RDFOntologyReasonerEvidenceCategory.ClassModel, "EquivalentClassTransitivity", sem_infB));
                    }
                }
            }
            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>
 /// Merges the evidences of the given report
 /// </summary>
 internal void Merge(RDFOntologyReasonerReport report)
 {
     foreach (var evidence in report)
     {
         this.AddEvidence(evidence);
     }
 }
        /// <summary>
        /// SameAsEntailment implements data entailments based on 'owl:sameAs' taxonomy:
        /// ((F1 P F2) AND (F1 SAMEAS F3)) => (F3 P F2)
        /// ((F1 P F2) AND (F2 SAMEAS F3)) => (F1 P F3)
        /// </summary>
        internal static RDFOntologyReasonerReport SameAsEntailmentExec(RDFOntology ontology)
        {
            var report = new RDFOntologyReasonerReport();

            foreach (var f1             in ontology.Data)
            {
                //Enlist the same facts of the current fact
                var sameFacts = ontology.Data.GetSameFactsAs(f1);
                if (sameFacts.FactsCount > 0)
                {
                    //Filter the assertions using the current fact
                    var f1AsnsSubj = ontology.Data.Relations.Assertions.SelectEntriesBySubject(f1);
                    var f1AsnsObj  = ontology.Data.Relations.Assertions.SelectEntriesByObject(f1);

                    //Enlist the same facts of the current fact
                    foreach (var f2     in sameFacts)
                    {
                        #region Subject-Side
                        //Iterate the assertions having the current fact as subject
                        foreach (var f1Asn  in f1AsnsSubj)
                        {
                            //Taxonomy-check for securing inference consistency
                            if (f1Asn.TaxonomyPredicate.IsObjectProperty() && f1Asn.TaxonomyObject.IsFact())
                            {
                                //Create the inference as a taxonomy entry
                                var sem_infA = new RDFOntologyTaxonomyEntry(f2, f1Asn.TaxonomyPredicate, f1Asn.TaxonomyObject).SetInference(RDFSemanticsEnums.RDFOntologyInferenceType.Reasoner);

                                //Add the inference to the ontology and to the report
                                if (ontology.Data.Relations.Assertions.AddEntry(sem_infA))
                                {
                                    report.AddEvidence(new RDFOntologyReasonerEvidence(RDFSemanticsEnums.RDFOntologyReasonerEvidenceCategory.Data, "SameAsEntailment", sem_infA));
                                }
                            }
                        }
                        #endregion

                        #region Object-Side
                        //Iterate the assertions having the current fact as object
                        foreach (var f1Asn  in f1AsnsObj)
                        {
                            //Taxonomy-check for securing inference consistency
                            if (f1Asn.TaxonomyPredicate.IsObjectProperty() && f2.IsFact())
                            {
                                //Create the inference as a taxonomy entry
                                var sem_infB = new RDFOntologyTaxonomyEntry(f1Asn.TaxonomySubject, f1Asn.TaxonomyPredicate, f2).SetInference(RDFSemanticsEnums.RDFOntologyInferenceType.Reasoner);

                                //Add the inference to the ontology and to the report
                                if (ontology.Data.Relations.Assertions.AddEntry(sem_infB))
                                {
                                    report.AddEvidence(new RDFOntologyReasonerEvidence(RDFSemanticsEnums.RDFOntologyReasonerEvidenceCategory.Data, "SameAsEntailment", sem_infB));
                                }
                            }
                        }
                        #endregion
                    }
                }
            }
            return(report);
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Applies the reasoner on the given ontology, producing a reasoning report.
        /// </summary>
        public RDFOntologyReasonerReport ApplyToOntology(ref RDFOntology ontology)
        {
            var report = new RDFOntologyReasonerReport();

            if (ontology != null)
            {
                RDFSemanticsEvents.RaiseSemanticsInfo(String.Format("Reasoner is going to be applied on Ontology '{0}'...", ontology.Value));

                //STEP 1: Expand ontology
                var ontologyValue = ontology.Value;
                ontology = ontology.UnionWith(RDFBASEOntology.Instance);

                //STEP 2: Execute BASE rules
                #region BASE rules
                var baseRules = this.Rules.Where(x => x.RulePriority <= RDFOntologyReasonerRuleset.RulesCount)
                                .OrderBy(x => x.RulePriority);
                foreach (var bRule in baseRules)
                {
                    RDFSemanticsEvents.RaiseSemanticsInfo(String.Format("Launching execution of BASE reasoning rule '{0}'...", bRule));
                    var bRuleReport = bRule.ExecuteRule(ontology);
                    report.Merge(bRuleReport);
                    RDFSemanticsEvents.RaiseSemanticsInfo(String.Format("Completed execution of BASE reasoning rule '{0}': found {1} evidences.", bRule, bRuleReport.EvidencesCount));
                }
                #endregion

                //STEP 3: Execute custom rules
                #region Custom rules
                var customRules = this.Rules.Where(x => x.RulePriority > RDFOntologyReasonerRuleset.RulesCount)
                                  .OrderBy(x => x.RulePriority);
                foreach (var cRule in customRules)
                {
                    RDFSemanticsEvents.RaiseSemanticsInfo(String.Format("Launching execution of reasoning rule '{0}'...", cRule));
                    var cRuleReport = cRule.ExecuteRule(ontology);
                    report.Merge(cRuleReport);
                    RDFSemanticsEvents.RaiseSemanticsInfo(String.Format("Completed execution of reasoning rule '{0}': found {1} evidences.", cRule, cRuleReport.EvidencesCount));
                }
                #endregion

                //STEP 4: Unexpand ontology
                ontology       = ontology.DifferenceWith(RDFBASEOntology.Instance);
                ontology.Value = ontologyValue;

                RDFSemanticsEvents.RaiseSemanticsInfo(String.Format("Reasoner has been applied on Ontology '{0}': found " + report.EvidencesCount + " evidences.", ontology.Value));
            }
            return(report);
        }
        /// <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>
        /// SubClassTransitivity (rdfs11) implements structural entailments based on 'rdfs:subClassOf' taxonomy:
        /// ((C1 SUBCLASSOF C2)      AND (C2 SUBCLASSOF C3))      => (C1 SUBCLASSOF C3);
        /// ((C1 SUBCLASSOF C2)      AND (C2 EQUIVALENTCLASS C3)) => (C1 SUBCLASSOF C3);
        /// ((C1 EQUIVALENTCLASS C2) AND (C2 SUBCLASSOF C3))      => (C1 SUBCLASSOF C3)
        /// </summary>
        internal static RDFOntologyReasonerReport SubClassTransitivityExec(RDFOntology ontology)
        {
            var report     = new RDFOntologyReasonerReport();
            var subClassOf = RDFVocabulary.RDFS.SUB_CLASS_OF.ToRDFOntologyObjectProperty();

            foreach (var c      in ontology.Model.ClassModel)
            {
                //Enlist the superclasses of the current class
                var superclasses = ontology.Model.ClassModel.GetSuperClassesOf(c);
                foreach (var sc in superclasses)
                {
                    //Create the inference as a taxonomy entry
                    var sem_inf = new RDFOntologyTaxonomyEntry(c, subClassOf, sc).SetInference(RDFSemanticsEnums.RDFOntologyInferenceType.Reasoner);

                    //Add the inference to the ontology and to the report
                    if (ontology.Model.ClassModel.Relations.SubClassOf.AddEntry(sem_inf))
                    {
                        report.AddEvidence(new RDFOntologyReasonerEvidence(RDFSemanticsEnums.RDFOntologyReasonerEvidenceCategory.ClassModel, "SubClassTransitivity", sem_inf));
                    }
                }
            }
            return(report);
        }