/// <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> /// 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> /// 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); }