From c39c1728821520db9c17cdfc8705428f0f252695 Mon Sep 17 00:00:00 2001 From: PedroGarcia Date: Fri, 24 Oct 2025 15:44:23 +0200 Subject: [PATCH 1/9] Add files via upload --- .../Pedro Garc\303\255a 24C017/task06.py" | 129 +++++++++ .../Pedro Garc\303\255a 24C017/task07.py" | 135 +++++++++ .../Pedro Garc\303\255a 24C017/validation.py" | 258 ++++++++++++++++++ 3 files changed, 522 insertions(+) create mode 100644 "Assignment4/Pedro Garc\303\255a 24C017/task06.py" create mode 100644 "Assignment4/Pedro Garc\303\255a 24C017/task07.py" create mode 100644 "Assignment4/Pedro Garc\303\255a 24C017/validation.py" diff --git "a/Assignment4/Pedro Garc\303\255a 24C017/task06.py" "b/Assignment4/Pedro Garc\303\255a 24C017/task06.py" new file mode 100644 index 00000000..482f9f62 --- /dev/null +++ "b/Assignment4/Pedro Garc\303\255a 24C017/task06.py" @@ -0,0 +1,129 @@ +# -*- coding: utf-8 -*- +"""Task06.ipynb + +Automatically generated by Colab. + +Original file is located at + https://colab.research.google.com/drive/10xc6w_MgKVk0SsWYuKegde4a8MUxcfDg + +**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.**""" + +ontology = Namespace("http://www.oeg-upm.net/Ontology#") +person = Namespace("http://www.oeg-upm.net/Ontology#") +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** + +""" + +#Person +g.add((ns.Person, RDF.type, RDFS.Class)) +g.add((ns.Person, RDFS.label, Literal("Person", datatype=XSD.string))) +#Professor +g.add((ns.Professor, RDF.type, RDFS.Class)) +g.add((ns.Professor, RDFS.subClassOf, ns.Person)) +g.add((ns.Professor, RDFS.label, Literal("Professor", datatype=XSD.string))) +#FullProfessor +g.add((ns.FullProfessor, RDF.type, RDFS.Class)) +g.add((ns.FullProfessor, RDFS.subClassOf, ns.Professor)) +g.add((ns.FullProfessor, RDFS.label, Literal("FullProfessor", datatype=XSD.string))) +#AssociateProfessor +g.add((ns.AssociateProfessor, RDF.type, RDFS.Class)) +g.add((ns.AssociateProfessor, RDFS.subClassOf, ns.Professor)) +g.add((ns.AssociateProfessor, RDFS.label, Literal("AssociateProfessor", datatype=XSD.string))) +#InterimAssociateProfessor +g.add((ns.InterimAssociateProfessor, RDF.type, RDFS.Class)) +g.add((ns.InterimAssociateProfessor, RDFS.subClassOf, ns.AssociateProfessor)) +g.add((ns.InterimAssociateProfessor, RDFS.label, Literal("InterimAssociateProfessor", datatype=XSD.string))) +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)**""" + +#HasColleague +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)) +#HasName +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)) +#HasHomePage +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."**""" + +Datos = Namespace("http://oeg.fi.upm.es/resource/person/") +#Oscar +g.add((Datos.Oscar, RDF.type, ns.AssociateProfessor)) +g.add((Datos.Oscar, RDFS.label, Literal("Oscar", datatype=XSD.string))) +g.add((Datos.Oscar, ns.hasName, Literal("Oscar Corcho García", datatype=XSD.string))) +g.add((Datos.Oscar, ns.hasColleague, Datos.Asun)) +#Raul +g.add((Datos.Raul, RDF.type, ns.InterimAssociateProfessor)) +g.add((Datos.Raul, RDFS.label, Literal("Raul", datatype=XSD.string))) +#Asun +g.add((Datos.Asun, RDF.type, ns.FullProfessor)) +g.add((Datos.Asun, RDFS.label, Literal("Asun", datatype=XSD.string))) +g.add((Datos.Asun, ns.hasColleague, Datos.Raul)) +g.add((Datos.Asun, ns.hasHomePage, Literal("http://oeg-upm.net/"))) + +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** + +""" + +vcard = Namespace("http://www.w3.org/2001/vcard-rdf/3.0/") +foaf = Namespace("http://xmlns.com/foaf/0.1/") +g.add((Datos.Oscar, vcard.Given, Literal("Oscar", datatype=XSD.string))) +g.add((Datos.Oscar, vcard.Family, Literal("Corcho García", datatype=XSD.string))) +g.add((Datos.Oscar, foaf.email, Literal("ocorcho@fi.upm.es", datatype=XSD.string))) +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/Pedro Garc\303\255a 24C017/task07.py" "b/Assignment4/Pedro Garc\303\255a 24C017/task07.py" new file mode 100644 index 00000000..51b757da --- /dev/null +++ "b/Assignment4/Pedro Garc\303\255a 24C017/task07.py" @@ -0,0 +1,135 @@ +# -*- coding: utf-8 -*- +"""Task07.ipynb + +Automatically generated by Colab. + +Original file is located at + https://colab.research.google.com/drive/1zvX2Bxt__j1SBu23wqpB-QcOs58Tz6_L + +**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** +""" + +result = [] +for clase in g.subjects(RDF.type, RDFS.Class): + superclass = None + for sclass in g.objects(clase, RDFS.subClassOf): + superclass = sclass + result.append((clase, 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 a 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#") + +# variable to return +individuals = [] +def person_subclass(clase): + if clase == ns.Person: + return True + for s, p, o in g.triples((clase, RDFS.subClassOf, None)): + if person_subclass(o): + return True + else: + return False +for s, p, o in g.triples((None, RDF.type, None)): + if o == ns.Person or person_subclass(o) == True: + individuals.append(s) +# 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 people: SELECT DISTINCT ?ind WHERE { ?class rdfs:subClassOf* people:Person . ?ind a ?class .}" +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 people: +PREFIX rdfs: +SELECT ?name ?type WHERE { + ?person people:knows people: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) + +## Validation: Do not remove +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 people: +SELECT DISTINCT ?name WHERE { + ?person rdfs:label ?name . + { + ?person people:hasColleague ?petowner . + ?petowner people:hasColleague ?colleague . + ?colleague people:ownsPet ?pet . + } UNION { + ?person people:hasColleague ?petowner . + ?petowner people:ownsPet ?pet . + } +} +""" + +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/Pedro Garc\303\255a 24C017/validation.py" "b/Assignment4/Pedro Garc\303\255a 24C017/validation.py" new file mode 100644 index 00000000..09bea35e --- /dev/null +++ "b/Assignment4/Pedro Garc\303\255a 24C017/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 1ccb95b89514046c69a6a27d7910cef722478d05 Mon Sep 17 00:00:00 2001 From: PedroGarcia Date: Sun, 26 Oct 2025 12:27:25 +0100 Subject: [PATCH 2/9] =?UTF-8?q?Assignment=204=20Pedro=20Garc=C3=ADa=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "Pedro Garc\303\255a 24C017/task06.py" | 129 +++++++++++ "Pedro Garc\303\255a 24C017/task07.py" | 135 +++++++++++ "Pedro Garc\303\255a 24C017/validation.py" | 258 +++++++++++++++++++++ 3 files changed, 522 insertions(+) create mode 100644 "Pedro Garc\303\255a 24C017/task06.py" create mode 100644 "Pedro Garc\303\255a 24C017/task07.py" create mode 100644 "Pedro Garc\303\255a 24C017/validation.py" diff --git "a/Pedro Garc\303\255a 24C017/task06.py" "b/Pedro Garc\303\255a 24C017/task06.py" new file mode 100644 index 00000000..482f9f62 --- /dev/null +++ "b/Pedro Garc\303\255a 24C017/task06.py" @@ -0,0 +1,129 @@ +# -*- coding: utf-8 -*- +"""Task06.ipynb + +Automatically generated by Colab. + +Original file is located at + https://colab.research.google.com/drive/10xc6w_MgKVk0SsWYuKegde4a8MUxcfDg + +**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.**""" + +ontology = Namespace("http://www.oeg-upm.net/Ontology#") +person = Namespace("http://www.oeg-upm.net/Ontology#") +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** + +""" + +#Person +g.add((ns.Person, RDF.type, RDFS.Class)) +g.add((ns.Person, RDFS.label, Literal("Person", datatype=XSD.string))) +#Professor +g.add((ns.Professor, RDF.type, RDFS.Class)) +g.add((ns.Professor, RDFS.subClassOf, ns.Person)) +g.add((ns.Professor, RDFS.label, Literal("Professor", datatype=XSD.string))) +#FullProfessor +g.add((ns.FullProfessor, RDF.type, RDFS.Class)) +g.add((ns.FullProfessor, RDFS.subClassOf, ns.Professor)) +g.add((ns.FullProfessor, RDFS.label, Literal("FullProfessor", datatype=XSD.string))) +#AssociateProfessor +g.add((ns.AssociateProfessor, RDF.type, RDFS.Class)) +g.add((ns.AssociateProfessor, RDFS.subClassOf, ns.Professor)) +g.add((ns.AssociateProfessor, RDFS.label, Literal("AssociateProfessor", datatype=XSD.string))) +#InterimAssociateProfessor +g.add((ns.InterimAssociateProfessor, RDF.type, RDFS.Class)) +g.add((ns.InterimAssociateProfessor, RDFS.subClassOf, ns.AssociateProfessor)) +g.add((ns.InterimAssociateProfessor, RDFS.label, Literal("InterimAssociateProfessor", datatype=XSD.string))) +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)**""" + +#HasColleague +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)) +#HasName +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)) +#HasHomePage +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."**""" + +Datos = Namespace("http://oeg.fi.upm.es/resource/person/") +#Oscar +g.add((Datos.Oscar, RDF.type, ns.AssociateProfessor)) +g.add((Datos.Oscar, RDFS.label, Literal("Oscar", datatype=XSD.string))) +g.add((Datos.Oscar, ns.hasName, Literal("Oscar Corcho García", datatype=XSD.string))) +g.add((Datos.Oscar, ns.hasColleague, Datos.Asun)) +#Raul +g.add((Datos.Raul, RDF.type, ns.InterimAssociateProfessor)) +g.add((Datos.Raul, RDFS.label, Literal("Raul", datatype=XSD.string))) +#Asun +g.add((Datos.Asun, RDF.type, ns.FullProfessor)) +g.add((Datos.Asun, RDFS.label, Literal("Asun", datatype=XSD.string))) +g.add((Datos.Asun, ns.hasColleague, Datos.Raul)) +g.add((Datos.Asun, ns.hasHomePage, Literal("http://oeg-upm.net/"))) + +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** + +""" + +vcard = Namespace("http://www.w3.org/2001/vcard-rdf/3.0/") +foaf = Namespace("http://xmlns.com/foaf/0.1/") +g.add((Datos.Oscar, vcard.Given, Literal("Oscar", datatype=XSD.string))) +g.add((Datos.Oscar, vcard.Family, Literal("Corcho García", datatype=XSD.string))) +g.add((Datos.Oscar, foaf.email, Literal("ocorcho@fi.upm.es", datatype=XSD.string))) +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/Pedro Garc\303\255a 24C017/task07.py" "b/Pedro Garc\303\255a 24C017/task07.py" new file mode 100644 index 00000000..51b757da --- /dev/null +++ "b/Pedro Garc\303\255a 24C017/task07.py" @@ -0,0 +1,135 @@ +# -*- coding: utf-8 -*- +"""Task07.ipynb + +Automatically generated by Colab. + +Original file is located at + https://colab.research.google.com/drive/1zvX2Bxt__j1SBu23wqpB-QcOs58Tz6_L + +**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** +""" + +result = [] +for clase in g.subjects(RDF.type, RDFS.Class): + superclass = None + for sclass in g.objects(clase, RDFS.subClassOf): + superclass = sclass + result.append((clase, 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 a 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#") + +# variable to return +individuals = [] +def person_subclass(clase): + if clase == ns.Person: + return True + for s, p, o in g.triples((clase, RDFS.subClassOf, None)): + if person_subclass(o): + return True + else: + return False +for s, p, o in g.triples((None, RDF.type, None)): + if o == ns.Person or person_subclass(o) == True: + individuals.append(s) +# 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 people: SELECT DISTINCT ?ind WHERE { ?class rdfs:subClassOf* people:Person . ?ind a ?class .}" +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 people: +PREFIX rdfs: +SELECT ?name ?type WHERE { + ?person people:knows people: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) + +## Validation: Do not remove +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 people: +SELECT DISTINCT ?name WHERE { + ?person rdfs:label ?name . + { + ?person people:hasColleague ?petowner . + ?petowner people:hasColleague ?colleague . + ?colleague people:ownsPet ?pet . + } UNION { + ?person people:hasColleague ?petowner . + ?petowner people:ownsPet ?pet . + } +} +""" + +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/Pedro Garc\303\255a 24C017/validation.py" "b/Pedro Garc\303\255a 24C017/validation.py" new file mode 100644 index 00000000..6024e0b5 --- /dev/null +++ "b/Pedro Garc\303\255a 24C017/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 a1e57c155cc8eadcdb31e351d133d8bfde0da8f1 Mon Sep 17 00:00:00 2001 From: PedroGarcia Date: Sun, 26 Oct 2025 12:42:21 +0100 Subject: [PATCH 3/9] =?UTF-8?q?Delete=20Pedro=20Garc=C3=ADa=2024C017=20dir?= =?UTF-8?q?ectory?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "Pedro Garc\303\255a 24C017/task06.py" | 129 ----------- "Pedro Garc\303\255a 24C017/task07.py" | 135 ----------- "Pedro Garc\303\255a 24C017/validation.py" | 258 --------------------- 3 files changed, 522 deletions(-) delete mode 100644 "Pedro Garc\303\255a 24C017/task06.py" delete mode 100644 "Pedro Garc\303\255a 24C017/task07.py" delete mode 100644 "Pedro Garc\303\255a 24C017/validation.py" diff --git "a/Pedro Garc\303\255a 24C017/task06.py" "b/Pedro Garc\303\255a 24C017/task06.py" deleted file mode 100644 index 482f9f62..00000000 --- "a/Pedro Garc\303\255a 24C017/task06.py" +++ /dev/null @@ -1,129 +0,0 @@ -# -*- coding: utf-8 -*- -"""Task06.ipynb - -Automatically generated by Colab. - -Original file is located at - https://colab.research.google.com/drive/10xc6w_MgKVk0SsWYuKegde4a8MUxcfDg - -**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.**""" - -ontology = Namespace("http://www.oeg-upm.net/Ontology#") -person = Namespace("http://www.oeg-upm.net/Ontology#") -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** - -""" - -#Person -g.add((ns.Person, RDF.type, RDFS.Class)) -g.add((ns.Person, RDFS.label, Literal("Person", datatype=XSD.string))) -#Professor -g.add((ns.Professor, RDF.type, RDFS.Class)) -g.add((ns.Professor, RDFS.subClassOf, ns.Person)) -g.add((ns.Professor, RDFS.label, Literal("Professor", datatype=XSD.string))) -#FullProfessor -g.add((ns.FullProfessor, RDF.type, RDFS.Class)) -g.add((ns.FullProfessor, RDFS.subClassOf, ns.Professor)) -g.add((ns.FullProfessor, RDFS.label, Literal("FullProfessor", datatype=XSD.string))) -#AssociateProfessor -g.add((ns.AssociateProfessor, RDF.type, RDFS.Class)) -g.add((ns.AssociateProfessor, RDFS.subClassOf, ns.Professor)) -g.add((ns.AssociateProfessor, RDFS.label, Literal("AssociateProfessor", datatype=XSD.string))) -#InterimAssociateProfessor -g.add((ns.InterimAssociateProfessor, RDF.type, RDFS.Class)) -g.add((ns.InterimAssociateProfessor, RDFS.subClassOf, ns.AssociateProfessor)) -g.add((ns.InterimAssociateProfessor, RDFS.label, Literal("InterimAssociateProfessor", datatype=XSD.string))) -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)**""" - -#HasColleague -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)) -#HasName -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)) -#HasHomePage -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."**""" - -Datos = Namespace("http://oeg.fi.upm.es/resource/person/") -#Oscar -g.add((Datos.Oscar, RDF.type, ns.AssociateProfessor)) -g.add((Datos.Oscar, RDFS.label, Literal("Oscar", datatype=XSD.string))) -g.add((Datos.Oscar, ns.hasName, Literal("Oscar Corcho García", datatype=XSD.string))) -g.add((Datos.Oscar, ns.hasColleague, Datos.Asun)) -#Raul -g.add((Datos.Raul, RDF.type, ns.InterimAssociateProfessor)) -g.add((Datos.Raul, RDFS.label, Literal("Raul", datatype=XSD.string))) -#Asun -g.add((Datos.Asun, RDF.type, ns.FullProfessor)) -g.add((Datos.Asun, RDFS.label, Literal("Asun", datatype=XSD.string))) -g.add((Datos.Asun, ns.hasColleague, Datos.Raul)) -g.add((Datos.Asun, ns.hasHomePage, Literal("http://oeg-upm.net/"))) - -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** - -""" - -vcard = Namespace("http://www.w3.org/2001/vcard-rdf/3.0/") -foaf = Namespace("http://xmlns.com/foaf/0.1/") -g.add((Datos.Oscar, vcard.Given, Literal("Oscar", datatype=XSD.string))) -g.add((Datos.Oscar, vcard.Family, Literal("Corcho García", datatype=XSD.string))) -g.add((Datos.Oscar, foaf.email, Literal("ocorcho@fi.upm.es", datatype=XSD.string))) -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/Pedro Garc\303\255a 24C017/task07.py" "b/Pedro Garc\303\255a 24C017/task07.py" deleted file mode 100644 index 51b757da..00000000 --- "a/Pedro Garc\303\255a 24C017/task07.py" +++ /dev/null @@ -1,135 +0,0 @@ -# -*- coding: utf-8 -*- -"""Task07.ipynb - -Automatically generated by Colab. - -Original file is located at - https://colab.research.google.com/drive/1zvX2Bxt__j1SBu23wqpB-QcOs58Tz6_L - -**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** -""" - -result = [] -for clase in g.subjects(RDF.type, RDFS.Class): - superclass = None - for sclass in g.objects(clase, RDFS.subClassOf): - superclass = sclass - result.append((clase, 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 a 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#") - -# variable to return -individuals = [] -def person_subclass(clase): - if clase == ns.Person: - return True - for s, p, o in g.triples((clase, RDFS.subClassOf, None)): - if person_subclass(o): - return True - else: - return False -for s, p, o in g.triples((None, RDF.type, None)): - if o == ns.Person or person_subclass(o) == True: - individuals.append(s) -# 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 people: SELECT DISTINCT ?ind WHERE { ?class rdfs:subClassOf* people:Person . ?ind a ?class .}" -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 people: -PREFIX rdfs: -SELECT ?name ?type WHERE { - ?person people:knows people: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) - -## Validation: Do not remove -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 people: -SELECT DISTINCT ?name WHERE { - ?person rdfs:label ?name . - { - ?person people:hasColleague ?petowner . - ?petowner people:hasColleague ?colleague . - ?colleague people:ownsPet ?pet . - } UNION { - ?person people:hasColleague ?petowner . - ?petowner people:ownsPet ?pet . - } -} -""" - -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/Pedro Garc\303\255a 24C017/validation.py" "b/Pedro Garc\303\255a 24C017/validation.py" deleted file mode 100644 index 6024e0b5..00000000 --- "a/Pedro Garc\303\255a 24C017/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 323ee9b028e5018ee755d07520ba55d35f857845 Mon Sep 17 00:00:00 2001 From: PedroGarcia Date: Sun, 26 Oct 2025 12:44:09 +0100 Subject: [PATCH 4/9] =?UTF-8?q?Delete=20Assignment4/Pedro=20Garc=C3=ADa=20?= =?UTF-8?q?24C017=20directory?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Pedro Garc\303\255a 24C017/task06.py" | 129 --------- .../Pedro Garc\303\255a 24C017/task07.py" | 135 --------- .../Pedro Garc\303\255a 24C017/validation.py" | 258 ------------------ 3 files changed, 522 deletions(-) delete mode 100644 "Assignment4/Pedro Garc\303\255a 24C017/task06.py" delete mode 100644 "Assignment4/Pedro Garc\303\255a 24C017/task07.py" delete mode 100644 "Assignment4/Pedro Garc\303\255a 24C017/validation.py" diff --git "a/Assignment4/Pedro Garc\303\255a 24C017/task06.py" "b/Assignment4/Pedro Garc\303\255a 24C017/task06.py" deleted file mode 100644 index 482f9f62..00000000 --- "a/Assignment4/Pedro Garc\303\255a 24C017/task06.py" +++ /dev/null @@ -1,129 +0,0 @@ -# -*- coding: utf-8 -*- -"""Task06.ipynb - -Automatically generated by Colab. - -Original file is located at - https://colab.research.google.com/drive/10xc6w_MgKVk0SsWYuKegde4a8MUxcfDg - -**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.**""" - -ontology = Namespace("http://www.oeg-upm.net/Ontology#") -person = Namespace("http://www.oeg-upm.net/Ontology#") -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** - -""" - -#Person -g.add((ns.Person, RDF.type, RDFS.Class)) -g.add((ns.Person, RDFS.label, Literal("Person", datatype=XSD.string))) -#Professor -g.add((ns.Professor, RDF.type, RDFS.Class)) -g.add((ns.Professor, RDFS.subClassOf, ns.Person)) -g.add((ns.Professor, RDFS.label, Literal("Professor", datatype=XSD.string))) -#FullProfessor -g.add((ns.FullProfessor, RDF.type, RDFS.Class)) -g.add((ns.FullProfessor, RDFS.subClassOf, ns.Professor)) -g.add((ns.FullProfessor, RDFS.label, Literal("FullProfessor", datatype=XSD.string))) -#AssociateProfessor -g.add((ns.AssociateProfessor, RDF.type, RDFS.Class)) -g.add((ns.AssociateProfessor, RDFS.subClassOf, ns.Professor)) -g.add((ns.AssociateProfessor, RDFS.label, Literal("AssociateProfessor", datatype=XSD.string))) -#InterimAssociateProfessor -g.add((ns.InterimAssociateProfessor, RDF.type, RDFS.Class)) -g.add((ns.InterimAssociateProfessor, RDFS.subClassOf, ns.AssociateProfessor)) -g.add((ns.InterimAssociateProfessor, RDFS.label, Literal("InterimAssociateProfessor", datatype=XSD.string))) -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)**""" - -#HasColleague -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)) -#HasName -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)) -#HasHomePage -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."**""" - -Datos = Namespace("http://oeg.fi.upm.es/resource/person/") -#Oscar -g.add((Datos.Oscar, RDF.type, ns.AssociateProfessor)) -g.add((Datos.Oscar, RDFS.label, Literal("Oscar", datatype=XSD.string))) -g.add((Datos.Oscar, ns.hasName, Literal("Oscar Corcho García", datatype=XSD.string))) -g.add((Datos.Oscar, ns.hasColleague, Datos.Asun)) -#Raul -g.add((Datos.Raul, RDF.type, ns.InterimAssociateProfessor)) -g.add((Datos.Raul, RDFS.label, Literal("Raul", datatype=XSD.string))) -#Asun -g.add((Datos.Asun, RDF.type, ns.FullProfessor)) -g.add((Datos.Asun, RDFS.label, Literal("Asun", datatype=XSD.string))) -g.add((Datos.Asun, ns.hasColleague, Datos.Raul)) -g.add((Datos.Asun, ns.hasHomePage, Literal("http://oeg-upm.net/"))) - -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** - -""" - -vcard = Namespace("http://www.w3.org/2001/vcard-rdf/3.0/") -foaf = Namespace("http://xmlns.com/foaf/0.1/") -g.add((Datos.Oscar, vcard.Given, Literal("Oscar", datatype=XSD.string))) -g.add((Datos.Oscar, vcard.Family, Literal("Corcho García", datatype=XSD.string))) -g.add((Datos.Oscar, foaf.email, Literal("ocorcho@fi.upm.es", datatype=XSD.string))) -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/Pedro Garc\303\255a 24C017/task07.py" "b/Assignment4/Pedro Garc\303\255a 24C017/task07.py" deleted file mode 100644 index 51b757da..00000000 --- "a/Assignment4/Pedro Garc\303\255a 24C017/task07.py" +++ /dev/null @@ -1,135 +0,0 @@ -# -*- coding: utf-8 -*- -"""Task07.ipynb - -Automatically generated by Colab. - -Original file is located at - https://colab.research.google.com/drive/1zvX2Bxt__j1SBu23wqpB-QcOs58Tz6_L - -**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** -""" - -result = [] -for clase in g.subjects(RDF.type, RDFS.Class): - superclass = None - for sclass in g.objects(clase, RDFS.subClassOf): - superclass = sclass - result.append((clase, 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 a 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#") - -# variable to return -individuals = [] -def person_subclass(clase): - if clase == ns.Person: - return True - for s, p, o in g.triples((clase, RDFS.subClassOf, None)): - if person_subclass(o): - return True - else: - return False -for s, p, o in g.triples((None, RDF.type, None)): - if o == ns.Person or person_subclass(o) == True: - individuals.append(s) -# 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 people: SELECT DISTINCT ?ind WHERE { ?class rdfs:subClassOf* people:Person . ?ind a ?class .}" -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 people: -PREFIX rdfs: -SELECT ?name ?type WHERE { - ?person people:knows people: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) - -## Validation: Do not remove -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 people: -SELECT DISTINCT ?name WHERE { - ?person rdfs:label ?name . - { - ?person people:hasColleague ?petowner . - ?petowner people:hasColleague ?colleague . - ?colleague people:ownsPet ?pet . - } UNION { - ?person people:hasColleague ?petowner . - ?petowner people:ownsPet ?pet . - } -} -""" - -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/Pedro Garc\303\255a 24C017/validation.py" "b/Assignment4/Pedro Garc\303\255a 24C017/validation.py" deleted file mode 100644 index 09bea35e..00000000 --- "a/Assignment4/Pedro Garc\303\255a 24C017/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 18633e07d432636765937102e4da7361d8cbe287 Mon Sep 17 00:00:00 2001 From: PedroGarcia Date: Sun, 26 Oct 2025 12:44:58 +0100 Subject: [PATCH 5/9] =?UTF-8?q?Assignment=204=20Pedro=20Garc=C3=ADa=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Pedro Garc\303\255a 24C017/task06.py" | 129 +++++++++ .../Pedro Garc\303\255a 24C017/task07.py" | 135 +++++++++ .../Pedro Garc\303\255a 24C017/validation.py" | 258 ++++++++++++++++++ 3 files changed, 522 insertions(+) create mode 100644 "Assignment4/Pedro Garc\303\255a 24C017/task06.py" create mode 100644 "Assignment4/Pedro Garc\303\255a 24C017/task07.py" create mode 100644 "Assignment4/Pedro Garc\303\255a 24C017/validation.py" diff --git "a/Assignment4/Pedro Garc\303\255a 24C017/task06.py" "b/Assignment4/Pedro Garc\303\255a 24C017/task06.py" new file mode 100644 index 00000000..482f9f62 --- /dev/null +++ "b/Assignment4/Pedro Garc\303\255a 24C017/task06.py" @@ -0,0 +1,129 @@ +# -*- coding: utf-8 -*- +"""Task06.ipynb + +Automatically generated by Colab. + +Original file is located at + https://colab.research.google.com/drive/10xc6w_MgKVk0SsWYuKegde4a8MUxcfDg + +**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.**""" + +ontology = Namespace("http://www.oeg-upm.net/Ontology#") +person = Namespace("http://www.oeg-upm.net/Ontology#") +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** + +""" + +#Person +g.add((ns.Person, RDF.type, RDFS.Class)) +g.add((ns.Person, RDFS.label, Literal("Person", datatype=XSD.string))) +#Professor +g.add((ns.Professor, RDF.type, RDFS.Class)) +g.add((ns.Professor, RDFS.subClassOf, ns.Person)) +g.add((ns.Professor, RDFS.label, Literal("Professor", datatype=XSD.string))) +#FullProfessor +g.add((ns.FullProfessor, RDF.type, RDFS.Class)) +g.add((ns.FullProfessor, RDFS.subClassOf, ns.Professor)) +g.add((ns.FullProfessor, RDFS.label, Literal("FullProfessor", datatype=XSD.string))) +#AssociateProfessor +g.add((ns.AssociateProfessor, RDF.type, RDFS.Class)) +g.add((ns.AssociateProfessor, RDFS.subClassOf, ns.Professor)) +g.add((ns.AssociateProfessor, RDFS.label, Literal("AssociateProfessor", datatype=XSD.string))) +#InterimAssociateProfessor +g.add((ns.InterimAssociateProfessor, RDF.type, RDFS.Class)) +g.add((ns.InterimAssociateProfessor, RDFS.subClassOf, ns.AssociateProfessor)) +g.add((ns.InterimAssociateProfessor, RDFS.label, Literal("InterimAssociateProfessor", datatype=XSD.string))) +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)**""" + +#HasColleague +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)) +#HasName +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)) +#HasHomePage +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."**""" + +Datos = Namespace("http://oeg.fi.upm.es/resource/person/") +#Oscar +g.add((Datos.Oscar, RDF.type, ns.AssociateProfessor)) +g.add((Datos.Oscar, RDFS.label, Literal("Oscar", datatype=XSD.string))) +g.add((Datos.Oscar, ns.hasName, Literal("Oscar Corcho García", datatype=XSD.string))) +g.add((Datos.Oscar, ns.hasColleague, Datos.Asun)) +#Raul +g.add((Datos.Raul, RDF.type, ns.InterimAssociateProfessor)) +g.add((Datos.Raul, RDFS.label, Literal("Raul", datatype=XSD.string))) +#Asun +g.add((Datos.Asun, RDF.type, ns.FullProfessor)) +g.add((Datos.Asun, RDFS.label, Literal("Asun", datatype=XSD.string))) +g.add((Datos.Asun, ns.hasColleague, Datos.Raul)) +g.add((Datos.Asun, ns.hasHomePage, Literal("http://oeg-upm.net/"))) + +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** + +""" + +vcard = Namespace("http://www.w3.org/2001/vcard-rdf/3.0/") +foaf = Namespace("http://xmlns.com/foaf/0.1/") +g.add((Datos.Oscar, vcard.Given, Literal("Oscar", datatype=XSD.string))) +g.add((Datos.Oscar, vcard.Family, Literal("Corcho García", datatype=XSD.string))) +g.add((Datos.Oscar, foaf.email, Literal("ocorcho@fi.upm.es", datatype=XSD.string))) +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/Pedro Garc\303\255a 24C017/task07.py" "b/Assignment4/Pedro Garc\303\255a 24C017/task07.py" new file mode 100644 index 00000000..51b757da --- /dev/null +++ "b/Assignment4/Pedro Garc\303\255a 24C017/task07.py" @@ -0,0 +1,135 @@ +# -*- coding: utf-8 -*- +"""Task07.ipynb + +Automatically generated by Colab. + +Original file is located at + https://colab.research.google.com/drive/1zvX2Bxt__j1SBu23wqpB-QcOs58Tz6_L + +**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** +""" + +result = [] +for clase in g.subjects(RDF.type, RDFS.Class): + superclass = None + for sclass in g.objects(clase, RDFS.subClassOf): + superclass = sclass + result.append((clase, 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 a 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#") + +# variable to return +individuals = [] +def person_subclass(clase): + if clase == ns.Person: + return True + for s, p, o in g.triples((clase, RDFS.subClassOf, None)): + if person_subclass(o): + return True + else: + return False +for s, p, o in g.triples((None, RDF.type, None)): + if o == ns.Person or person_subclass(o) == True: + individuals.append(s) +# 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 people: SELECT DISTINCT ?ind WHERE { ?class rdfs:subClassOf* people:Person . ?ind a ?class .}" +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 people: +PREFIX rdfs: +SELECT ?name ?type WHERE { + ?person people:knows people: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) + +## Validation: Do not remove +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 people: +SELECT DISTINCT ?name WHERE { + ?person rdfs:label ?name . + { + ?person people:hasColleague ?petowner . + ?petowner people:hasColleague ?colleague . + ?colleague people:ownsPet ?pet . + } UNION { + ?person people:hasColleague ?petowner . + ?petowner people:ownsPet ?pet . + } +} +""" + +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/Pedro Garc\303\255a 24C017/validation.py" "b/Assignment4/Pedro Garc\303\255a 24C017/validation.py" new file mode 100644 index 00000000..6024e0b5 --- /dev/null +++ "b/Assignment4/Pedro Garc\303\255a 24C017/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 d13c981757999d9307f7d95f76a751821764571f Mon Sep 17 00:00:00 2001 From: PedroGarcia Date: Mon, 24 Nov 2025 15:27:59 +0100 Subject: [PATCH 6/9] Add files via upload --- .../__pycache__/validation.cpython-312.pyc | Bin 0 -> 15317 bytes Pedro Garcia 24C017/report_result_Task_06.txt | 5 + Pedro Garcia 24C017/report_result_Task_07.txt | 6 + Pedro Garcia 24C017/task06.py | 129 +++++++++ Pedro Garcia 24C017/task07.py | 135 +++++++++ Pedro Garcia 24C017/validation.py | 258 ++++++++++++++++++ 6 files changed, 533 insertions(+) create mode 100644 Pedro Garcia 24C017/__pycache__/validation.cpython-312.pyc create mode 100644 Pedro Garcia 24C017/report_result_Task_06.txt create mode 100644 Pedro Garcia 24C017/report_result_Task_07.txt create mode 100644 Pedro Garcia 24C017/task06.py create mode 100644 Pedro Garcia 24C017/task07.py create mode 100644 Pedro Garcia 24C017/validation.py diff --git a/Pedro Garcia 24C017/__pycache__/validation.cpython-312.pyc b/Pedro Garcia 24C017/__pycache__/validation.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c8dc58fb119f4476bf60962eb461095a42a810de GIT binary patch literal 15317 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 W&!VO3qUkHsTSmI(A%&7u_5T6ctnj`7 literal 0 HcmV?d00001 diff --git a/Pedro Garcia 24C017/report_result_Task_06.txt b/Pedro Garcia 24C017/report_result_Task_06.txt new file mode 100644 index 00000000..3b9c960c --- /dev/null +++ b/Pedro Garcia 24C017/report_result_Task_06.txt @@ -0,0 +1,5 @@ +Hierarchy OK +TASK 6.1 OK +TASK 6.2 OK +TASK 6.3 OK +TASK 6.4 OK diff --git a/Pedro Garcia 24C017/report_result_Task_07.txt b/Pedro Garcia 24C017/report_result_Task_07.txt new file mode 100644 index 00000000..412273c0 --- /dev/null +++ b/Pedro Garcia 24C017/report_result_Task_07.txt @@ -0,0 +1,6 @@ +TASK 7.1a OK +TASK 7.1b OK +TASK 7.2a OK +TASK 7.2b OK +TASK 7.3 OK +TASK 7.4 OK diff --git a/Pedro Garcia 24C017/task06.py b/Pedro Garcia 24C017/task06.py new file mode 100644 index 00000000..482f9f62 --- /dev/null +++ b/Pedro Garcia 24C017/task06.py @@ -0,0 +1,129 @@ +# -*- coding: utf-8 -*- +"""Task06.ipynb + +Automatically generated by Colab. + +Original file is located at + https://colab.research.google.com/drive/10xc6w_MgKVk0SsWYuKegde4a8MUxcfDg + +**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.**""" + +ontology = Namespace("http://www.oeg-upm.net/Ontology#") +person = Namespace("http://www.oeg-upm.net/Ontology#") +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** + +""" + +#Person +g.add((ns.Person, RDF.type, RDFS.Class)) +g.add((ns.Person, RDFS.label, Literal("Person", datatype=XSD.string))) +#Professor +g.add((ns.Professor, RDF.type, RDFS.Class)) +g.add((ns.Professor, RDFS.subClassOf, ns.Person)) +g.add((ns.Professor, RDFS.label, Literal("Professor", datatype=XSD.string))) +#FullProfessor +g.add((ns.FullProfessor, RDF.type, RDFS.Class)) +g.add((ns.FullProfessor, RDFS.subClassOf, ns.Professor)) +g.add((ns.FullProfessor, RDFS.label, Literal("FullProfessor", datatype=XSD.string))) +#AssociateProfessor +g.add((ns.AssociateProfessor, RDF.type, RDFS.Class)) +g.add((ns.AssociateProfessor, RDFS.subClassOf, ns.Professor)) +g.add((ns.AssociateProfessor, RDFS.label, Literal("AssociateProfessor", datatype=XSD.string))) +#InterimAssociateProfessor +g.add((ns.InterimAssociateProfessor, RDF.type, RDFS.Class)) +g.add((ns.InterimAssociateProfessor, RDFS.subClassOf, ns.AssociateProfessor)) +g.add((ns.InterimAssociateProfessor, RDFS.label, Literal("InterimAssociateProfessor", datatype=XSD.string))) +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)**""" + +#HasColleague +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)) +#HasName +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)) +#HasHomePage +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."**""" + +Datos = Namespace("http://oeg.fi.upm.es/resource/person/") +#Oscar +g.add((Datos.Oscar, RDF.type, ns.AssociateProfessor)) +g.add((Datos.Oscar, RDFS.label, Literal("Oscar", datatype=XSD.string))) +g.add((Datos.Oscar, ns.hasName, Literal("Oscar Corcho García", datatype=XSD.string))) +g.add((Datos.Oscar, ns.hasColleague, Datos.Asun)) +#Raul +g.add((Datos.Raul, RDF.type, ns.InterimAssociateProfessor)) +g.add((Datos.Raul, RDFS.label, Literal("Raul", datatype=XSD.string))) +#Asun +g.add((Datos.Asun, RDF.type, ns.FullProfessor)) +g.add((Datos.Asun, RDFS.label, Literal("Asun", datatype=XSD.string))) +g.add((Datos.Asun, ns.hasColleague, Datos.Raul)) +g.add((Datos.Asun, ns.hasHomePage, Literal("http://oeg-upm.net/"))) + +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** + +""" + +vcard = Namespace("http://www.w3.org/2001/vcard-rdf/3.0/") +foaf = Namespace("http://xmlns.com/foaf/0.1/") +g.add((Datos.Oscar, vcard.Given, Literal("Oscar", datatype=XSD.string))) +g.add((Datos.Oscar, vcard.Family, Literal("Corcho García", datatype=XSD.string))) +g.add((Datos.Oscar, foaf.email, Literal("ocorcho@fi.upm.es", datatype=XSD.string))) +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/Pedro Garcia 24C017/task07.py b/Pedro Garcia 24C017/task07.py new file mode 100644 index 00000000..51b757da --- /dev/null +++ b/Pedro Garcia 24C017/task07.py @@ -0,0 +1,135 @@ +# -*- coding: utf-8 -*- +"""Task07.ipynb + +Automatically generated by Colab. + +Original file is located at + https://colab.research.google.com/drive/1zvX2Bxt__j1SBu23wqpB-QcOs58Tz6_L + +**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** +""" + +result = [] +for clase in g.subjects(RDF.type, RDFS.Class): + superclass = None + for sclass in g.objects(clase, RDFS.subClassOf): + superclass = sclass + result.append((clase, 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 a 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#") + +# variable to return +individuals = [] +def person_subclass(clase): + if clase == ns.Person: + return True + for s, p, o in g.triples((clase, RDFS.subClassOf, None)): + if person_subclass(o): + return True + else: + return False +for s, p, o in g.triples((None, RDF.type, None)): + if o == ns.Person or person_subclass(o) == True: + individuals.append(s) +# 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 people: SELECT DISTINCT ?ind WHERE { ?class rdfs:subClassOf* people:Person . ?ind a ?class .}" +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 people: +PREFIX rdfs: +SELECT ?name ?type WHERE { + ?person people:knows people: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) + +## Validation: Do not remove +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 people: +SELECT DISTINCT ?name WHERE { + ?person rdfs:label ?name . + { + ?person people:hasColleague ?petowner . + ?petowner people:hasColleague ?colleague . + ?colleague people:ownsPet ?pet . + } UNION { + ?person people:hasColleague ?petowner . + ?petowner people:ownsPet ?pet . + } +} +""" + +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/Pedro Garcia 24C017/validation.py b/Pedro Garcia 24C017/validation.py new file mode 100644 index 00000000..6024e0b5 --- /dev/null +++ b/Pedro Garcia 24C017/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 fdb7389cecfffc98620532573e3c1d9ce0cb36c7 Mon Sep 17 00:00:00 2001 From: PedroGarcia Date: Mon, 24 Nov 2025 15:36:32 +0100 Subject: [PATCH 7/9] Add files via upload --- .../__pycache__/validation.cpython-312.pyc | Bin 15317 -> 15316 bytes Pedro Garcia 24C017/task06.py | 14 ++++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Pedro Garcia 24C017/__pycache__/validation.cpython-312.pyc b/Pedro Garcia 24C017/__pycache__/validation.cpython-312.pyc index c8dc58fb119f4476bf60962eb461095a42a810de..4ba625a2f28804f3c744676d3bd58b2b8285796b 100644 GIT binary patch delta 34 ocmcawex;n}G%qg~0}x2%s$_2D`NYUrKlwjnHe=@I9HvZ50K&No0ssI2 delta 35 qcmcaoezlzEG%qg~0}$+C`j@eh=My7i!{q;r*-VGmZq8=Pv;+X?r41SY diff --git a/Pedro Garcia 24C017/task06.py b/Pedro Garcia 24C017/task06.py index 482f9f62..526607ba 100644 --- a/Pedro Garcia 24C017/task06.py +++ b/Pedro Garcia 24C017/task06.py @@ -11,6 +11,7 @@ #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" @@ -20,6 +21,7 @@ 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() @@ -29,7 +31,7 @@ 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) + 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.**""" @@ -62,7 +64,7 @@ g.add((ns.InterimAssociateProfessor, RDFS.subClassOf, ns.AssociateProfessor)) g.add((ns.InterimAssociateProfessor, RDFS.label, Literal("InterimAssociateProfessor", datatype=XSD.string))) for s, p, o in g: - print(s,p,o) + print(s, p, o) # Validation. Do not remove r.validate_task_06_01(g) @@ -85,7 +87,7 @@ 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) + print(s, p, o) # Validation. Do not remove r.validate_task_06_02(g) @@ -108,7 +110,7 @@ g.add((Datos.Asun, ns.hasHomePage, Literal("http://oeg-upm.net/"))) for s, p, o in g: - print(s,p,o) + print(s, p, o) r.validate_task_06_03(g) @@ -122,8 +124,8 @@ g.add((Datos.Oscar, vcard.Family, Literal("Corcho García", datatype=XSD.string))) g.add((Datos.Oscar, foaf.email, Literal("ocorcho@fi.upm.es", datatype=XSD.string))) for s, p, o in g: - print(s,p,o) + 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 +r.save_report("_Task_06") From 1cabddad34e3a6984faf30b9b52bdb1bfa55ceb6 Mon Sep 17 00:00:00 2001 From: PedroGarcia Date: Wed, 10 Dec 2025 17:29:25 +0100 Subject: [PATCH 8/9] Assignment 4 Pedro Garcia --- .../Pedro Garc\303\255a 24C017/task06.py" | 129 --------- .../__pycache__/validation.cpython-312.pyc | Bin .../report_result_Task_06.txt | 0 .../report_result_Task_07.txt | 0 .../Pedro_Garcia_24C017}/task06.py | 0 .../Pedro_Garcia_24C017/task07.py | 0 .../Pedro_Garcia_24C017/validation.py | 0 Pedro Garcia 24C017/task07.py | 135 --------- Pedro Garcia 24C017/validation.py | 258 ------------------ 9 files changed, 522 deletions(-) delete mode 100644 "Assignment4/Pedro Garc\303\255a 24C017/task06.py" rename {Pedro Garcia 24C017 => Assignment4/Pedro_Garcia_24C017}/__pycache__/validation.cpython-312.pyc (100%) rename {Pedro Garcia 24C017 => Assignment4/Pedro_Garcia_24C017}/report_result_Task_06.txt (100%) rename {Pedro Garcia 24C017 => Assignment4/Pedro_Garcia_24C017}/report_result_Task_07.txt (100%) rename {Pedro Garcia 24C017 => Assignment4/Pedro_Garcia_24C017}/task06.py (100%) rename "Assignment4/Pedro Garc\303\255a 24C017/task07.py" => Assignment4/Pedro_Garcia_24C017/task07.py (100%) rename "Assignment4/Pedro Garc\303\255a 24C017/validation.py" => Assignment4/Pedro_Garcia_24C017/validation.py (100%) delete mode 100644 Pedro Garcia 24C017/task07.py delete mode 100644 Pedro Garcia 24C017/validation.py diff --git "a/Assignment4/Pedro Garc\303\255a 24C017/task06.py" "b/Assignment4/Pedro Garc\303\255a 24C017/task06.py" deleted file mode 100644 index 482f9f62..00000000 --- "a/Assignment4/Pedro Garc\303\255a 24C017/task06.py" +++ /dev/null @@ -1,129 +0,0 @@ -# -*- coding: utf-8 -*- -"""Task06.ipynb - -Automatically generated by Colab. - -Original file is located at - https://colab.research.google.com/drive/10xc6w_MgKVk0SsWYuKegde4a8MUxcfDg - -**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.**""" - -ontology = Namespace("http://www.oeg-upm.net/Ontology#") -person = Namespace("http://www.oeg-upm.net/Ontology#") -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** - -""" - -#Person -g.add((ns.Person, RDF.type, RDFS.Class)) -g.add((ns.Person, RDFS.label, Literal("Person", datatype=XSD.string))) -#Professor -g.add((ns.Professor, RDF.type, RDFS.Class)) -g.add((ns.Professor, RDFS.subClassOf, ns.Person)) -g.add((ns.Professor, RDFS.label, Literal("Professor", datatype=XSD.string))) -#FullProfessor -g.add((ns.FullProfessor, RDF.type, RDFS.Class)) -g.add((ns.FullProfessor, RDFS.subClassOf, ns.Professor)) -g.add((ns.FullProfessor, RDFS.label, Literal("FullProfessor", datatype=XSD.string))) -#AssociateProfessor -g.add((ns.AssociateProfessor, RDF.type, RDFS.Class)) -g.add((ns.AssociateProfessor, RDFS.subClassOf, ns.Professor)) -g.add((ns.AssociateProfessor, RDFS.label, Literal("AssociateProfessor", datatype=XSD.string))) -#InterimAssociateProfessor -g.add((ns.InterimAssociateProfessor, RDF.type, RDFS.Class)) -g.add((ns.InterimAssociateProfessor, RDFS.subClassOf, ns.AssociateProfessor)) -g.add((ns.InterimAssociateProfessor, RDFS.label, Literal("InterimAssociateProfessor", datatype=XSD.string))) -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)**""" - -#HasColleague -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)) -#HasName -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)) -#HasHomePage -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."**""" - -Datos = Namespace("http://oeg.fi.upm.es/resource/person/") -#Oscar -g.add((Datos.Oscar, RDF.type, ns.AssociateProfessor)) -g.add((Datos.Oscar, RDFS.label, Literal("Oscar", datatype=XSD.string))) -g.add((Datos.Oscar, ns.hasName, Literal("Oscar Corcho García", datatype=XSD.string))) -g.add((Datos.Oscar, ns.hasColleague, Datos.Asun)) -#Raul -g.add((Datos.Raul, RDF.type, ns.InterimAssociateProfessor)) -g.add((Datos.Raul, RDFS.label, Literal("Raul", datatype=XSD.string))) -#Asun -g.add((Datos.Asun, RDF.type, ns.FullProfessor)) -g.add((Datos.Asun, RDFS.label, Literal("Asun", datatype=XSD.string))) -g.add((Datos.Asun, ns.hasColleague, Datos.Raul)) -g.add((Datos.Asun, ns.hasHomePage, Literal("http://oeg-upm.net/"))) - -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** - -""" - -vcard = Namespace("http://www.w3.org/2001/vcard-rdf/3.0/") -foaf = Namespace("http://xmlns.com/foaf/0.1/") -g.add((Datos.Oscar, vcard.Given, Literal("Oscar", datatype=XSD.string))) -g.add((Datos.Oscar, vcard.Family, Literal("Corcho García", datatype=XSD.string))) -g.add((Datos.Oscar, foaf.email, Literal("ocorcho@fi.upm.es", datatype=XSD.string))) -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/Pedro Garcia 24C017/__pycache__/validation.cpython-312.pyc b/Assignment4/Pedro_Garcia_24C017/__pycache__/validation.cpython-312.pyc similarity index 100% rename from Pedro Garcia 24C017/__pycache__/validation.cpython-312.pyc rename to Assignment4/Pedro_Garcia_24C017/__pycache__/validation.cpython-312.pyc diff --git a/Pedro Garcia 24C017/report_result_Task_06.txt b/Assignment4/Pedro_Garcia_24C017/report_result_Task_06.txt similarity index 100% rename from Pedro Garcia 24C017/report_result_Task_06.txt rename to Assignment4/Pedro_Garcia_24C017/report_result_Task_06.txt diff --git a/Pedro Garcia 24C017/report_result_Task_07.txt b/Assignment4/Pedro_Garcia_24C017/report_result_Task_07.txt similarity index 100% rename from Pedro Garcia 24C017/report_result_Task_07.txt rename to Assignment4/Pedro_Garcia_24C017/report_result_Task_07.txt diff --git a/Pedro Garcia 24C017/task06.py b/Assignment4/Pedro_Garcia_24C017/task06.py similarity index 100% rename from Pedro Garcia 24C017/task06.py rename to Assignment4/Pedro_Garcia_24C017/task06.py diff --git "a/Assignment4/Pedro Garc\303\255a 24C017/task07.py" b/Assignment4/Pedro_Garcia_24C017/task07.py similarity index 100% rename from "Assignment4/Pedro Garc\303\255a 24C017/task07.py" rename to Assignment4/Pedro_Garcia_24C017/task07.py diff --git "a/Assignment4/Pedro Garc\303\255a 24C017/validation.py" b/Assignment4/Pedro_Garcia_24C017/validation.py similarity index 100% rename from "Assignment4/Pedro Garc\303\255a 24C017/validation.py" rename to Assignment4/Pedro_Garcia_24C017/validation.py diff --git a/Pedro Garcia 24C017/task07.py b/Pedro Garcia 24C017/task07.py deleted file mode 100644 index 51b757da..00000000 --- a/Pedro Garcia 24C017/task07.py +++ /dev/null @@ -1,135 +0,0 @@ -# -*- coding: utf-8 -*- -"""Task07.ipynb - -Automatically generated by Colab. - -Original file is located at - https://colab.research.google.com/drive/1zvX2Bxt__j1SBu23wqpB-QcOs58Tz6_L - -**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** -""" - -result = [] -for clase in g.subjects(RDF.type, RDFS.Class): - superclass = None - for sclass in g.objects(clase, RDFS.subClassOf): - superclass = sclass - result.append((clase, 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 a 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#") - -# variable to return -individuals = [] -def person_subclass(clase): - if clase == ns.Person: - return True - for s, p, o in g.triples((clase, RDFS.subClassOf, None)): - if person_subclass(o): - return True - else: - return False -for s, p, o in g.triples((None, RDF.type, None)): - if o == ns.Person or person_subclass(o) == True: - individuals.append(s) -# 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 people: SELECT DISTINCT ?ind WHERE { ?class rdfs:subClassOf* people:Person . ?ind a ?class .}" -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 people: -PREFIX rdfs: -SELECT ?name ?type WHERE { - ?person people:knows people: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) - -## Validation: Do not remove -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 people: -SELECT DISTINCT ?name WHERE { - ?person rdfs:label ?name . - { - ?person people:hasColleague ?petowner . - ?petowner people:hasColleague ?colleague . - ?colleague people:ownsPet ?pet . - } UNION { - ?person people:hasColleague ?petowner . - ?petowner people:ownsPet ?pet . - } -} -""" - -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/Pedro Garcia 24C017/validation.py b/Pedro Garcia 24C017/validation.py deleted file mode 100644 index 6024e0b5..00000000 --- a/Pedro Garcia 24C017/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 9daabae1980af96dfb4d537b2f94c1f7f771787a Mon Sep 17 00:00:00 2001 From: PedroGarcia Date: Wed, 10 Dec 2025 18:36:32 +0100 Subject: [PATCH 9/9] Assignment 4 Pedro Garcia --- .../__pycache__/validation.cpython-312.pyc | Bin 15316 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Assignment4/Pedro_Garcia_24C017/__pycache__/validation.cpython-312.pyc diff --git a/Assignment4/Pedro_Garcia_24C017/__pycache__/validation.cpython-312.pyc b/Assignment4/Pedro_Garcia_24C017/__pycache__/validation.cpython-312.pyc deleted file mode 100644 index 4ba625a2f28804f3c744676d3bd58b2b8285796b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15316 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