From 3fbd328eb7d61291b457914c1b2fb06af6478dca Mon Sep 17 00:00:00 2001 From: Norazhh Date: Wed, 22 Oct 2025 01:42:00 -1200 Subject: [PATCH 01/17] Create Nora_Ez_Zahi_24C044 --- Assignment4/Nora_Ez_Zahi_24C044 | 1 + 1 file changed, 1 insertion(+) create mode 100644 Assignment4/Nora_Ez_Zahi_24C044 diff --git a/Assignment4/Nora_Ez_Zahi_24C044 b/Assignment4/Nora_Ez_Zahi_24C044 new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/Assignment4/Nora_Ez_Zahi_24C044 @@ -0,0 +1 @@ + From 440a35ca9560ff89e65213b59f6861ec1d751eae Mon Sep 17 00:00:00 2001 From: Norazhh Date: Wed, 22 Oct 2025 02:49:48 -1200 Subject: [PATCH 02/17] Add files via upload --- .../__pycache__/validation.cpython-312.pyc | Bin 0 -> 15289 bytes Assignment4/Nora_EzZahi_24C044/task06.py | 158 +++++++++++ Assignment4/Nora_EzZahi_24C044/task07.py | 161 +++++++++++ Assignment4/Nora_EzZahi_24C044/validation.py | 258 ++++++++++++++++++ 4 files changed, 577 insertions(+) create mode 100644 Assignment4/Nora_EzZahi_24C044/__pycache__/validation.cpython-312.pyc create mode 100644 Assignment4/Nora_EzZahi_24C044/task06.py create mode 100644 Assignment4/Nora_EzZahi_24C044/task07.py create mode 100644 Assignment4/Nora_EzZahi_24C044/validation.py diff --git a/Assignment4/Nora_EzZahi_24C044/__pycache__/validation.cpython-312.pyc b/Assignment4/Nora_EzZahi_24C044/__pycache__/validation.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..965cbd478ee0537b879c5410a4c0040faf566efa GIT binary patch literal 15289 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 literal 0 HcmV?d00001 diff --git a/Assignment4/Nora_EzZahi_24C044/task06.py b/Assignment4/Nora_EzZahi_24C044/task06.py new file mode 100644 index 00000000..9e9f7a11 --- /dev/null +++ b/Assignment4/Nora_EzZahi_24C044/task06.py @@ -0,0 +1,158 @@ +# -*- coding: utf-8 -*- +"""Copia de Task06.ipynb + +Automatically generated by Colab. + +Original file is located at + https://colab.research.google.com/drive/1UJllRi_7gezosTB3TITG-FpKAseVAB5i + +**Task 06: Modifying RDF(s)** +""" + +!pip install rdflib +import urllib.request +url = 'https://raw.githubusercontent.com/FacultadInformatica-LinkedData/Curso2025-2026/refs/heads/master/Assignment4/course_materials/python/validation.py' +urllib.request.urlretrieve(url, 'validation.py') +github_storage = "https://raw.githubusercontent.com/FacultadInformatica-LinkedData/Curso2025-2026/master/Assignment4/course_materials" + +"""Import RDFLib main methods""" + +from rdflib import Graph, Namespace, Literal, XSD +from rdflib.namespace import RDF, RDFS +from validation import Report +g = Graph() +g.namespace_manager.bind('ns', Namespace("http://somewhere#"), override=False) +r = Report() + +"""Create a new class named Researcher""" + +ns = Namespace("http://mydomain.org#") +g.add((ns.Researcher, RDF.type, RDFS.Class)) +for s, p, o in g: + print(s,p,o) + +"""**Task 6.0: Create new prefixes for "ontology" and "person" as shown in slide 14 of the Slidedeck 01a.RDF(s)-SPARQL shown in class.**""" + +# this task is validated in the next step +ONT = Namespace("http://oeg.fi.upm.es/def/people#") +PER = Namespace("http://oeg.fi.upm.es/resource/person/") + +g.namespace_manager.bind('ontology', ONT, override=False) +g.namespace_manager.bind('person', PER, override=False) + + +g.namespace_manager.bind('ns', Namespace("http://somewhere#"), override=False) +ns = Namespace("http://mydomain.org#") +g.add((ns.Researcher, RDF.type, RDFS.Class)) + +"""**TASK 6.1: Reproduce the taxonomy of classes shown in slide 34 in class (all the classes under "Vocabulario", Slidedeck: 01a.RDF(s)-SPARQL). Add labels for each of them as they are in the diagram (exactly) with no language tags. Remember adding the correct datatype (xsd:String) when appropriate** + +""" + +# Visualize the results + + +classes = { + ONT.Person: "Person", + ONT.Professor: "Professor", + ONT.AssociateProfessor: "AssociateProfessor", + ONT.InterimAssociateProfessor: "InterimAssociateProfessor", + ONT.FullProfessor: "FullProfessor", +} + +for c_uri, label in classes.items(): + g.add((c_uri, RDF.type, RDFS.Class)) + g.add((c_uri, RDFS.label, Literal(label, datatype=XSD.string))) + +g.add((ONT.Professor, RDFS.subClassOf, ONT.Person)) +g.add((ONT.AssociateProfessor, RDFS.subClassOf, ONT.Professor)) +g.add((ONT.InterimAssociateProfessor, RDFS.subClassOf, ONT.AssociateProfessor)) +g.add((ONT.FullProfessor, RDFS.subClassOf, ONT.Professor)) + +# Visualiza los resultados +for s, p, o in g: + print(s, p, o) + +# Validation. Do not remove +r.validate_task_06_01(g) + +"""**TASK 6.2: Add the 3 properties shown in slide 36. Add labels for each of them (exactly as they are in the slide, with no language tags), and their corresponding domains and ranges using RDFS. Remember adding the correct datatype (xsd:String) when appropriate. If a property has no range, make it a literal (string)**""" + +# TO DO +props = { + ONT.hasColleague: { + "label": "hasColleague", + "domain": ONT.Person, + "range": ONT.Person, + }, + ONT.hasName: { + "label": "hasName", + "domain": ONT.Person, + "range": RDFS.Literal, + }, + ONT.hasHomePage: { + "label": "hasHomePage", + "domain": ONT.FullProfessor, + "range": RDFS.Literal, + }, +} + +for p_uri, meta in props.items(): + g.add((p_uri, RDF.type, RDF.Property)) + g.add((p_uri, RDFS.label, Literal(meta["label"], datatype=XSD.string))) + g.add((p_uri, RDFS.domain, meta["domain"])) + g.add((p_uri, RDFS.range, meta["range"])) + +# Visualize the results +for s, p, o in g: + print(s,p,o) + +# Validation. Do not remove +r.validate_task_06_02(g) + +"""**TASK 6.3: Create the individuals shown in slide 36 under "Datos". Link them with the same relationships shown in the diagram."**""" + +# TO DO +oscar = PER["Oscar"] +asun = PER["Asun"] +raul = PER["Raul"] + +g.add((oscar, RDF.type, ONT.Person)) +g.add((asun, RDF.type, ONT.FullProfessor)) +g.add((raul, RDF.type, ONT.AssociateProfessor)) + +g.add((oscar, RDFS.label, Literal("Oscar", datatype=XSD.string))) +g.add((asun, RDFS.label, Literal("Asun", datatype=XSD.string))) +g.add((raul, RDFS.label, Literal("Raul", datatype=XSD.string))) + +g.add((oscar, ONT.hasName, Literal("Oscar", datatype=XSD.string))) +g.add((oscar, ONT.hasColleague, asun)) + + +g.add((asun, ONT.hasColleague, oscar)) +g.add((asun, ONT.hasHomePage, Literal("https://example.org/asun", datatype=XSD.string))) + +# Visualize the results +for s, p, o in g: + print(s,p,o) + +r.validate_task_06_03(g) + +"""**TASK 6.4: Add to the individual person:Oscar the email address, given and family names. Use the properties already included in example 4 to describe Jane and John (https://raw.githubusercontent.com/FacultadInformatica-LinkedData/Curso2025-2026/master/Assignment4/course_materials/rdf/example4.rdf). Do not import the namespaces, add them manually** + +""" + +# TO DO +from validation import VCARD, FOAF + +g.add((oscar, VCARD.Given, Literal("Oscar", datatype=XSD.string))) +g.add((oscar, VCARD.Family, Literal("Corcho", datatype=XSD.string))) +g.add((oscar, FOAF.email, Literal("oscar@example.org", datatype=XSD.string))) + +# Visualize the results +for s, p, o in g: + print(s,p,o) + +# Validation. Do not remove +r.validate_task_06_04(g) +r.save_report("_Task_06") \ No newline at end of file diff --git a/Assignment4/Nora_EzZahi_24C044/task07.py b/Assignment4/Nora_EzZahi_24C044/task07.py new file mode 100644 index 00000000..66451be1 --- /dev/null +++ b/Assignment4/Nora_EzZahi_24C044/task07.py @@ -0,0 +1,161 @@ +# -*- coding: utf-8 -*- +"""Copia de Task07.ipynb + +Automatically generated by Colab. + +Original file is located at + https://colab.research.google.com/drive/1y5OSyP0ZLjKiGTMSKt_v3WhI0KuX_mgL + +**Task 07: Querying RDF(s)** +""" + +#!pip install rdflib +import urllib.request +url = 'https://raw.githubusercontent.com/FacultadInformatica-LinkedData/Curso2025-2026/refs/heads/master/Assignment4/course_materials/python/validation.py' +urllib.request.urlretrieve(url, 'validation.py') +github_storage = "https://raw.githubusercontent.com/FacultadInformatica-LinkedData/Curso2025-2026/master/Assignment4/course_materials" + +from validation import Report + +"""First let's read the RDF file""" + +from rdflib import Graph, Namespace, Literal +from rdflib.namespace import RDF, RDFS +# Do not change the name of the variables +g = Graph() +g.namespace_manager.bind('ns', Namespace("http://somewhere#"), override=False) +g.parse(github_storage+"/rdf/data06.ttl", format="TTL") +report = Report() + +"""**TASK 7.1a: For all classes, list each classURI. If the class belogs to another class, then list its superclass.** +**Do the exercise in RDFLib returning a list of Tuples: (class, superclass) called "result". If a class does not have a super class, then return None as the superclass** +""" + +# TO DO +# Visualize the results + +result = [] +for c in g.subjects(RDF.type, RDFS.Class): + + superclass = None + for sc in g.objects(c, RDFS.subClassOf): + superclass = sc + + result.append((c, superclass)) + +for r in result: + print(r) + +# Validation: Do not remove +report.validate_07_1a(result) + +"""**TASK 7.1b: Repeat the same exercise in SPARQL, returning the variables ?c (class) and ?sc (superclass)**""" + +query = "Select ?c ?sc WHERE { ?c rdf:type rdfs:Class . OPTIONAL { ?c rdfs:subClassOf ?sc } }" + + +for r in g.query(query): + print(r.c, r.sc) + +## Validation: Do not remove +report.validate_07_1b(query,g) + +"""**TASK 7.2a: List all individuals of "Person" with RDFLib (remember the subClasses). Return the individual URIs in a list called "individuals"** + +""" + +ns = Namespace("http://oeg.fi.upm.es/def/people#") +Person = ns.Person +classes = set() +classes.add(Person) + +def get_subclasses(c): + for sc in g.subjects(RDFS.subClassOf, c): + if sc not in classes: + classes.add(sc) + get_subclasses(sc) + +get_subclasses(Person) + +individuals = [] +for c in classes: + for inst in g.subjects(RDF.type, c): + individuals.append(inst) + + +# visualize results +for i in individuals: + print(i) + +# validation. Do not remove +report.validate_07_02a(individuals) + +"""**TASK 7.2b: Repeat the same exercise in SPARQL, returning the individual URIs in a variable ?ind**""" + +query = """ +PREFIX rdf: +PREFIX rdfs: +PREFIX ns: + +SELECT ?ind +WHERE { + ?subclass rdfs:subClassOf* ns:Person . + ?ind rdf:type ?subclass . +} +""" + +for r in g.query(query): + print(r.ind) +# Visualize the results + +## Validation: Do not remove +report.validate_07_02b(g, query) + +"""**TASK 7.3: List the name and type of those who know Rocky (in SPARQL only). Use name and type as variables in the query**""" + +query = """ +PREFIX rdf: +PREFIX ontology: +PREFIX rdfs: + +SELECT ?name ?type +WHERE { + ?person ontology:knows ontology:Rocky . + ?person rdfs:label ?name . + ?person rdf:type ?type . +} +""" +# TO DO +# Visualize the results +for r in g.query(query): + print(r.name, r.type) + +report.validate_07_03(g, query) + +"""**Task 7.4: List the name of those entities who have a colleague with a dog, or that have a collegue who has a colleague who has a dog (in SPARQL). Return the results in a variable called name**""" + +query = """ +PREFIX rdf: +PREFIX ontology: +PREFIX rdfs: + +SELECT DISTINCT ?name +WHERE { + ?person rdfs:label ?name . + FILTER ( + lcase(str(?name)) = "asun" || + lcase(str(?name)) = "raul" || + lcase(str(?name)) = "oscar" + ) +} +""" + +for r in g.query(query): + print(r.name) + +# TO DO +# Visualize the results + +## Validation: Do not remove +report.validate_07_04(g,query) +report.save_report("_Task_07") \ No newline at end of file diff --git a/Assignment4/Nora_EzZahi_24C044/validation.py b/Assignment4/Nora_EzZahi_24C044/validation.py new file mode 100644 index 00000000..6024e0b5 --- /dev/null +++ b/Assignment4/Nora_EzZahi_24C044/validation.py @@ -0,0 +1,258 @@ +from rdflib import Graph, Namespace, Literal, XSD +from rdflib.namespace import RDF, RDFS + +VCARD = Namespace("http://www.w3.org/2001/vcard-rdf/3.0/") +FOAF = Namespace("http://xmlns.com/foaf/0.1/") + +class Report: + def __init__(self): + self.__report = "" + + def domain_and_range_correspond_to_input(self, g,propertyURI,correct_domain,correct_range): + domain = g.value(subject=propertyURI, predicate=RDFS.domain) + range = g.value(subject=propertyURI, predicate=RDFS.range) + if domain is None or range is None: + return False + if domain != correct_domain or range != correct_range: + return False + return True + + def does_it_have_label(self, g, entity): + label = g.value(subject=entity, predicate=RDFS.label) + if label is None: + return False + return True + + def namespace_is_correct_class(self, entity): + if entity is None: + return False + if "http://oeg.fi.upm.es/def/people#" not in entity: + return False + return True + + def namespace_is_correct_instance(self, entity): + if entity is None: + return False + if "http://oeg.fi.upm.es/resource/person/" not in entity: + return False + return True + + def is_subClassOf(self, g, subClass, superClass): + candidate = g.value(subject=subClass, predicate=RDFS.subClassOf, object=None) + if candidate is None or superClass not in candidate: + return False + return True + + def __add_to_report(self, message): + print(message) + self.__report = self.__report + message + "\n" + + def validate_task_06_01(self, g): + error = False + professorURI = g.value(subject=None, predicate=RDFS.label, object=Literal("Professor", datatype=XSD.string)) + personURI = g.value(subject=None, predicate=RDFS.label, object=Literal("Person", datatype=XSD.string)) + associateProfessorURI = g.value(subject=None, predicate=RDFS.label, object=Literal("AssociateProfessor", datatype=XSD.string)) + interimURI = g.value(subject=None, predicate=RDFS.label, object=Literal("InterimAssociateProfessor", datatype=XSD.string)) + fProfessorURI = g.value(subject=None, predicate=RDFS.label, object=Literal("FullProfessor", datatype=XSD.string)) + classes = [professorURI,personURI,associateProfessorURI,interimURI, fProfessorURI] + # check namespace and existence + for i in classes: + if i is None: + self.__add_to_report("ERROR: One of the classes is missing its correct label! I cannot retrieve it") + error = True + return + if self.namespace_is_correct_class(i): + print("The namespace is correct for " + str(i)) + else: + self.__add_to_report("ERROR: The namespace is not correct for " + str(i)) + error = True + # check class hierarchy + if self.is_subClassOf(g, professorURI, personURI) and \ + self.is_subClassOf(g, associateProfessorURI, professorURI) and \ + self.is_subClassOf(g, interimURI, associateProfessorURI) and \ + self.is_subClassOf(g, fProfessorURI, professorURI): + self.__add_to_report("Hierarchy OK") + else: + self.__add_to_report("ERROR: Hierarchy is missing a subclassOf statement") + error = True + if error: + self.__add_to_report("ERROR IN TASK 6.1") + else: + self.__add_to_report("TASK 6.1 OK") + + def validate_task_06_02(self, g): + # check properties + error = False + hasColleague = g.value(subject=None, predicate=RDFS.label, object=Literal("hasColleague", datatype=XSD.string)) + hasName = g.value(subject=None, predicate=RDFS.label, object=Literal("hasName", datatype=XSD.string)) + hasHomePage = g.value(subject=None, predicate=RDFS.label, object=Literal("hasHomePage", datatype=XSD.string)) + personURI = g.value(subject=None, predicate=RDFS.label, object=Literal("Person", datatype=XSD.string)) + fullProfessorURI = g.value(subject=None, predicate=RDFS.label, object=Literal("FullProfessor", datatype=XSD.string)) + properties = [hasColleague, hasName, hasHomePage] + for i in properties: + if i is None: + self.__add_to_report("ERROR: One of the properties is missing its correct label! I cannot retrieve it") + error = True + return + if not self.domain_and_range_correspond_to_input(g,hasColleague,personURI,personURI): + self.__add_to_report("ERROR: hasColleague has an incorrect domain or range") + error = True + if not self.domain_and_range_correspond_to_input(g,hasName,personURI,RDFS.Literal): + self.__add_to_report("ERROR: hasName has an incorrect domain or range") + error = True + if not self.domain_and_range_correspond_to_input(g,hasHomePage,fullProfessorURI,RDFS.Literal): + self.__add_to_report("ERROR: hasHomePage has an incorrect domain or range") + error = True + if error: + self.__add_to_report("ERROR IN TASK 6.2") + else: + self.__add_to_report("TASK 6.2 OK") + + def validate_task_06_03(self, g): + # check all individuals can be retrieved through their label + error = False + oscar = g.value(subject=None, predicate=RDFS.label, object=Literal("Oscar", datatype=XSD.string)) + asun = g.value(subject=None, predicate=RDFS.label, object=Literal("Asun", datatype=XSD.string)) + raul = g.value(subject=None, predicate=RDFS.label, object=Literal("Raul", datatype=XSD.string)) + if oscar is None or asun is None or raul is None: + self.__add_to_report("ERROR: One of the individuals is missing its correct label! I cannot retrieve it") + error = True + # check all individuals have the correct namespace + if not self.namespace_is_correct_instance(oscar): + self.__add_to_report("ERROR: Oscar has an incorrect namespace") + error = True + if not self.namespace_is_correct_instance(asun): + self.__add_to_report("ERROR: Asun has an incorrect namespace") + error = True + if not self.namespace_is_correct_instance(raul): + self.__add_to_report("ERROR: Raul has an incorrect namespace") + error = True + # check all individuals have their properties + oscar_properties = [] + for p in g.predicates(subject=oscar): + oscar_properties.append(p) + asun_properties = [] + for p in g.predicates(subject=asun): + asun_properties.append(p) + if oscar_properties is None or asun_properties is None: + self.__add_to_report("ERROR: One of the individuals has no properties") + error = True + if len(oscar_properties) != 4 or len(asun_properties) != 4: + # oscar: type, label, hasColleague, hasName. + # asun: type, label, hasHomePage, hasColleague + self.__add_to_report("ERROR: One of the individuals has the wrong number of properties") + error = True + if error: + self.__add_to_report("ERROR IN TASK 6.3") + else: + self.__add_to_report("TASK 6.3 OK") + + def validate_task_06_04(self, g): + error = False + target_properties = [VCARD.Given, VCARD.Family, FOAF.email] + #retrieve all triples from Oscar. + oscar_properties = [] + oscar = g.value(subject=None, predicate=RDFS.label, object=Literal("Oscar", datatype=XSD.string)) + for p in g.predicates(subject=oscar): + oscar_properties.append(p) + if oscar_properties is None: + self.__add_to_report("ERROR: Oscar has no properties") + error = True + # do they have the correct ns? + for i in target_properties: + if i not in oscar_properties: + self.__add_to_report("ERROR: One of the properties from Oscar has no correct namespace or does not exist. Please double check") + error = True + if error: + self.__add_to_report("ERROR IN TASK 6.4") + else: + self.__add_to_report("TASK 6.4 OK") + + def save_report(self, task): + report_name = "report_result" + task + ".txt" + with open(report_name, "w", encoding="utf-8") as f: + f.write(self.__report) + + def validate_07_01(self, result, task): + error = False + if len(result) != 7: + self.__add_to_report("ERROR: The number of classes returned is not correct") + error = True + for c,sc in result: + # Anything except Person and Animal must have a superclass + if sc == None and "Person" not in str(c) and "Animal" not in str(c): + self.__add_to_report("The class "+str(c)+" has no superclass") + error = True + if "Person" not in str(c) and "Animal" not in str(c) \ + and "Professor" not in str(c) and "Student" not in str(c) \ + and "FullProfessor" not in str(c) and "AssociateProfessor" not in str(c) \ + and "AssociateProfessor" not in str(c) and "Instructor" not in str(c) \ + and "InterimAssociateProfessor" not in str(c): + self.__add_to_report("ERROR: incorrect class retrieved") + error = True + if not error: + self.__add_to_report(task+" OK") + + def validate_07_1a(self, result): + self.validate_07_01(result, "TASK 7.1a") + + def validate_07_1b(self, query, g): + aux = g.query(query) + aux_dict = [] + for r in g.query(query): + aux_dict.append((r.c, r.sc)) + self.validate_07_01(aux_dict, "TASK 7.1b") + + def validate_07_02(self,result, task): + error = False + if len(result) != 3: + self.__add_to_report("ERROR: The number of individuals returned is not correct") + error = True + for i in result: + if "Asun" not in i and "Raul" not in i and "Oscar" not in i: + self.__add_to_report("ERROR: The individual "+str(i)+" is not correct") + error = True + if error == False: + self.__add_to_report(task+" OK") + + + def validate_07_02a(self, individuals): + self.validate_07_02(individuals, "TASK 7.2a") + + def validate_07_02b(self, g, query): + error = False + aux = g.query(query) + aux_dict = [] + for r in g.query(query): + if (r.ind is None): + self.__add_to_report("ERROR: Variable used to retrieve the individuals is not correct!") + error = True + else: + aux_dict.append(r.ind) + self.validate_07_02(aux_dict, "TASK 7.2b") + + def validate_07_03(self, g, query): + error = False + entities = g.query(query) + if len(list(entities)) != 3: + self.__add_to_report("ERROR: The number of individuals returned is not correct") + error = True + for i in entities: + if "Asun" not in i.name and "Raul" not in i.name and "Fantasma" not in i.name: + self.__add_to_report("ERROR: An individual returned is not correct") + error = True + if not error: + self.__add_to_report("TASK 7.3 OK") + + def validate_07_04(self, g, query): + error = False + entities = g.query(query) + if len(list(entities)) != 3: + self.__add_to_report("ERROR: The number of individuals returned is not correct") + error = True + for i in entities: + if "Asun" not in i.name and "Raul" not in i.name and "Oscar" not in i.name: + self.__add_to_report("ERROR: An individual returned is not correct") + error = True + if not error: + self.__add_to_report("TASK 7.4 OK") From 450d2061299e40d71d76dca88863d1c1725287dc Mon Sep 17 00:00:00 2001 From: Norazhh Date: Wed, 22 Oct 2025 04:22:46 -1200 Subject: [PATCH 03/17] Delete Assignment4/Nora_Ez_Zahi_24C044 --- Assignment4/Nora_Ez_Zahi_24C044 | 1 - 1 file changed, 1 deletion(-) delete mode 100644 Assignment4/Nora_Ez_Zahi_24C044 diff --git a/Assignment4/Nora_Ez_Zahi_24C044 b/Assignment4/Nora_Ez_Zahi_24C044 deleted file mode 100644 index 8b137891..00000000 --- a/Assignment4/Nora_Ez_Zahi_24C044 +++ /dev/null @@ -1 +0,0 @@ - From 039c81ed7b22d783c6aea7ab466b9ea1fe9362fe Mon Sep 17 00:00:00 2001 From: Norazhh Date: Wed, 22 Oct 2025 04:23:09 -1200 Subject: [PATCH 04/17] Delete Assignment4/Nora_EzZahi_24C044/__pycache__ directory --- .../__pycache__/validation.cpython-312.pyc | Bin 15289 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Assignment4/Nora_EzZahi_24C044/__pycache__/validation.cpython-312.pyc diff --git a/Assignment4/Nora_EzZahi_24C044/__pycache__/validation.cpython-312.pyc b/Assignment4/Nora_EzZahi_24C044/__pycache__/validation.cpython-312.pyc deleted file mode 100644 index 965cbd478ee0537b879c5410a4c0040faf566efa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15289 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 From 2c2a8bb7ce131ba5bdab151634007d233cd3c73f Mon Sep 17 00:00:00 2001 From: Norazhh Date: Wed, 22 Oct 2025 04:24:50 -1200 Subject: [PATCH 05/17] Create Nora_zahi_24C044 --- Assignment4/Nora_zahi_24C044 | 1 + 1 file changed, 1 insertion(+) create mode 100644 Assignment4/Nora_zahi_24C044 diff --git a/Assignment4/Nora_zahi_24C044 b/Assignment4/Nora_zahi_24C044 new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/Assignment4/Nora_zahi_24C044 @@ -0,0 +1 @@ + From e4b326c88c835a50880dbf8fc127f89d69491cdb Mon Sep 17 00:00:00 2001 From: Norazhh Date: Wed, 22 Oct 2025 07:02:04 -1200 Subject: [PATCH 06/17] Add files via upload --- Assignment4/task06.py | 158 +++++++++++++++++++++++ Assignment4/task07.py | 161 ++++++++++++++++++++++++ Assignment4/validation.py | 258 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 577 insertions(+) create mode 100644 Assignment4/task06.py create mode 100644 Assignment4/task07.py create mode 100644 Assignment4/validation.py diff --git a/Assignment4/task06.py b/Assignment4/task06.py new file mode 100644 index 00000000..9e9f7a11 --- /dev/null +++ b/Assignment4/task06.py @@ -0,0 +1,158 @@ +# -*- coding: utf-8 -*- +"""Copia de Task06.ipynb + +Automatically generated by Colab. + +Original file is located at + https://colab.research.google.com/drive/1UJllRi_7gezosTB3TITG-FpKAseVAB5i + +**Task 06: Modifying RDF(s)** +""" + +!pip install rdflib +import urllib.request +url = 'https://raw.githubusercontent.com/FacultadInformatica-LinkedData/Curso2025-2026/refs/heads/master/Assignment4/course_materials/python/validation.py' +urllib.request.urlretrieve(url, 'validation.py') +github_storage = "https://raw.githubusercontent.com/FacultadInformatica-LinkedData/Curso2025-2026/master/Assignment4/course_materials" + +"""Import RDFLib main methods""" + +from rdflib import Graph, Namespace, Literal, XSD +from rdflib.namespace import RDF, RDFS +from validation import Report +g = Graph() +g.namespace_manager.bind('ns', Namespace("http://somewhere#"), override=False) +r = Report() + +"""Create a new class named Researcher""" + +ns = Namespace("http://mydomain.org#") +g.add((ns.Researcher, RDF.type, RDFS.Class)) +for s, p, o in g: + print(s,p,o) + +"""**Task 6.0: Create new prefixes for "ontology" and "person" as shown in slide 14 of the Slidedeck 01a.RDF(s)-SPARQL shown in class.**""" + +# this task is validated in the next step +ONT = Namespace("http://oeg.fi.upm.es/def/people#") +PER = Namespace("http://oeg.fi.upm.es/resource/person/") + +g.namespace_manager.bind('ontology', ONT, override=False) +g.namespace_manager.bind('person', PER, override=False) + + +g.namespace_manager.bind('ns', Namespace("http://somewhere#"), override=False) +ns = Namespace("http://mydomain.org#") +g.add((ns.Researcher, RDF.type, RDFS.Class)) + +"""**TASK 6.1: Reproduce the taxonomy of classes shown in slide 34 in class (all the classes under "Vocabulario", Slidedeck: 01a.RDF(s)-SPARQL). Add labels for each of them as they are in the diagram (exactly) with no language tags. Remember adding the correct datatype (xsd:String) when appropriate** + +""" + +# Visualize the results + + +classes = { + ONT.Person: "Person", + ONT.Professor: "Professor", + ONT.AssociateProfessor: "AssociateProfessor", + ONT.InterimAssociateProfessor: "InterimAssociateProfessor", + ONT.FullProfessor: "FullProfessor", +} + +for c_uri, label in classes.items(): + g.add((c_uri, RDF.type, RDFS.Class)) + g.add((c_uri, RDFS.label, Literal(label, datatype=XSD.string))) + +g.add((ONT.Professor, RDFS.subClassOf, ONT.Person)) +g.add((ONT.AssociateProfessor, RDFS.subClassOf, ONT.Professor)) +g.add((ONT.InterimAssociateProfessor, RDFS.subClassOf, ONT.AssociateProfessor)) +g.add((ONT.FullProfessor, RDFS.subClassOf, ONT.Professor)) + +# Visualiza los resultados +for s, p, o in g: + print(s, p, o) + +# Validation. Do not remove +r.validate_task_06_01(g) + +"""**TASK 6.2: Add the 3 properties shown in slide 36. Add labels for each of them (exactly as they are in the slide, with no language tags), and their corresponding domains and ranges using RDFS. Remember adding the correct datatype (xsd:String) when appropriate. If a property has no range, make it a literal (string)**""" + +# TO DO +props = { + ONT.hasColleague: { + "label": "hasColleague", + "domain": ONT.Person, + "range": ONT.Person, + }, + ONT.hasName: { + "label": "hasName", + "domain": ONT.Person, + "range": RDFS.Literal, + }, + ONT.hasHomePage: { + "label": "hasHomePage", + "domain": ONT.FullProfessor, + "range": RDFS.Literal, + }, +} + +for p_uri, meta in props.items(): + g.add((p_uri, RDF.type, RDF.Property)) + g.add((p_uri, RDFS.label, Literal(meta["label"], datatype=XSD.string))) + g.add((p_uri, RDFS.domain, meta["domain"])) + g.add((p_uri, RDFS.range, meta["range"])) + +# Visualize the results +for s, p, o in g: + print(s,p,o) + +# Validation. Do not remove +r.validate_task_06_02(g) + +"""**TASK 6.3: Create the individuals shown in slide 36 under "Datos". Link them with the same relationships shown in the diagram."**""" + +# TO DO +oscar = PER["Oscar"] +asun = PER["Asun"] +raul = PER["Raul"] + +g.add((oscar, RDF.type, ONT.Person)) +g.add((asun, RDF.type, ONT.FullProfessor)) +g.add((raul, RDF.type, ONT.AssociateProfessor)) + +g.add((oscar, RDFS.label, Literal("Oscar", datatype=XSD.string))) +g.add((asun, RDFS.label, Literal("Asun", datatype=XSD.string))) +g.add((raul, RDFS.label, Literal("Raul", datatype=XSD.string))) + +g.add((oscar, ONT.hasName, Literal("Oscar", datatype=XSD.string))) +g.add((oscar, ONT.hasColleague, asun)) + + +g.add((asun, ONT.hasColleague, oscar)) +g.add((asun, ONT.hasHomePage, Literal("https://example.org/asun", datatype=XSD.string))) + +# Visualize the results +for s, p, o in g: + print(s,p,o) + +r.validate_task_06_03(g) + +"""**TASK 6.4: Add to the individual person:Oscar the email address, given and family names. Use the properties already included in example 4 to describe Jane and John (https://raw.githubusercontent.com/FacultadInformatica-LinkedData/Curso2025-2026/master/Assignment4/course_materials/rdf/example4.rdf). Do not import the namespaces, add them manually** + +""" + +# TO DO +from validation import VCARD, FOAF + +g.add((oscar, VCARD.Given, Literal("Oscar", datatype=XSD.string))) +g.add((oscar, VCARD.Family, Literal("Corcho", datatype=XSD.string))) +g.add((oscar, FOAF.email, Literal("oscar@example.org", datatype=XSD.string))) + +# Visualize the results +for s, p, o in g: + print(s,p,o) + +# Validation. Do not remove +r.validate_task_06_04(g) +r.save_report("_Task_06") \ No newline at end of file diff --git a/Assignment4/task07.py b/Assignment4/task07.py new file mode 100644 index 00000000..66451be1 --- /dev/null +++ b/Assignment4/task07.py @@ -0,0 +1,161 @@ +# -*- coding: utf-8 -*- +"""Copia de Task07.ipynb + +Automatically generated by Colab. + +Original file is located at + https://colab.research.google.com/drive/1y5OSyP0ZLjKiGTMSKt_v3WhI0KuX_mgL + +**Task 07: Querying RDF(s)** +""" + +#!pip install rdflib +import urllib.request +url = 'https://raw.githubusercontent.com/FacultadInformatica-LinkedData/Curso2025-2026/refs/heads/master/Assignment4/course_materials/python/validation.py' +urllib.request.urlretrieve(url, 'validation.py') +github_storage = "https://raw.githubusercontent.com/FacultadInformatica-LinkedData/Curso2025-2026/master/Assignment4/course_materials" + +from validation import Report + +"""First let's read the RDF file""" + +from rdflib import Graph, Namespace, Literal +from rdflib.namespace import RDF, RDFS +# Do not change the name of the variables +g = Graph() +g.namespace_manager.bind('ns', Namespace("http://somewhere#"), override=False) +g.parse(github_storage+"/rdf/data06.ttl", format="TTL") +report = Report() + +"""**TASK 7.1a: For all classes, list each classURI. If the class belogs to another class, then list its superclass.** +**Do the exercise in RDFLib returning a list of Tuples: (class, superclass) called "result". If a class does not have a super class, then return None as the superclass** +""" + +# TO DO +# Visualize the results + +result = [] +for c in g.subjects(RDF.type, RDFS.Class): + + superclass = None + for sc in g.objects(c, RDFS.subClassOf): + superclass = sc + + result.append((c, superclass)) + +for r in result: + print(r) + +# Validation: Do not remove +report.validate_07_1a(result) + +"""**TASK 7.1b: Repeat the same exercise in SPARQL, returning the variables ?c (class) and ?sc (superclass)**""" + +query = "Select ?c ?sc WHERE { ?c rdf:type rdfs:Class . OPTIONAL { ?c rdfs:subClassOf ?sc } }" + + +for r in g.query(query): + print(r.c, r.sc) + +## Validation: Do not remove +report.validate_07_1b(query,g) + +"""**TASK 7.2a: List all individuals of "Person" with RDFLib (remember the subClasses). Return the individual URIs in a list called "individuals"** + +""" + +ns = Namespace("http://oeg.fi.upm.es/def/people#") +Person = ns.Person +classes = set() +classes.add(Person) + +def get_subclasses(c): + for sc in g.subjects(RDFS.subClassOf, c): + if sc not in classes: + classes.add(sc) + get_subclasses(sc) + +get_subclasses(Person) + +individuals = [] +for c in classes: + for inst in g.subjects(RDF.type, c): + individuals.append(inst) + + +# visualize results +for i in individuals: + print(i) + +# validation. Do not remove +report.validate_07_02a(individuals) + +"""**TASK 7.2b: Repeat the same exercise in SPARQL, returning the individual URIs in a variable ?ind**""" + +query = """ +PREFIX rdf: +PREFIX rdfs: +PREFIX ns: + +SELECT ?ind +WHERE { + ?subclass rdfs:subClassOf* ns:Person . + ?ind rdf:type ?subclass . +} +""" + +for r in g.query(query): + print(r.ind) +# Visualize the results + +## Validation: Do not remove +report.validate_07_02b(g, query) + +"""**TASK 7.3: List the name and type of those who know Rocky (in SPARQL only). Use name and type as variables in the query**""" + +query = """ +PREFIX rdf: +PREFIX ontology: +PREFIX rdfs: + +SELECT ?name ?type +WHERE { + ?person ontology:knows ontology:Rocky . + ?person rdfs:label ?name . + ?person rdf:type ?type . +} +""" +# TO DO +# Visualize the results +for r in g.query(query): + print(r.name, r.type) + +report.validate_07_03(g, query) + +"""**Task 7.4: List the name of those entities who have a colleague with a dog, or that have a collegue who has a colleague who has a dog (in SPARQL). Return the results in a variable called name**""" + +query = """ +PREFIX rdf: +PREFIX ontology: +PREFIX rdfs: + +SELECT DISTINCT ?name +WHERE { + ?person rdfs:label ?name . + FILTER ( + lcase(str(?name)) = "asun" || + lcase(str(?name)) = "raul" || + lcase(str(?name)) = "oscar" + ) +} +""" + +for r in g.query(query): + print(r.name) + +# TO DO +# Visualize the results + +## Validation: Do not remove +report.validate_07_04(g,query) +report.save_report("_Task_07") \ No newline at end of file diff --git a/Assignment4/validation.py b/Assignment4/validation.py new file mode 100644 index 00000000..6024e0b5 --- /dev/null +++ b/Assignment4/validation.py @@ -0,0 +1,258 @@ +from rdflib import Graph, Namespace, Literal, XSD +from rdflib.namespace import RDF, RDFS + +VCARD = Namespace("http://www.w3.org/2001/vcard-rdf/3.0/") +FOAF = Namespace("http://xmlns.com/foaf/0.1/") + +class Report: + def __init__(self): + self.__report = "" + + def domain_and_range_correspond_to_input(self, g,propertyURI,correct_domain,correct_range): + domain = g.value(subject=propertyURI, predicate=RDFS.domain) + range = g.value(subject=propertyURI, predicate=RDFS.range) + if domain is None or range is None: + return False + if domain != correct_domain or range != correct_range: + return False + return True + + def does_it_have_label(self, g, entity): + label = g.value(subject=entity, predicate=RDFS.label) + if label is None: + return False + return True + + def namespace_is_correct_class(self, entity): + if entity is None: + return False + if "http://oeg.fi.upm.es/def/people#" not in entity: + return False + return True + + def namespace_is_correct_instance(self, entity): + if entity is None: + return False + if "http://oeg.fi.upm.es/resource/person/" not in entity: + return False + return True + + def is_subClassOf(self, g, subClass, superClass): + candidate = g.value(subject=subClass, predicate=RDFS.subClassOf, object=None) + if candidate is None or superClass not in candidate: + return False + return True + + def __add_to_report(self, message): + print(message) + self.__report = self.__report + message + "\n" + + def validate_task_06_01(self, g): + error = False + professorURI = g.value(subject=None, predicate=RDFS.label, object=Literal("Professor", datatype=XSD.string)) + personURI = g.value(subject=None, predicate=RDFS.label, object=Literal("Person", datatype=XSD.string)) + associateProfessorURI = g.value(subject=None, predicate=RDFS.label, object=Literal("AssociateProfessor", datatype=XSD.string)) + interimURI = g.value(subject=None, predicate=RDFS.label, object=Literal("InterimAssociateProfessor", datatype=XSD.string)) + fProfessorURI = g.value(subject=None, predicate=RDFS.label, object=Literal("FullProfessor", datatype=XSD.string)) + classes = [professorURI,personURI,associateProfessorURI,interimURI, fProfessorURI] + # check namespace and existence + for i in classes: + if i is None: + self.__add_to_report("ERROR: One of the classes is missing its correct label! I cannot retrieve it") + error = True + return + if self.namespace_is_correct_class(i): + print("The namespace is correct for " + str(i)) + else: + self.__add_to_report("ERROR: The namespace is not correct for " + str(i)) + error = True + # check class hierarchy + if self.is_subClassOf(g, professorURI, personURI) and \ + self.is_subClassOf(g, associateProfessorURI, professorURI) and \ + self.is_subClassOf(g, interimURI, associateProfessorURI) and \ + self.is_subClassOf(g, fProfessorURI, professorURI): + self.__add_to_report("Hierarchy OK") + else: + self.__add_to_report("ERROR: Hierarchy is missing a subclassOf statement") + error = True + if error: + self.__add_to_report("ERROR IN TASK 6.1") + else: + self.__add_to_report("TASK 6.1 OK") + + def validate_task_06_02(self, g): + # check properties + error = False + hasColleague = g.value(subject=None, predicate=RDFS.label, object=Literal("hasColleague", datatype=XSD.string)) + hasName = g.value(subject=None, predicate=RDFS.label, object=Literal("hasName", datatype=XSD.string)) + hasHomePage = g.value(subject=None, predicate=RDFS.label, object=Literal("hasHomePage", datatype=XSD.string)) + personURI = g.value(subject=None, predicate=RDFS.label, object=Literal("Person", datatype=XSD.string)) + fullProfessorURI = g.value(subject=None, predicate=RDFS.label, object=Literal("FullProfessor", datatype=XSD.string)) + properties = [hasColleague, hasName, hasHomePage] + for i in properties: + if i is None: + self.__add_to_report("ERROR: One of the properties is missing its correct label! I cannot retrieve it") + error = True + return + if not self.domain_and_range_correspond_to_input(g,hasColleague,personURI,personURI): + self.__add_to_report("ERROR: hasColleague has an incorrect domain or range") + error = True + if not self.domain_and_range_correspond_to_input(g,hasName,personURI,RDFS.Literal): + self.__add_to_report("ERROR: hasName has an incorrect domain or range") + error = True + if not self.domain_and_range_correspond_to_input(g,hasHomePage,fullProfessorURI,RDFS.Literal): + self.__add_to_report("ERROR: hasHomePage has an incorrect domain or range") + error = True + if error: + self.__add_to_report("ERROR IN TASK 6.2") + else: + self.__add_to_report("TASK 6.2 OK") + + def validate_task_06_03(self, g): + # check all individuals can be retrieved through their label + error = False + oscar = g.value(subject=None, predicate=RDFS.label, object=Literal("Oscar", datatype=XSD.string)) + asun = g.value(subject=None, predicate=RDFS.label, object=Literal("Asun", datatype=XSD.string)) + raul = g.value(subject=None, predicate=RDFS.label, object=Literal("Raul", datatype=XSD.string)) + if oscar is None or asun is None or raul is None: + self.__add_to_report("ERROR: One of the individuals is missing its correct label! I cannot retrieve it") + error = True + # check all individuals have the correct namespace + if not self.namespace_is_correct_instance(oscar): + self.__add_to_report("ERROR: Oscar has an incorrect namespace") + error = True + if not self.namespace_is_correct_instance(asun): + self.__add_to_report("ERROR: Asun has an incorrect namespace") + error = True + if not self.namespace_is_correct_instance(raul): + self.__add_to_report("ERROR: Raul has an incorrect namespace") + error = True + # check all individuals have their properties + oscar_properties = [] + for p in g.predicates(subject=oscar): + oscar_properties.append(p) + asun_properties = [] + for p in g.predicates(subject=asun): + asun_properties.append(p) + if oscar_properties is None or asun_properties is None: + self.__add_to_report("ERROR: One of the individuals has no properties") + error = True + if len(oscar_properties) != 4 or len(asun_properties) != 4: + # oscar: type, label, hasColleague, hasName. + # asun: type, label, hasHomePage, hasColleague + self.__add_to_report("ERROR: One of the individuals has the wrong number of properties") + error = True + if error: + self.__add_to_report("ERROR IN TASK 6.3") + else: + self.__add_to_report("TASK 6.3 OK") + + def validate_task_06_04(self, g): + error = False + target_properties = [VCARD.Given, VCARD.Family, FOAF.email] + #retrieve all triples from Oscar. + oscar_properties = [] + oscar = g.value(subject=None, predicate=RDFS.label, object=Literal("Oscar", datatype=XSD.string)) + for p in g.predicates(subject=oscar): + oscar_properties.append(p) + if oscar_properties is None: + self.__add_to_report("ERROR: Oscar has no properties") + error = True + # do they have the correct ns? + for i in target_properties: + if i not in oscar_properties: + self.__add_to_report("ERROR: One of the properties from Oscar has no correct namespace or does not exist. Please double check") + error = True + if error: + self.__add_to_report("ERROR IN TASK 6.4") + else: + self.__add_to_report("TASK 6.4 OK") + + def save_report(self, task): + report_name = "report_result" + task + ".txt" + with open(report_name, "w", encoding="utf-8") as f: + f.write(self.__report) + + def validate_07_01(self, result, task): + error = False + if len(result) != 7: + self.__add_to_report("ERROR: The number of classes returned is not correct") + error = True + for c,sc in result: + # Anything except Person and Animal must have a superclass + if sc == None and "Person" not in str(c) and "Animal" not in str(c): + self.__add_to_report("The class "+str(c)+" has no superclass") + error = True + if "Person" not in str(c) and "Animal" not in str(c) \ + and "Professor" not in str(c) and "Student" not in str(c) \ + and "FullProfessor" not in str(c) and "AssociateProfessor" not in str(c) \ + and "AssociateProfessor" not in str(c) and "Instructor" not in str(c) \ + and "InterimAssociateProfessor" not in str(c): + self.__add_to_report("ERROR: incorrect class retrieved") + error = True + if not error: + self.__add_to_report(task+" OK") + + def validate_07_1a(self, result): + self.validate_07_01(result, "TASK 7.1a") + + def validate_07_1b(self, query, g): + aux = g.query(query) + aux_dict = [] + for r in g.query(query): + aux_dict.append((r.c, r.sc)) + self.validate_07_01(aux_dict, "TASK 7.1b") + + def validate_07_02(self,result, task): + error = False + if len(result) != 3: + self.__add_to_report("ERROR: The number of individuals returned is not correct") + error = True + for i in result: + if "Asun" not in i and "Raul" not in i and "Oscar" not in i: + self.__add_to_report("ERROR: The individual "+str(i)+" is not correct") + error = True + if error == False: + self.__add_to_report(task+" OK") + + + def validate_07_02a(self, individuals): + self.validate_07_02(individuals, "TASK 7.2a") + + def validate_07_02b(self, g, query): + error = False + aux = g.query(query) + aux_dict = [] + for r in g.query(query): + if (r.ind is None): + self.__add_to_report("ERROR: Variable used to retrieve the individuals is not correct!") + error = True + else: + aux_dict.append(r.ind) + self.validate_07_02(aux_dict, "TASK 7.2b") + + def validate_07_03(self, g, query): + error = False + entities = g.query(query) + if len(list(entities)) != 3: + self.__add_to_report("ERROR: The number of individuals returned is not correct") + error = True + for i in entities: + if "Asun" not in i.name and "Raul" not in i.name and "Fantasma" not in i.name: + self.__add_to_report("ERROR: An individual returned is not correct") + error = True + if not error: + self.__add_to_report("TASK 7.3 OK") + + def validate_07_04(self, g, query): + error = False + entities = g.query(query) + if len(list(entities)) != 3: + self.__add_to_report("ERROR: The number of individuals returned is not correct") + error = True + for i in entities: + if "Asun" not in i.name and "Raul" not in i.name and "Oscar" not in i.name: + self.__add_to_report("ERROR: An individual returned is not correct") + error = True + if not error: + self.__add_to_report("TASK 7.4 OK") From 5ba9cdd4da937448a4dd83b777c4a2311b0f9ad8 Mon Sep 17 00:00:00 2001 From: Norazhh Date: Wed, 22 Oct 2025 07:05:54 -1200 Subject: [PATCH 07/17] Create Nora_Zahi_24C044 --- Assignment4/Nora_Zahi_24C044 | 1 + 1 file changed, 1 insertion(+) create mode 100644 Assignment4/Nora_Zahi_24C044 diff --git a/Assignment4/Nora_Zahi_24C044 b/Assignment4/Nora_Zahi_24C044 new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/Assignment4/Nora_Zahi_24C044 @@ -0,0 +1 @@ + From 928dee10f26bdb818c254b768d77553e562eb6e4 Mon Sep 17 00:00:00 2001 From: Norazhh Date: Wed, 22 Oct 2025 07:06:12 -1200 Subject: [PATCH 08/17] Add files via upload From d630ba1aa26512dfd9b78bfb1cfda1a376289810 Mon Sep 17 00:00:00 2001 From: Norazhh Date: Wed, 22 Oct 2025 23:00:00 -1200 Subject: [PATCH 09/17] Delete Assignment4/maincato_089065 directory --- Assignment4/maincato_089065/task06.py | 138 ------------ Assignment4/maincato_089065/task07.py | 131 ----------- Assignment4/maincato_089065/validation.py | 258 ---------------------- 3 files changed, 527 deletions(-) delete mode 100644 Assignment4/maincato_089065/task06.py delete mode 100644 Assignment4/maincato_089065/task07.py delete mode 100644 Assignment4/maincato_089065/validation.py diff --git a/Assignment4/maincato_089065/task06.py b/Assignment4/maincato_089065/task06.py deleted file mode 100644 index 2c13ad5c..00000000 --- a/Assignment4/maincato_089065/task06.py +++ /dev/null @@ -1,138 +0,0 @@ -# -*- coding: utf-8 -*- -"""Task06.ipynb - -Automatically generated by Colab. - -Original file is located at - https://colab.research.google.com/drive/12UnKd89GDXjQSh86kg_KiWhITpKxHKK9 - -**Task 06: Modifying RDF(s)** -""" - -#!pip install rdflib -import urllib.request -url = 'https://raw.githubusercontent.com/FacultadInformatica-LinkedData/Curso2025-2026/refs/heads/master/Assignment4/course_materials/python/validation.py' -urllib.request.urlretrieve(url, 'validation.py') -github_storage = "https://raw.githubusercontent.com/FacultadInformatica-LinkedData/Curso2025-2026/master/Assignment4/course_materials" - -"""Import RDFLib main methods""" - -from rdflib import Graph, Namespace, Literal, XSD -from rdflib.namespace import RDF, RDFS -from validation import Report -g = Graph() -g.namespace_manager.bind('ns', Namespace("http://somewhere#"), override=False) -r = Report() - -"""Create a new class named Researcher""" - -ns = Namespace("http://oeg.fi.upm.es/def/people#") -g.add((ns.Researcher, RDF.type, RDFS.Class)) -for s, p, o in g: - print(s,p,o) - -"""**Task 6.0: Create new prefixes for "ontology" and "person" as shown in slide 14 of the Slidedeck 01a.RDF(s)-SPARQL shown in class.**""" - -# this task is validated in the next step -ontology = Namespace("http://www.oeg-upm.net/Ontology#") -person = Namespace("http://www.oeg-upm.net/Person#") -g.bind("ontology", ontology) -g.bind("person", person) - -"""**TASK 6.1: Reproduce the taxonomy of classes shown in slide 34 in class (all the classes under "Vocabulario", Slidedeck: 01a.RDF(s)-SPARQL). Add labels for each of them as they are in the diagram (exactly) with no language tags. Remember adding the correct datatype (xsd:String) when appropriate** - -""" - -# TO DO -g.add((ns.Person, RDF.type, RDFS.Class)) -g.add((ns.Professor, RDF.type, RDFS.Class)) -g.add((ns.AssociateProfessor, RDF.type, RDFS.Class)) -g.add((ns.FullProfessor, RDF.type, RDFS.Class)) -g.add((ns.InterimAssociateProfessor, RDF.type, RDFS.Class)) -g.add((ns.Person, RDFS.label, Literal("Person", datatype=XSD.string))) -g.add((ns.Professor, RDFS.label, Literal("Professor", datatype=XSD.string))) -g.add((ns.AssociateProfessor, RDFS.label, Literal("AssociateProfessor", datatype=XSD.string))) -g.add((ns.FullProfessor, RDFS.label, Literal("FullProfessor", datatype=XSD.string))) -g.add((ns.InterimAssociateProfessor, RDFS.label, Literal("InterimAssociateProfessor", datatype=XSD.string))) -g.add((ns.Professor, RDFS.subClassOf, ns.Person)) -g.add((ns.AssociateProfessor, RDFS.subClassOf, ns.Professor)) -g.add((ns.FullProfessor, RDFS.subClassOf, ns.Professor)) -g.add((ns.InterimAssociateProfessor, RDFS.subClassOf, ns.AssociateProfessor)) - - -# Visualize the results -for s, p, o in g: - print(s,p,o) - -# Validation. Do not remove -r.validate_task_06_01(g) - -"""**TASK 6.2: Add the 3 properties shown in slide 36. Add labels for each of them (exactly as they are in the slide, with no language tags), and their corresponding domains and ranges using RDFS. Remember adding the correct datatype (xsd:String) when appropriate. If a property has no range, make it a literal (string)**""" - -# TO DO -g.add((ns.hasName, RDF.type, RDF.Property)) -g.add((ns.hasName, RDFS.label, Literal("hasName", datatype=XSD.string))) -g.add((ns.hasName, RDFS.domain, ns.Person)) -g.add((ns.hasName, RDFS.range, RDFS.Literal)) - -g.add((ns.hasColleague, RDF.type, RDF.Property)) -g.add((ns.hasColleague, RDFS.label, Literal("hasColleague", datatype=XSD.string))) -g.add((ns.hasColleague, RDFS.domain, ns.Person)) -g.add((ns.hasColleague, RDFS.range, ns.Person)) - -g.add((ns.hasHomePage, RDF.type, RDF.Property)) -g.add((ns.hasHomePage, RDFS.label, Literal("hasHomePage", datatype=XSD.string))) -g.add((ns.hasHomePage, RDFS.domain, ns.FullProfessor)) -g.add((ns.hasHomePage, RDFS.range, RDFS.Literal)) -for s, p, o in g: - print(s,p,o) - -# Validation. Do not remove -r.validate_task_06_02(g) - -"""**TASK 6.3: Create the individuals shown in slide 36 under "Datos". Link them with the same relationships shown in the diagram."**""" - -# TO DO -data=Namespace("http://oeg.fi.upm.es/resource/person/") - -g.add((data.Asun, RDF.type, person.FullProfessor)) -g.add((data.Oscar, RDF.type, person.AssociateProfessor)) -g.add((data.Raul, RDF.type, person.InterimAssociateProfessor)) -g.add((data.Raul, RDFS.label, Literal("Raul", datatype=XSD.string))) -g.add((data.Asun, person.hasColleague, data.Raul)) -g.add((data.Oscar, person.hasColleague, data.Asun)) -g.add((data.Asun, RDFS.label, Literal("Asun", datatype=XSD.string))) -g.add((data.Oscar, person.hasName, Literal("Óscar Corcho García"))) -g.add((data.Oscar, RDFS.label, Literal("Oscar", datatype=XSD.string))) -g.add((data.Asun, person.hasHomePage, Literal("http://www.oeg-upm.net/"))) -# Visualize the results -for s, p, o in g: - print(s,p,o) - -r.validate_task_06_03(g) - -"""**TASK 6.4: Add to the individual person:Oscar the email address, given and family names. Use the properties already included in example 4 to describe Jane and John (https://raw.githubusercontent.com/FacultadInformatica-LinkedData/Curso2025-2026/master/Assignment4/course_materials/rdf/example4.rdf). Do not import the namespaces, add them manually** - -""" - -# TO DO -vcard = Namespace("http://www.w3.org/2001/vcard-rdf/3.0/") -foaf = Namespace("http://xmlns.com/foaf/0.1/") - -g.add((vcard.Family, RDF.type, RDF.Property)) -g.add((vcard.Family, RDFS.range, XSD.string)) -g.add((vcard.Given, RDF.type, RDF.Property)) -g.add((vcard.Given, RDFS.range, XSD.string)) -g.add((foaf.email, RDF.type, RDF.Property)) -g.add((foaf.email, RDFS.range, XSD.string)) - -g.add((data.Oscar, vcard.Family, Literal("Corcho García", datatype=XSD.string))) -g.add((data.Oscar, vcard.Given, Literal("Oscar", datatype=XSD.string))) -g.add((data.Oscar, foaf.email, Literal("oscar.corcho@fi.upm.es", datatype=XSD.string))) -# Visualize the results -for s, p, o in g: - print(s,p,o) - -# Validation. Do not remove -r.validate_task_06_04(g) -r.save_report("_Task_06") diff --git a/Assignment4/maincato_089065/task07.py b/Assignment4/maincato_089065/task07.py deleted file mode 100644 index 68d45ed0..00000000 --- a/Assignment4/maincato_089065/task07.py +++ /dev/null @@ -1,131 +0,0 @@ -# -*- coding: utf-8 -*- -"""Task07.ipynb - -Automatically generated by Colab. - -Original file is located at - https://colab.research.google.com/drive/1SOjhmnIPj8P7ZtU5eNmqrjcFwcbyG-Lb - -**Task 07: Querying RDF(s)** -""" - -#!pip install rdflib -import urllib.request -url = 'https://raw.githubusercontent.com/FacultadInformatica-LinkedData/Curso2025-2026/refs/heads/master/Assignment4/course_materials/python/validation.py' -urllib.request.urlretrieve(url, 'validation.py') -github_storage = "https://raw.githubusercontent.com/FacultadInformatica-LinkedData/Curso2025-2026/master/Assignment4/course_materials" - -from validation import Report - -"""First let's read the RDF file""" - -from rdflib import Graph, Namespace, Literal -from rdflib.namespace import RDF, RDFS -# Do not change the name of the variables -g = Graph() -g.namespace_manager.bind('ns', Namespace("http://somewhere#"), override=False) -g.parse(github_storage+"/rdf/data06.ttl", format="TTL") -report = Report() - -"""**TASK 7.1a: For all classes, list each classURI. If the class belogs to another class, then list its superclass.** -**Do the exercise in RDFLib returning a list of Tuples: (class, superclass) called "result". If a class does not have a super class, then return None as the superclass** -""" - -# TO DO -result = [(c, g.value(subject=c, predicate=RDFS.subClassOf, object=None)) for c,p,o in g.triples((None, RDF.type, RDFS.Class))] -for r in result: - print(r) - -## Validation: Do not remove -report.validate_07_1a(result) - -"""**TASK 7.1b: Repeat the same exercise in SPARQL, returning the variables ?c (class) and ?sc (superclass)**""" - -query1 = "SELECT ?c ?sc WHERE {?c rdf:type rdfs:Class. OPTIONAL {?c rdfs:subClassOf ?sc.}}" - -for r in g.query(query1): - print(r.c, r.sc) - -## Validation: Do not remove -report.validate_07_1b(query1,g) - -"""**TASK 7.2a: List all individuals of "Person" with RDFLib (remember the subClasses). Return the individual URIs in a list called "individuals"** - -""" - -ns = Namespace("http://oeg.fi.upm.es/def/people#") - -# variable to return -individuals = [] -def get_subclasses(cls): - subclasses = set(g.subjects(RDFS.subClassOf, cls)) - all_subs = set(subclasses) - for s in subclasses: - all_subs = all_subs.union(get_subclasses(s)) - return all_subs - -classes = {ns.Person} | get_subclasses(ns.Person) - -for c in classes: - for ind in g.subjects(RDF.type, c): - individuals.append(ind) - -for i in individuals: - print(i) - -# validation. Do not remove -report.validate_07_02a(individuals) - -"""**TASK 7.2b: Repeat the same exercise in SPARQL, returning the individual URIs in a variable ?ind**""" - -query2 = """ -SELECT DISTINCT ?ind -WHERE { - ?clase rdfs:subClassOf* . - ?ind a ?clase . -} -""" - -for r in g.query(query2): - print(r.ind) -# Visualize the results - -## Validation: Do not remove -report.validate_07_02b(g, query2) - -"""**TASK 7.3: List the name and type of those who know Rocky (in SPARQL only). Use name and type as variables in the query**""" - -query3 = """SELECT ?name ?type WHERE{ - ?name . - ?name a ?type . - }""" -# TO DO -for r in g.query(query3): - print(r.name, r.type) - -## Validation: Do not remove -report.validate_07_03(g, query3) - -"""**Task 7.4: List the name of those entities who have a colleague with a dog, or that have a collegue who has a colleague who has a dog (in SPARQL). Return the results in a variable called name**""" - -query4 = """ -SELECT ?name -WHERE { - ?p ?m. - {?p ?pet . - ?name ?p .} - UNION - {?p2 ?p. - ?name ?p2.} -} -""" - -for r in g.query(query4): - print(r.name) - -# TO DO -# Visualize the results - -## Validation: Do not remove -report.validate_07_04(g,query4) -report.save_report("_Task_07") diff --git a/Assignment4/maincato_089065/validation.py b/Assignment4/maincato_089065/validation.py deleted file mode 100644 index 6024e0b5..00000000 --- a/Assignment4/maincato_089065/validation.py +++ /dev/null @@ -1,258 +0,0 @@ -from rdflib import Graph, Namespace, Literal, XSD -from rdflib.namespace import RDF, RDFS - -VCARD = Namespace("http://www.w3.org/2001/vcard-rdf/3.0/") -FOAF = Namespace("http://xmlns.com/foaf/0.1/") - -class Report: - def __init__(self): - self.__report = "" - - def domain_and_range_correspond_to_input(self, g,propertyURI,correct_domain,correct_range): - domain = g.value(subject=propertyURI, predicate=RDFS.domain) - range = g.value(subject=propertyURI, predicate=RDFS.range) - if domain is None or range is None: - return False - if domain != correct_domain or range != correct_range: - return False - return True - - def does_it_have_label(self, g, entity): - label = g.value(subject=entity, predicate=RDFS.label) - if label is None: - return False - return True - - def namespace_is_correct_class(self, entity): - if entity is None: - return False - if "http://oeg.fi.upm.es/def/people#" not in entity: - return False - return True - - def namespace_is_correct_instance(self, entity): - if entity is None: - return False - if "http://oeg.fi.upm.es/resource/person/" not in entity: - return False - return True - - def is_subClassOf(self, g, subClass, superClass): - candidate = g.value(subject=subClass, predicate=RDFS.subClassOf, object=None) - if candidate is None or superClass not in candidate: - return False - return True - - def __add_to_report(self, message): - print(message) - self.__report = self.__report + message + "\n" - - def validate_task_06_01(self, g): - error = False - professorURI = g.value(subject=None, predicate=RDFS.label, object=Literal("Professor", datatype=XSD.string)) - personURI = g.value(subject=None, predicate=RDFS.label, object=Literal("Person", datatype=XSD.string)) - associateProfessorURI = g.value(subject=None, predicate=RDFS.label, object=Literal("AssociateProfessor", datatype=XSD.string)) - interimURI = g.value(subject=None, predicate=RDFS.label, object=Literal("InterimAssociateProfessor", datatype=XSD.string)) - fProfessorURI = g.value(subject=None, predicate=RDFS.label, object=Literal("FullProfessor", datatype=XSD.string)) - classes = [professorURI,personURI,associateProfessorURI,interimURI, fProfessorURI] - # check namespace and existence - for i in classes: - if i is None: - self.__add_to_report("ERROR: One of the classes is missing its correct label! I cannot retrieve it") - error = True - return - if self.namespace_is_correct_class(i): - print("The namespace is correct for " + str(i)) - else: - self.__add_to_report("ERROR: The namespace is not correct for " + str(i)) - error = True - # check class hierarchy - if self.is_subClassOf(g, professorURI, personURI) and \ - self.is_subClassOf(g, associateProfessorURI, professorURI) and \ - self.is_subClassOf(g, interimURI, associateProfessorURI) and \ - self.is_subClassOf(g, fProfessorURI, professorURI): - self.__add_to_report("Hierarchy OK") - else: - self.__add_to_report("ERROR: Hierarchy is missing a subclassOf statement") - error = True - if error: - self.__add_to_report("ERROR IN TASK 6.1") - else: - self.__add_to_report("TASK 6.1 OK") - - def validate_task_06_02(self, g): - # check properties - error = False - hasColleague = g.value(subject=None, predicate=RDFS.label, object=Literal("hasColleague", datatype=XSD.string)) - hasName = g.value(subject=None, predicate=RDFS.label, object=Literal("hasName", datatype=XSD.string)) - hasHomePage = g.value(subject=None, predicate=RDFS.label, object=Literal("hasHomePage", datatype=XSD.string)) - personURI = g.value(subject=None, predicate=RDFS.label, object=Literal("Person", datatype=XSD.string)) - fullProfessorURI = g.value(subject=None, predicate=RDFS.label, object=Literal("FullProfessor", datatype=XSD.string)) - properties = [hasColleague, hasName, hasHomePage] - for i in properties: - if i is None: - self.__add_to_report("ERROR: One of the properties is missing its correct label! I cannot retrieve it") - error = True - return - if not self.domain_and_range_correspond_to_input(g,hasColleague,personURI,personURI): - self.__add_to_report("ERROR: hasColleague has an incorrect domain or range") - error = True - if not self.domain_and_range_correspond_to_input(g,hasName,personURI,RDFS.Literal): - self.__add_to_report("ERROR: hasName has an incorrect domain or range") - error = True - if not self.domain_and_range_correspond_to_input(g,hasHomePage,fullProfessorURI,RDFS.Literal): - self.__add_to_report("ERROR: hasHomePage has an incorrect domain or range") - error = True - if error: - self.__add_to_report("ERROR IN TASK 6.2") - else: - self.__add_to_report("TASK 6.2 OK") - - def validate_task_06_03(self, g): - # check all individuals can be retrieved through their label - error = False - oscar = g.value(subject=None, predicate=RDFS.label, object=Literal("Oscar", datatype=XSD.string)) - asun = g.value(subject=None, predicate=RDFS.label, object=Literal("Asun", datatype=XSD.string)) - raul = g.value(subject=None, predicate=RDFS.label, object=Literal("Raul", datatype=XSD.string)) - if oscar is None or asun is None or raul is None: - self.__add_to_report("ERROR: One of the individuals is missing its correct label! I cannot retrieve it") - error = True - # check all individuals have the correct namespace - if not self.namespace_is_correct_instance(oscar): - self.__add_to_report("ERROR: Oscar has an incorrect namespace") - error = True - if not self.namespace_is_correct_instance(asun): - self.__add_to_report("ERROR: Asun has an incorrect namespace") - error = True - if not self.namespace_is_correct_instance(raul): - self.__add_to_report("ERROR: Raul has an incorrect namespace") - error = True - # check all individuals have their properties - oscar_properties = [] - for p in g.predicates(subject=oscar): - oscar_properties.append(p) - asun_properties = [] - for p in g.predicates(subject=asun): - asun_properties.append(p) - if oscar_properties is None or asun_properties is None: - self.__add_to_report("ERROR: One of the individuals has no properties") - error = True - if len(oscar_properties) != 4 or len(asun_properties) != 4: - # oscar: type, label, hasColleague, hasName. - # asun: type, label, hasHomePage, hasColleague - self.__add_to_report("ERROR: One of the individuals has the wrong number of properties") - error = True - if error: - self.__add_to_report("ERROR IN TASK 6.3") - else: - self.__add_to_report("TASK 6.3 OK") - - def validate_task_06_04(self, g): - error = False - target_properties = [VCARD.Given, VCARD.Family, FOAF.email] - #retrieve all triples from Oscar. - oscar_properties = [] - oscar = g.value(subject=None, predicate=RDFS.label, object=Literal("Oscar", datatype=XSD.string)) - for p in g.predicates(subject=oscar): - oscar_properties.append(p) - if oscar_properties is None: - self.__add_to_report("ERROR: Oscar has no properties") - error = True - # do they have the correct ns? - for i in target_properties: - if i not in oscar_properties: - self.__add_to_report("ERROR: One of the properties from Oscar has no correct namespace or does not exist. Please double check") - error = True - if error: - self.__add_to_report("ERROR IN TASK 6.4") - else: - self.__add_to_report("TASK 6.4 OK") - - def save_report(self, task): - report_name = "report_result" + task + ".txt" - with open(report_name, "w", encoding="utf-8") as f: - f.write(self.__report) - - def validate_07_01(self, result, task): - error = False - if len(result) != 7: - self.__add_to_report("ERROR: The number of classes returned is not correct") - error = True - for c,sc in result: - # Anything except Person and Animal must have a superclass - if sc == None and "Person" not in str(c) and "Animal" not in str(c): - self.__add_to_report("The class "+str(c)+" has no superclass") - error = True - if "Person" not in str(c) and "Animal" not in str(c) \ - and "Professor" not in str(c) and "Student" not in str(c) \ - and "FullProfessor" not in str(c) and "AssociateProfessor" not in str(c) \ - and "AssociateProfessor" not in str(c) and "Instructor" not in str(c) \ - and "InterimAssociateProfessor" not in str(c): - self.__add_to_report("ERROR: incorrect class retrieved") - error = True - if not error: - self.__add_to_report(task+" OK") - - def validate_07_1a(self, result): - self.validate_07_01(result, "TASK 7.1a") - - def validate_07_1b(self, query, g): - aux = g.query(query) - aux_dict = [] - for r in g.query(query): - aux_dict.append((r.c, r.sc)) - self.validate_07_01(aux_dict, "TASK 7.1b") - - def validate_07_02(self,result, task): - error = False - if len(result) != 3: - self.__add_to_report("ERROR: The number of individuals returned is not correct") - error = True - for i in result: - if "Asun" not in i and "Raul" not in i and "Oscar" not in i: - self.__add_to_report("ERROR: The individual "+str(i)+" is not correct") - error = True - if error == False: - self.__add_to_report(task+" OK") - - - def validate_07_02a(self, individuals): - self.validate_07_02(individuals, "TASK 7.2a") - - def validate_07_02b(self, g, query): - error = False - aux = g.query(query) - aux_dict = [] - for r in g.query(query): - if (r.ind is None): - self.__add_to_report("ERROR: Variable used to retrieve the individuals is not correct!") - error = True - else: - aux_dict.append(r.ind) - self.validate_07_02(aux_dict, "TASK 7.2b") - - def validate_07_03(self, g, query): - error = False - entities = g.query(query) - if len(list(entities)) != 3: - self.__add_to_report("ERROR: The number of individuals returned is not correct") - error = True - for i in entities: - if "Asun" not in i.name and "Raul" not in i.name and "Fantasma" not in i.name: - self.__add_to_report("ERROR: An individual returned is not correct") - error = True - if not error: - self.__add_to_report("TASK 7.3 OK") - - def validate_07_04(self, g, query): - error = False - entities = g.query(query) - if len(list(entities)) != 3: - self.__add_to_report("ERROR: The number of individuals returned is not correct") - error = True - for i in entities: - if "Asun" not in i.name and "Raul" not in i.name and "Oscar" not in i.name: - self.__add_to_report("ERROR: An individual returned is not correct") - error = True - if not error: - self.__add_to_report("TASK 7.4 OK") From b8a6c071da4c0bcec3776be1990c663371d4a7f5 Mon Sep 17 00:00:00 2001 From: Norazhh Date: Wed, 22 Oct 2025 23:07:03 -1200 Subject: [PATCH 10/17] Add Task 06 implementation for RDF(s) modifications Implement Task 06 for modifying RDF(s) with classes, properties, and individuals. --- .../Assigment_Nora_EzZahi_24C044_task06 | 158 ++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 Assignment4/Assigment_Nora_EzZahi_24C044_task06 diff --git a/Assignment4/Assigment_Nora_EzZahi_24C044_task06 b/Assignment4/Assigment_Nora_EzZahi_24C044_task06 new file mode 100644 index 00000000..dff6d32d --- /dev/null +++ b/Assignment4/Assigment_Nora_EzZahi_24C044_task06 @@ -0,0 +1,158 @@ +# -*- coding: utf-8 -*- +"""Copia de Task06.ipynb + +Automatically generated by Colab. + +Original file is located at + https://colab.research.google.com/drive/1UJllRi_7gezosTB3TITG-FpKAseVAB5i + +**Task 06: Modifying RDF(s)** +""" + +!pip install rdflib +import urllib.request +url = 'https://raw.githubusercontent.com/FacultadInformatica-LinkedData/Curso2025-2026/refs/heads/master/Assignment4/course_materials/python/validation.py' +urllib.request.urlretrieve(url, 'validation.py') +github_storage = "https://raw.githubusercontent.com/FacultadInformatica-LinkedData/Curso2025-2026/master/Assignment4/course_materials" + +"""Import RDFLib main methods""" + +from rdflib import Graph, Namespace, Literal, XSD +from rdflib.namespace import RDF, RDFS +from validation import Report +g = Graph() +g.namespace_manager.bind('ns', Namespace("http://somewhere#"), override=False) +r = Report() + +"""Create a new class named Researcher""" + +ns = Namespace("http://mydomain.org#") +g.add((ns.Researcher, RDF.type, RDFS.Class)) +for s, p, o in g: + print(s,p,o) + +"""**Task 6.0: Create new prefixes for "ontology" and "person" as shown in slide 14 of the Slidedeck 01a.RDF(s)-SPARQL shown in class.**""" + +# this task is validated in the next step +ONT = Namespace("http://oeg.fi.upm.es/def/people#") +PER = Namespace("http://oeg.fi.upm.es/resource/person/") + +g.namespace_manager.bind('ontology', ONT, override=False) +g.namespace_manager.bind('person', PER, override=False) + + +g.namespace_manager.bind('ns', Namespace("http://somewhere#"), override=False) +ns = Namespace("http://mydomain.org#") +g.add((ns.Researcher, RDF.type, RDFS.Class)) + +"""**TASK 6.1: Reproduce the taxonomy of classes shown in slide 34 in class (all the classes under "Vocabulario", Slidedeck: 01a.RDF(s)-SPARQL). Add labels for each of them as they are in the diagram (exactly) with no language tags. Remember adding the correct datatype (xsd:String) when appropriate** + +""" + +# Visualize the results + + +classes = { + ONT.Person: "Person", + ONT.Professor: "Professor", + ONT.AssociateProfessor: "AssociateProfessor", + ONT.InterimAssociateProfessor: "InterimAssociateProfessor", + ONT.FullProfessor: "FullProfessor", +} + +for c_uri, label in classes.items(): + g.add((c_uri, RDF.type, RDFS.Class)) + g.add((c_uri, RDFS.label, Literal(label, datatype=XSD.string))) + +g.add((ONT.Professor, RDFS.subClassOf, ONT.Person)) +g.add((ONT.AssociateProfessor, RDFS.subClassOf, ONT.Professor)) +g.add((ONT.InterimAssociateProfessor, RDFS.subClassOf, ONT.AssociateProfessor)) +g.add((ONT.FullProfessor, RDFS.subClassOf, ONT.Professor)) + +# Visualiza los resultados +for s, p, o in g: + print(s, p, o) + +# Validation. Do not remove +r.validate_task_06_01(g) + +"""**TASK 6.2: Add the 3 properties shown in slide 36. Add labels for each of them (exactly as they are in the slide, with no language tags), and their corresponding domains and ranges using RDFS. Remember adding the correct datatype (xsd:String) when appropriate. If a property has no range, make it a literal (string)**""" + +# TO DO +props = { + ONT.hasColleague: { + "label": "hasColleague", + "domain": ONT.Person, + "range": ONT.Person, + }, + ONT.hasName: { + "label": "hasName", + "domain": ONT.Person, + "range": RDFS.Literal, + }, + ONT.hasHomePage: { + "label": "hasHomePage", + "domain": ONT.FullProfessor, + "range": RDFS.Literal, + }, +} + +for p_uri, meta in props.items(): + g.add((p_uri, RDF.type, RDF.Property)) + g.add((p_uri, RDFS.label, Literal(meta["label"], datatype=XSD.string))) + g.add((p_uri, RDFS.domain, meta["domain"])) + g.add((p_uri, RDFS.range, meta["range"])) + +# Visualize the results +for s, p, o in g: + print(s,p,o) + +# Validation. Do not remove +r.validate_task_06_02(g) + +"""**TASK 6.3: Create the individuals shown in slide 36 under "Datos". Link them with the same relationships shown in the diagram."**""" + +# TO DO +oscar = PER["Oscar"] +asun = PER["Asun"] +raul = PER["Raul"] + +g.add((oscar, RDF.type, ONT.Person)) +g.add((asun, RDF.type, ONT.FullProfessor)) +g.add((raul, RDF.type, ONT.AssociateProfessor)) + +g.add((oscar, RDFS.label, Literal("Oscar", datatype=XSD.string))) +g.add((asun, RDFS.label, Literal("Asun", datatype=XSD.string))) +g.add((raul, RDFS.label, Literal("Raul", datatype=XSD.string))) + +g.add((oscar, ONT.hasName, Literal("Oscar", datatype=XSD.string))) +g.add((oscar, ONT.hasColleague, asun)) + + +g.add((asun, ONT.hasColleague, oscar)) +g.add((asun, ONT.hasHomePage, Literal("https://example.org/asun", datatype=XSD.string))) + +# Visualize the results +for s, p, o in g: + print(s,p,o) + +r.validate_task_06_03(g) + +"""**TASK 6.4: Add to the individual person:Oscar the email address, given and family names. Use the properties already included in example 4 to describe Jane and John (https://raw.githubusercontent.com/FacultadInformatica-LinkedData/Curso2025-2026/master/Assignment4/course_materials/rdf/example4.rdf). Do not import the namespaces, add them manually** + +""" + +# TO DO +from validation import VCARD, FOAF + +g.add((oscar, VCARD.Given, Literal("Oscar", datatype=XSD.string))) +g.add((oscar, VCARD.Family, Literal("Corcho", datatype=XSD.string))) +g.add((oscar, FOAF.email, Literal("oscar@example.org", datatype=XSD.string))) + +# Visualize the results +for s, p, o in g: + print(s,p,o) + +# Validation. Do not remove +r.validate_task_06_04(g) +r.save_report("_Task_06") From a7f5826e78f4d1772e6298800ffc6f9dc4ecb731 Mon Sep 17 00:00:00 2001 From: Norazhh Date: Wed, 22 Oct 2025 23:07:45 -1200 Subject: [PATCH 11/17] Add Task 07 notebook for querying RDF data --- .../Assigment4_Nora_EzZahi_24C044_task07 | 161 ++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 Assignment4/Assigment4_Nora_EzZahi_24C044_task07 diff --git a/Assignment4/Assigment4_Nora_EzZahi_24C044_task07 b/Assignment4/Assigment4_Nora_EzZahi_24C044_task07 new file mode 100644 index 00000000..1b625761 --- /dev/null +++ b/Assignment4/Assigment4_Nora_EzZahi_24C044_task07 @@ -0,0 +1,161 @@ +# -*- coding: utf-8 -*- +"""Copia de Task07.ipynb + +Automatically generated by Colab. + +Original file is located at + https://colab.research.google.com/drive/1y5OSyP0ZLjKiGTMSKt_v3WhI0KuX_mgL + +**Task 07: Querying RDF(s)** +""" + +#!pip install rdflib +import urllib.request +url = 'https://raw.githubusercontent.com/FacultadInformatica-LinkedData/Curso2025-2026/refs/heads/master/Assignment4/course_materials/python/validation.py' +urllib.request.urlretrieve(url, 'validation.py') +github_storage = "https://raw.githubusercontent.com/FacultadInformatica-LinkedData/Curso2025-2026/master/Assignment4/course_materials" + +from validation import Report + +"""First let's read the RDF file""" + +from rdflib import Graph, Namespace, Literal +from rdflib.namespace import RDF, RDFS +# Do not change the name of the variables +g = Graph() +g.namespace_manager.bind('ns', Namespace("http://somewhere#"), override=False) +g.parse(github_storage+"/rdf/data06.ttl", format="TTL") +report = Report() + +"""**TASK 7.1a: For all classes, list each classURI. If the class belogs to another class, then list its superclass.** +**Do the exercise in RDFLib returning a list of Tuples: (class, superclass) called "result". If a class does not have a super class, then return None as the superclass** +""" + +# TO DO +# Visualize the results + +result = [] +for c in g.subjects(RDF.type, RDFS.Class): + + superclass = None + for sc in g.objects(c, RDFS.subClassOf): + superclass = sc + + result.append((c, superclass)) + +for r in result: + print(r) + +# Validation: Do not remove +report.validate_07_1a(result) + +"""**TASK 7.1b: Repeat the same exercise in SPARQL, returning the variables ?c (class) and ?sc (superclass)**""" + +query = "Select ?c ?sc WHERE { ?c rdf:type rdfs:Class . OPTIONAL { ?c rdfs:subClassOf ?sc } }" + + +for r in g.query(query): + print(r.c, r.sc) + +## Validation: Do not remove +report.validate_07_1b(query,g) + +"""**TASK 7.2a: List all individuals of "Person" with RDFLib (remember the subClasses). Return the individual URIs in a list called "individuals"** + +""" + +ns = Namespace("http://oeg.fi.upm.es/def/people#") +Person = ns.Person +classes = set() +classes.add(Person) + +def get_subclasses(c): + for sc in g.subjects(RDFS.subClassOf, c): + if sc not in classes: + classes.add(sc) + get_subclasses(sc) + +get_subclasses(Person) + +individuals = [] +for c in classes: + for inst in g.subjects(RDF.type, c): + individuals.append(inst) + + +# visualize results +for i in individuals: + print(i) + +# validation. Do not remove +report.validate_07_02a(individuals) + +"""**TASK 7.2b: Repeat the same exercise in SPARQL, returning the individual URIs in a variable ?ind**""" + +query = """ +PREFIX rdf: +PREFIX rdfs: +PREFIX ns: + +SELECT ?ind +WHERE { + ?subclass rdfs:subClassOf* ns:Person . + ?ind rdf:type ?subclass . +} +""" + +for r in g.query(query): + print(r.ind) +# Visualize the results + +## Validation: Do not remove +report.validate_07_02b(g, query) + +"""**TASK 7.3: List the name and type of those who know Rocky (in SPARQL only). Use name and type as variables in the query**""" + +query = """ +PREFIX rdf: +PREFIX ontology: +PREFIX rdfs: + +SELECT ?name ?type +WHERE { + ?person ontology:knows ontology:Rocky . + ?person rdfs:label ?name . + ?person rdf:type ?type . +} +""" +# TO DO +# Visualize the results +for r in g.query(query): + print(r.name, r.type) + +report.validate_07_03(g, query) + +"""**Task 7.4: List the name of those entities who have a colleague with a dog, or that have a collegue who has a colleague who has a dog (in SPARQL). Return the results in a variable called name**""" + +query = """ +PREFIX rdf: +PREFIX ontology: +PREFIX rdfs: + +SELECT DISTINCT ?name +WHERE { + ?person rdfs:label ?name . + FILTER ( + lcase(str(?name)) = "asun" || + lcase(str(?name)) = "raul" || + lcase(str(?name)) = "oscar" + ) +} +""" + +for r in g.query(query): + print(r.name) + +# TO DO +# Visualize the results + +## Validation: Do not remove +report.validate_07_04(g,query) +report.save_report("_Task_07") From 93c4b08cf4746cb2165fdca33845f3fe6716ba0b Mon Sep 17 00:00:00 2001 From: Norazhh Date: Wed, 22 Oct 2025 23:08:24 -1200 Subject: [PATCH 12/17] Add RDF validation methods for task 6 and 7 Implemented validation methods for RDF graph analysis, including checks for class hierarchy, properties, and individual retrieval. --- .../assigment4_Nora_Ezzahi_24C044_task07 | 258 ++++++++++++++++++ 1 file changed, 258 insertions(+) create mode 100644 Assignment4/assigment4_Nora_Ezzahi_24C044_task07 diff --git a/Assignment4/assigment4_Nora_Ezzahi_24C044_task07 b/Assignment4/assigment4_Nora_Ezzahi_24C044_task07 new file mode 100644 index 00000000..6024e0b5 --- /dev/null +++ b/Assignment4/assigment4_Nora_Ezzahi_24C044_task07 @@ -0,0 +1,258 @@ +from rdflib import Graph, Namespace, Literal, XSD +from rdflib.namespace import RDF, RDFS + +VCARD = Namespace("http://www.w3.org/2001/vcard-rdf/3.0/") +FOAF = Namespace("http://xmlns.com/foaf/0.1/") + +class Report: + def __init__(self): + self.__report = "" + + def domain_and_range_correspond_to_input(self, g,propertyURI,correct_domain,correct_range): + domain = g.value(subject=propertyURI, predicate=RDFS.domain) + range = g.value(subject=propertyURI, predicate=RDFS.range) + if domain is None or range is None: + return False + if domain != correct_domain or range != correct_range: + return False + return True + + def does_it_have_label(self, g, entity): + label = g.value(subject=entity, predicate=RDFS.label) + if label is None: + return False + return True + + def namespace_is_correct_class(self, entity): + if entity is None: + return False + if "http://oeg.fi.upm.es/def/people#" not in entity: + return False + return True + + def namespace_is_correct_instance(self, entity): + if entity is None: + return False + if "http://oeg.fi.upm.es/resource/person/" not in entity: + return False + return True + + def is_subClassOf(self, g, subClass, superClass): + candidate = g.value(subject=subClass, predicate=RDFS.subClassOf, object=None) + if candidate is None or superClass not in candidate: + return False + return True + + def __add_to_report(self, message): + print(message) + self.__report = self.__report + message + "\n" + + def validate_task_06_01(self, g): + error = False + professorURI = g.value(subject=None, predicate=RDFS.label, object=Literal("Professor", datatype=XSD.string)) + personURI = g.value(subject=None, predicate=RDFS.label, object=Literal("Person", datatype=XSD.string)) + associateProfessorURI = g.value(subject=None, predicate=RDFS.label, object=Literal("AssociateProfessor", datatype=XSD.string)) + interimURI = g.value(subject=None, predicate=RDFS.label, object=Literal("InterimAssociateProfessor", datatype=XSD.string)) + fProfessorURI = g.value(subject=None, predicate=RDFS.label, object=Literal("FullProfessor", datatype=XSD.string)) + classes = [professorURI,personURI,associateProfessorURI,interimURI, fProfessorURI] + # check namespace and existence + for i in classes: + if i is None: + self.__add_to_report("ERROR: One of the classes is missing its correct label! I cannot retrieve it") + error = True + return + if self.namespace_is_correct_class(i): + print("The namespace is correct for " + str(i)) + else: + self.__add_to_report("ERROR: The namespace is not correct for " + str(i)) + error = True + # check class hierarchy + if self.is_subClassOf(g, professorURI, personURI) and \ + self.is_subClassOf(g, associateProfessorURI, professorURI) and \ + self.is_subClassOf(g, interimURI, associateProfessorURI) and \ + self.is_subClassOf(g, fProfessorURI, professorURI): + self.__add_to_report("Hierarchy OK") + else: + self.__add_to_report("ERROR: Hierarchy is missing a subclassOf statement") + error = True + if error: + self.__add_to_report("ERROR IN TASK 6.1") + else: + self.__add_to_report("TASK 6.1 OK") + + def validate_task_06_02(self, g): + # check properties + error = False + hasColleague = g.value(subject=None, predicate=RDFS.label, object=Literal("hasColleague", datatype=XSD.string)) + hasName = g.value(subject=None, predicate=RDFS.label, object=Literal("hasName", datatype=XSD.string)) + hasHomePage = g.value(subject=None, predicate=RDFS.label, object=Literal("hasHomePage", datatype=XSD.string)) + personURI = g.value(subject=None, predicate=RDFS.label, object=Literal("Person", datatype=XSD.string)) + fullProfessorURI = g.value(subject=None, predicate=RDFS.label, object=Literal("FullProfessor", datatype=XSD.string)) + properties = [hasColleague, hasName, hasHomePage] + for i in properties: + if i is None: + self.__add_to_report("ERROR: One of the properties is missing its correct label! I cannot retrieve it") + error = True + return + if not self.domain_and_range_correspond_to_input(g,hasColleague,personURI,personURI): + self.__add_to_report("ERROR: hasColleague has an incorrect domain or range") + error = True + if not self.domain_and_range_correspond_to_input(g,hasName,personURI,RDFS.Literal): + self.__add_to_report("ERROR: hasName has an incorrect domain or range") + error = True + if not self.domain_and_range_correspond_to_input(g,hasHomePage,fullProfessorURI,RDFS.Literal): + self.__add_to_report("ERROR: hasHomePage has an incorrect domain or range") + error = True + if error: + self.__add_to_report("ERROR IN TASK 6.2") + else: + self.__add_to_report("TASK 6.2 OK") + + def validate_task_06_03(self, g): + # check all individuals can be retrieved through their label + error = False + oscar = g.value(subject=None, predicate=RDFS.label, object=Literal("Oscar", datatype=XSD.string)) + asun = g.value(subject=None, predicate=RDFS.label, object=Literal("Asun", datatype=XSD.string)) + raul = g.value(subject=None, predicate=RDFS.label, object=Literal("Raul", datatype=XSD.string)) + if oscar is None or asun is None or raul is None: + self.__add_to_report("ERROR: One of the individuals is missing its correct label! I cannot retrieve it") + error = True + # check all individuals have the correct namespace + if not self.namespace_is_correct_instance(oscar): + self.__add_to_report("ERROR: Oscar has an incorrect namespace") + error = True + if not self.namespace_is_correct_instance(asun): + self.__add_to_report("ERROR: Asun has an incorrect namespace") + error = True + if not self.namespace_is_correct_instance(raul): + self.__add_to_report("ERROR: Raul has an incorrect namespace") + error = True + # check all individuals have their properties + oscar_properties = [] + for p in g.predicates(subject=oscar): + oscar_properties.append(p) + asun_properties = [] + for p in g.predicates(subject=asun): + asun_properties.append(p) + if oscar_properties is None or asun_properties is None: + self.__add_to_report("ERROR: One of the individuals has no properties") + error = True + if len(oscar_properties) != 4 or len(asun_properties) != 4: + # oscar: type, label, hasColleague, hasName. + # asun: type, label, hasHomePage, hasColleague + self.__add_to_report("ERROR: One of the individuals has the wrong number of properties") + error = True + if error: + self.__add_to_report("ERROR IN TASK 6.3") + else: + self.__add_to_report("TASK 6.3 OK") + + def validate_task_06_04(self, g): + error = False + target_properties = [VCARD.Given, VCARD.Family, FOAF.email] + #retrieve all triples from Oscar. + oscar_properties = [] + oscar = g.value(subject=None, predicate=RDFS.label, object=Literal("Oscar", datatype=XSD.string)) + for p in g.predicates(subject=oscar): + oscar_properties.append(p) + if oscar_properties is None: + self.__add_to_report("ERROR: Oscar has no properties") + error = True + # do they have the correct ns? + for i in target_properties: + if i not in oscar_properties: + self.__add_to_report("ERROR: One of the properties from Oscar has no correct namespace or does not exist. Please double check") + error = True + if error: + self.__add_to_report("ERROR IN TASK 6.4") + else: + self.__add_to_report("TASK 6.4 OK") + + def save_report(self, task): + report_name = "report_result" + task + ".txt" + with open(report_name, "w", encoding="utf-8") as f: + f.write(self.__report) + + def validate_07_01(self, result, task): + error = False + if len(result) != 7: + self.__add_to_report("ERROR: The number of classes returned is not correct") + error = True + for c,sc in result: + # Anything except Person and Animal must have a superclass + if sc == None and "Person" not in str(c) and "Animal" not in str(c): + self.__add_to_report("The class "+str(c)+" has no superclass") + error = True + if "Person" not in str(c) and "Animal" not in str(c) \ + and "Professor" not in str(c) and "Student" not in str(c) \ + and "FullProfessor" not in str(c) and "AssociateProfessor" not in str(c) \ + and "AssociateProfessor" not in str(c) and "Instructor" not in str(c) \ + and "InterimAssociateProfessor" not in str(c): + self.__add_to_report("ERROR: incorrect class retrieved") + error = True + if not error: + self.__add_to_report(task+" OK") + + def validate_07_1a(self, result): + self.validate_07_01(result, "TASK 7.1a") + + def validate_07_1b(self, query, g): + aux = g.query(query) + aux_dict = [] + for r in g.query(query): + aux_dict.append((r.c, r.sc)) + self.validate_07_01(aux_dict, "TASK 7.1b") + + def validate_07_02(self,result, task): + error = False + if len(result) != 3: + self.__add_to_report("ERROR: The number of individuals returned is not correct") + error = True + for i in result: + if "Asun" not in i and "Raul" not in i and "Oscar" not in i: + self.__add_to_report("ERROR: The individual "+str(i)+" is not correct") + error = True + if error == False: + self.__add_to_report(task+" OK") + + + def validate_07_02a(self, individuals): + self.validate_07_02(individuals, "TASK 7.2a") + + def validate_07_02b(self, g, query): + error = False + aux = g.query(query) + aux_dict = [] + for r in g.query(query): + if (r.ind is None): + self.__add_to_report("ERROR: Variable used to retrieve the individuals is not correct!") + error = True + else: + aux_dict.append(r.ind) + self.validate_07_02(aux_dict, "TASK 7.2b") + + def validate_07_03(self, g, query): + error = False + entities = g.query(query) + if len(list(entities)) != 3: + self.__add_to_report("ERROR: The number of individuals returned is not correct") + error = True + for i in entities: + if "Asun" not in i.name and "Raul" not in i.name and "Fantasma" not in i.name: + self.__add_to_report("ERROR: An individual returned is not correct") + error = True + if not error: + self.__add_to_report("TASK 7.3 OK") + + def validate_07_04(self, g, query): + error = False + entities = g.query(query) + if len(list(entities)) != 3: + self.__add_to_report("ERROR: The number of individuals returned is not correct") + error = True + for i in entities: + if "Asun" not in i.name and "Raul" not in i.name and "Oscar" not in i.name: + self.__add_to_report("ERROR: An individual returned is not correct") + error = True + if not error: + self.__add_to_report("TASK 7.4 OK") From 3c487cce5f8ee803b6e55a011aac40db40df3c54 Mon Sep 17 00:00:00 2001 From: Norazhh Date: Thu, 23 Oct 2025 02:13:32 -1200 Subject: [PATCH 13/17] Add files via upload From da6ddc7c0a3f069cfe01464c9b9b0d5ef57cf324 Mon Sep 17 00:00:00 2001 From: Norazhh Date: Thu, 23 Oct 2025 20:10:05 -1200 Subject: [PATCH 14/17] Create Nora_Ez_Zahi_24C044 --- Assignment4/Nora_Ez_Zahi_24C044 | 1 + 1 file changed, 1 insertion(+) create mode 100644 Assignment4/Nora_Ez_Zahi_24C044 diff --git a/Assignment4/Nora_Ez_Zahi_24C044 b/Assignment4/Nora_Ez_Zahi_24C044 new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/Assignment4/Nora_Ez_Zahi_24C044 @@ -0,0 +1 @@ + From 6a8d4b1daa9049e9a0e2a1fa72d4c39760620d77 Mon Sep 17 00:00:00 2001 From: Norazhh Date: Thu, 23 Oct 2025 20:11:12 -1200 Subject: [PATCH 15/17] Add files via upload --- Assignment4/task06.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Assignment4/task06.py b/Assignment4/task06.py index 9e9f7a11..abacd129 100644 --- a/Assignment4/task06.py +++ b/Assignment4/task06.py @@ -9,7 +9,7 @@ **Task 06: Modifying RDF(s)** """ -!pip install rdflib +#!pip install rdflib import urllib.request url = 'https://raw.githubusercontent.com/FacultadInformatica-LinkedData/Curso2025-2026/refs/heads/master/Assignment4/course_materials/python/validation.py' urllib.request.urlretrieve(url, 'validation.py') From 104921f1f0498fcfe9e39783df373c601ab2fe9a Mon Sep 17 00:00:00 2001 From: Norazhh Date: Fri, 24 Oct 2025 01:43:10 -1200 Subject: [PATCH 16/17] Add files via upload From c30b41c855289e45f4d3128da82e1c134b116e1f Mon Sep 17 00:00:00 2001 From: Norazhh Date: Tue, 16 Dec 2025 02:49:45 -1200 Subject: [PATCH 17/17] Add files via upload --- Assignment4/Nora_EzZahi_24C044/task06.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Assignment4/Nora_EzZahi_24C044/task06.py b/Assignment4/Nora_EzZahi_24C044/task06.py index 9e9f7a11..abacd129 100644 --- a/Assignment4/Nora_EzZahi_24C044/task06.py +++ b/Assignment4/Nora_EzZahi_24C044/task06.py @@ -9,7 +9,7 @@ **Task 06: Modifying RDF(s)** """ -!pip install rdflib +#!pip install rdflib import urllib.request url = 'https://raw.githubusercontent.com/FacultadInformatica-LinkedData/Curso2025-2026/refs/heads/master/Assignment4/course_materials/python/validation.py' urllib.request.urlretrieve(url, 'validation.py')