KR 2024 homework part 1
You will have to write a small program to convert/filter data to a suitable format for experimenting with a logical reasoner, and then write ca 10 nontrivial rules for answering questions. Finally, experiment with the reasoner on this data + rules and make a small presentation of your data, rules, successes and failures.
Not everything you try out needs to work: some failures are also interesting.
Data
Riina took the large datasets from https://yago-knowledge.org/ and prepared relatively small selections (all about something Estonian) from this data. The link to the files is here. The data is presented as plain triplets, no fancy encoding (except namespaces) are involved.
First, please download the files and explore them a bit. Then convert the files to the format our reasoner gk (or its web version http://logictools.org) can eat.
For example, the triplet
yago:Lake_Peipsi rdf:type yago:Lake
can be converted to
triple(yago:Lake_Peipsi,rdf:type,yago:Lake).
or with the quotation marks
triple("yago:Lake_Peipsi","rdf:type","yago:Lake").
Notice that I have not bothered to replace the abbreviations of namespaces like yago, rdf etc with full names http://yago-knowledge.org/resource/ and http://www.w3.org/1999/02/22-rdf-syntax-ns#: the abbreviations make the symbols unique enough for our purposes.
The predicate triple is really arbitrary: you may use any name you like. You may also use the fourth argument for type, if you wish (like "string" in the case above). Importantly, there are subtle differences between writing constants like yago:Lake_Peipsi with or without quotation marks:
- Without quotation the reasoner does not assume that two different constants necessarily mean different objects. Saying yago:Lake_Peipsi = yago:Lake_Peipus does not lead to a contradiction. Also, non-ascii symbols are generally not ok for non-quoted constants.
- Quotation marks make the reasoner to treat constants as strings, and thus "yago:Lake_Peipsi" = "yago:Lake_Peipus" is a contradiction. Also, non-ascii symbols are OK.
Observe that the datasets contain a huge amount of labels (i.e. human names) and comments in different languages, like
yago:Tartu rdfs:label "Tartu"@sh . yago:Tartu rdfs:label "Tartu"@lfn . yago:Tartu rdfs:label "Tartu"@es . yago:Tartu schema:alternateName "Tartu"@ko . yago:Tartu schema:alternateName "Tartu"@mhr . yago:Tartu schema:alternateName "Jurjev"@cs . yago:Tartu_Art_House rdfs:comment "museum di Estonia"@id . yago:Tartu_Art_House rdfs:comment "Museum in Estland"@de .
You may safely remove all the comments and most (or all) names, except these which you really use in your questions and rules, if any. For example, you may want to keep just one rdfs:label for an object, without indicating a language (the @-stuff) at all.
Rules and questions
The best way to try out rules and questions is to use http://logictools.org for quick experiments along with small selections of data. For example, try
triple("yago:Lake_Peipsi","rdf:type","yago:Lake").
triple("yago:Võrtsjärv","rdf:type","yago:Lake").
triple(X,Y,"yago:Lake") => $ans(X).
and you should get a single answer along with the trivial proof. To get more answers, click the "Advanced" button and copy { "max_answers": 2} into the strategy box. Beware that in case you ask for more answers than there really are, the reasoner may just keeping looking for more, eventually timeouting, and not giving any answers at all.
Now let us try out something simple, but not totally trivial:
triple(yago:Jaan_Lepp, schema:birthPlace, yago:Anija_Parish). triple(yago:August_Vaga, schema:birthPlace, yago:Kehra). triple(yago:Silvi_Vrait, schema:birthPlace, yago:Kehra). triple(yago:Karmen_Pedaru, schema:birthPlace, yago:Kehra). triple(X,schema:birthPlace,Z) => bornin(X,K). bornin(X,Z) & bornin(Y,Z) => borninsameplace(X,Y). borninsameplace(X,Y) & -$substr(X,Y) & -$substr(Y,X) => $ans(X,Y).
Put, say { "max_answers": 3} to the strategy box, to get more answers than one.
Here we took a small selection of data from one of the files and added a few rules. Notice the trick with the special builtin predicate $substr(K,Z): it treats the argument constants as strings and checks whether the first one is a substring of the second one. Thus the -$substr(X,Y) & -$substr(Y,X) simply eliminates equal constants to avoid answers like $ans('yago:August_Vaga','yago:August_Vaga').. Alternatively, if we had used the quotation marks around person id-s, we could have used the rule
borninsameplace(X,Y) & X!=Y => $ans(X,Y).
instead.
Next, a slightly more interesting example (use { "max_answers": 6} or less):
triple("yago:Lake_Peipus","rdf:type", "yago:Lake").
triple("yago:Võrtsjärv","rdf:type","yago:Lake").
triple("yago:Veisjärv","rdf:type","yago:Lake").
triple("yago:Väike_Emajõgi", "yago:flowsInto", "yago:Võrtsjärv").
triple("yago:Tänassilma_River", "yago:flowsInto", "yago:Võrtsjärv").
triple("yago:Tarvastu_River", "yago:flowsInto", "yago:Võrtsjärv").
triple("yago:Võrtsjärv", "yago:flowsInto", "yago:Emajõgi").
triple("yago:Veisjärv","yago:flowsInto","yago:Õhne").
triple("yago:Õhne", "yago:flowsInto", "yago:Võrtsjärv").
triple("yago:Emajõgi", "yago:flowsInto", "yago:Lake_Peipus").
triple(X,"yago:flowsInto",Y) => boattravel(X,Y).
triple(X,"yago:flowsInto",Y) => boattravel(Y,X).
boattravel(X,Y) & boattravel(Y,Z) => boattravel(X,Z).
triple(X,"rdf:type","yago:Lake") & triple(Z,"rdf:type","yago:Lake") & boattravel(X,Y) & boattravel(Y,Z) & X!=Z => laketolake(X,Z).
laketolake(X,Y) => $ans(X,Y).
Interestingly, the Yago dataset uses two different id-s for Peipsi: yago:Lake_Peipus and yago:Lake_Peipsi with several additional triplets indicating equality of these id-s to some other id-s, but not to each other! The related datasets for these id-s are also different. Conceptually, this is an errorish thingy in Yago.
yago:Lake_Peipsi rdf:type yago:Lake yago:Lake_Peipsi owl:sameAs wd:Q2627792 yago:Lake_Peipsi schema:sameAs "/g/1217z1dh" yago:Lake_Peipus rdf:type yago:Lake yago:Lake_Peipus owl:sameAs wd:Q19253 yago:Lake_Peipus schema:sameAs "/m/021yh2"