{\n",
" ?s ?p ?o .\n",
" }\n",
"}\n",
@@ -295,7 +298,7 @@
"metadata": {},
"outputs": [],
"source": [
- "%%sparql http://fuseki.cluster.gsi.dit.upm.es/hotels\n",
+ "%%sparql http://fuseki.gsi.upm.es/hotels\n",
"\n",
"PREFIX schema: \n",
" \n",
@@ -308,7 +311,7 @@
" SELECT ?g\n",
" WHERE {\n",
" GRAPH ?g {}\n",
- " FILTER (str(?g) != 'http://fuseki.cluster.gsi.dit.upm.es/synthetic')\n",
+ " FILTER (str(?g) != 'http://fuseki.gsi.upm.es/synthetic')\n",
" }\n",
" }\n",
"\n",
@@ -339,12 +342,13 @@
"metadata": {
"deletable": false,
"nbgrader": {
+ "cell_type": "code",
"checksum": "860c3977cd06736f1342d535944dbb63",
"grade": true,
"grade_id": "cell-9bd08e4f5842cb89",
"locked": false,
"points": 0,
- "schema_version": 1,
+ "schema_version": 3,
"solution": true
}
},
@@ -366,12 +370,13 @@
"metadata": {
"deletable": false,
"nbgrader": {
+ "cell_type": "code",
"checksum": "1946a7ed4aba8d168bb3fad898c05651",
"grade": true,
"grade_id": "cell-9dc1c9033198bb18",
"locked": false,
"points": 0,
- "schema_version": 1,
+ "schema_version": 3,
"solution": true
}
},
@@ -393,12 +398,13 @@
"metadata": {
"deletable": false,
"nbgrader": {
+ "cell_type": "code",
"checksum": "6714abc5226618b76dc4c1aaed6d1a49",
"grade": true,
"grade_id": "cell-6c18003ced54be23",
"locked": false,
"points": 0,
- "schema_version": 1,
+ "schema_version": 3,
"solution": true
}
},
@@ -449,7 +455,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.7.2"
+ "version": "3.8.1"
}
},
"nbformat": 4,
diff --git a/lod/03_SPARQL_Writers.ipynb b/lod/03_SPARQL_Writers.ipynb
new file mode 100644
index 0000000..887108b
--- /dev/null
+++ b/lod/03_SPARQL_Writers.ipynb
@@ -0,0 +1,1417 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "markdown",
+ "checksum": "7276f055a8c504d3c80098c62ed41a4f",
+ "grade": false,
+ "grade_id": "cell-0bfe38f97f6ab2d2",
+ "locked": true,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "source": [
+ "\n",
+ " \n",
+ "
Course Notes for Learning Intelligent Systems
\n",
+ " Department of Telematic Engineering Systems
\n",
+ " Universidad Politécnica de Madrid
\n",
+ " \n",
+ " \n",
+ ""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "markdown",
+ "checksum": "2387a77db61721ecc375a8275111ecaf",
+ "grade": false,
+ "grade_id": "cell-0cd673883ee592d1",
+ "locked": true,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "source": [
+ "## Introduction to Linked Open Data\n",
+ "\n",
+ "In this lecture, we will apply the same SPARQL concepts as in previous notebooks.\n",
+ "This time, instead of using a database specifically built for the exercise, we will be using DBpedia.\n",
+ "DBpedia is a semantic version of Wikipedia.\n",
+ "\n",
+ "The language we will use to query DBpedia is SPARQL, a semantic query language inspired by SQL.\n",
+ "For convenience, the examples in the notebook are executable, and they are accompanied by some code to test the results.\n",
+ "If the tests pass, you probably got the answer right.\n",
+ "\n",
+ "However, you can also use any other method to write and send your queries.\n",
+ "You may find online query editors particularly useful.\n",
+ "In addition to running queries from your browser, they provide useful features such as syntax highlighting and autocompletion.\n",
+ "Some examples are:\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "markdown",
+ "checksum": "bc0ca2e21254707344c60f895cb204b4",
+ "grade": false,
+ "grade_id": "cell-10264483046abcc4",
+ "locked": true,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "source": [
+ "## Objectives\n",
+ "\n",
+ "* Learning SPARQL and the Linked Data principles by defining queries to answer a set of problems of increasing difficulty\n",
+ "* Learning how to use integrated SPARQL editors and programming interfaces to SPARQL."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "markdown",
+ "checksum": "2fedf0d73fc90104d1ab72c3413dfc83",
+ "grade": false,
+ "grade_id": "cell-4f8492996e74bf20",
+ "locked": true,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "source": [
+ "## Tools\n",
+ "\n",
+ "See [the SPARQL notebook](./01_SPARQL_Introduction.ipynb#Tools)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Instructions\n",
+ "\n",
+ "As in previous notebooks, the exercises can be done in the notebook, using the `%%sparql` magic, and the set of tests.\n",
+ "\n",
+ "\n",
+ "After every query, you will find some python code to test the results of the query.\n",
+ "**Make sure you've run the tests before moving to the next exercise**.\n",
+ "If the test gives you an error, you've probably done something wrong.\n",
+ "You **do not need to understand or modify the test code**.\n",
+ "\n",
+ "If you prefer to edit your queries in a different editor, here are some options:\n",
+ "\n",
+ "* DBpedia's virtuoso query editor https://dbpedia.org/sparql\n",
+ "* A javascript based client hosted at GSI: http://yasgui.gsi.upm.es/\n",
+ "\n",
+ "If you use an editor, make sure to copy it to the notebook and run the tests, once you are getting the expected results."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "markdown",
+ "checksum": "c5f8646518bd832a47d71f9d3218237a",
+ "grade": false,
+ "grade_id": "cell-eb13908482825e42",
+ "locked": true,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "source": [
+ "Run this line to enable the `%%sparql` magic command."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from helpers import sparql, solution, show_photos"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The `%%sparql` magic command will allow us to use SPARQL inside normal jupyter cells.\n",
+ "\n",
+ "For instance, the following code:\n",
+ "\n",
+ "```python\n",
+ "%%sparql\n",
+ "\n",
+ "\n",
+ "``` \n",
+ "\n",
+ "Is the same as `run_query('', endpoint='http://dbpedia.org/sparql')` plus some additional steps, such as saving the results in a nice table format so that they can be used later and storing the results in a variable (`solution()`), which we will use in our tests.\n",
+ "\n",
+ "You do not need to worry about it, and **you can always use one of the suggested online editors if you wish**."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Exercises"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### First Select"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Let's start with a simple query. We will get a list of cities and towns in Madrid.\n",
+ "If we take a look at the DBpedia ontology or the page of any town we already know, we discover that the property that links towns to their community is [`isPartOf`](http://dbpedia.org/ontology/isPartOf), and [the Community of Madrid is also a resource in DBpedia](http://dbpedia.org/resource/Community_of_Madrid)\n",
+ "\n",
+ "Since there are potentially many cities to get, we will limit our results to the first 10 results:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%%sparql http://dbpedia.org/sparql\n",
+ "\n",
+ "SELECT ?localidad\n",
+ "WHERE {\n",
+ " ?localidad \n",
+ "}\n",
+ "LIMIT 10"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "However, that query is very verbose because we are using full URIs.\n",
+ "To simplify it, we will make use of SPARQL prefixes:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%%sparql http://dbpedia.org/sparql\n",
+ "\n",
+ "PREFIX dbo: \n",
+ "PREFIX dbr: \n",
+ " \n",
+ "SELECT ?localidad\n",
+ "WHERE {\n",
+ " ?localidad dbo:isPartOf dbr:Community_of_Madrid.\n",
+ "}\n",
+ "LIMIT 10"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "To make sure that the query returned something sensible, we can test it with some python code:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "assert 'localidad' in solution()['columns']\n",
+ "assert len(solution()['tuples']) == 10"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Now that you have some experience under your belt, it is time to design your own query.\n",
+ "\n",
+ "Your first task it to get a list of Spanish Novelits, using the skeleton below and the previous query to guide you.\n",
+ "\n",
+ "Pages for Spanish novelists are grouped in the *Spanish novelists* DBpedia category. You can use that fact to get your list.\n",
+ "In other words, the difference from the previous query will be using `dct:subject` instead of `dbo:isPartOf`, and `dbc:Spanish_novelists` instead of `dbr:Community_of_Madrid`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "eef1c62e2797bd3ef01f2061da6f83c4",
+ "grade": false,
+ "grade_id": "cell-7a9509ff3c34127e",
+ "locked": false,
+ "schema_version": 3,
+ "solution": true
+ }
+ },
+ "outputs": [],
+ "source": [
+ "%%sparql http://dbpedia.org/sparql\n",
+ "\n",
+ "PREFIX dct:\n",
+ "PREFIX dbc:\n",
+ "\n",
+ "SELECT ?escritor\n",
+ "\n",
+ "WHERE {\n",
+ "# YOUR ANSWER HERE\n",
+ "}\n",
+ "LIMIT 10"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "5a57d16cb2b53925f6e39fba429b7ef2",
+ "grade": true,
+ "grade_id": "cell-91240ded2cac7b6d",
+ "locked": true,
+ "points": 0,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "assert len(solution()['columns']) == 1 # We only use one variable, ?escritor\n",
+ "assert len(solution()['tuples']) == 10 # There should be 10 results"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Using more criteria\n",
+ "\n",
+ "We can get more than one property in the same query. Let us modify our query to get the population of the cities as well."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%%sparql http://dbpedia.org/sparql\n",
+ "\n",
+ "PREFIX rdfs: \n",
+ "PREFIX dbo: \n",
+ "PREFIX dbr: \n",
+ "PREFIX dbp: \n",
+ " \n",
+ "SELECT ?localidad ?pop ?when\n",
+ "\n",
+ "WHERE {\n",
+ " ?localidad dbo:populationTotal ?pop .\n",
+ " ?localidad dbo:isPartOf dbr:Community_of_Madrid.\n",
+ " ?localidad dbp:populationAsOf ?when .\n",
+ "}\n",
+ "\n",
+ "LIMIT 100"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "assert 'localidad' in solution()['columns']\n",
+ "assert 'http://dbpedia.org/resource/Parla' in solution()['columns']['localidad']\n",
+ "assert ('http://dbpedia.org/resource/San_Sebastián_de_los_Reyes', '75912', '2009') in solution()['tuples']"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Time to try it yourself.\n",
+ "\n",
+ "Get the list of Spanish novelists AND their name (using rdfs:label)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "9d4193612dea95da2d91762b638ad5e6",
+ "grade": false,
+ "grade_id": "cell-83dcaae0d09657b5",
+ "locked": false,
+ "schema_version": 3,
+ "solution": true
+ }
+ },
+ "outputs": [],
+ "source": [
+ "%%sparql http://dbpedia.org/sparql\n",
+ "\n",
+ "PREFIX rdfs:\n",
+ "PREFIX dct:\n",
+ "PREFIX dbc:\n",
+ "\n",
+ "SELECT ?escritor ?name\n",
+ "\n",
+ "WHERE {\n",
+ "# YOUR ANSWER HERE\n",
+ "}\n",
+ "LIMIT 10"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "86115c2a8982ad12b7250cf4341ae9c3",
+ "grade": true,
+ "grade_id": "cell-8afd28aada7a896c",
+ "locked": true,
+ "points": 0,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "assert 'escritor' in solution()['columns']\n",
+ "assert 'http://dbpedia.org/resource/Eduardo_Mendoza_Garriga' in solution()['columns']['escritor']\n",
+ "assert ('http://dbpedia.org/resource/Eduardo_Mendoza_Garriga', 'Eduardo Mendoza') in solution()['tuples']"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Filtering and ordering"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "In the previous example, we saw that we got what seemed to be duplicated answers.\n",
+ "\n",
+ "This happens because entities can have labels in different languages (e.g. English, Spanish).\n",
+ "To restrict the search to only those results we're interested in, we can use filtering.\n",
+ "\n",
+ "We can also decide the order in which our results are shown.\n",
+ "\n",
+ "For instance, this is how we could use filtering to get only large cities in our example, ordered by population:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%%sparql http://dbpedia.org/sparql\n",
+ "\n",
+ "PREFIX rdfs: \n",
+ "PREFIX dbo: \n",
+ "PREFIX dbr: \n",
+ " \n",
+ "SELECT ?localidad ?pop ?when\n",
+ "\n",
+ "WHERE {\n",
+ " ?localidad dbo:populationTotal ?pop .\n",
+ " ?localidad dbo:isPartOf dbr:Community_of_Madrid.\n",
+ " ?localidad dbp:populationAsOf ?when .\n",
+ " FILTER(?pop > 100000)\n",
+ "}\n",
+ "ORDER BY ?pop\n",
+ "LIMIT 100"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Note that ordering happens before limits."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "a38cb1aea7b1f01f6b37c088384e0a3d",
+ "grade": true,
+ "grade_id": "cell-cb7b8283568cd349",
+ "locked": true,
+ "points": 0,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# We still have the biggest city\n",
+ "assert ('http://dbpedia.org/resource/Madrid', '3141991', '2014') in solution()['tuples']\n",
+ "# But the smaller ones are gone\n",
+ "assert 'http://dbpedia.org/resource/Tres_Cantos' not in solution()['columns']['localidad']\n",
+ "assert 'http://dbpedia.org/resource/San_Sebastián_de_los_Reyes' not in solution()['columns']['localidad']"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Now, try filtering to get a list of novelists and their name in Spanish, ordered by name `(FILTER (LANG(?nombre) = \"es\") y ORDER BY`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "b6aaac8ab30d52a042c1efefbbff7550",
+ "grade": false,
+ "grade_id": "cell-ff3d611cb0304b01",
+ "locked": false,
+ "schema_version": 3,
+ "solution": true
+ }
+ },
+ "outputs": [],
+ "source": [
+ "%%sparql http://dbpedia.org/sparql\n",
+ "\n",
+ "PREFIX rdfs: \n",
+ "PREFIX dct:\n",
+ "PREFIX dbc:\n",
+ "\n",
+ "SELECT ?escritor ?nombre\n",
+ "\n",
+ "WHERE {\n",
+ "# YOUR ANSWER HERE\n",
+ "}\n",
+ "# YOUR ANSWER HERE\n",
+ "LIMIT 1000"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "3441fbd2267002acbb0d46d9ce94ba97",
+ "grade": true,
+ "grade_id": "cell-d70cc6ea394741bc",
+ "locked": true,
+ "points": 0,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "assert len(solution()['tuples']) >= 50\n",
+ "assert 'Adelaida García Morales' in solution()['columns']['nombre']\n",
+ "assert sum(1 for k in solution()['columns']['escritor'] if k == 'http://dbpedia.org/resource/Adelaida_García_Morales') == 1"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Optional"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "From now on, we will focus on our Writers example.\n",
+ "\n",
+ "First, we will search for writers born in the XX century, using the [20th-century Spanish novelists](http://dbpedia.org/page/Category:20th-century_Spanish_novelists) category."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "e3ff089c983be1ae937f254b8d9d229a",
+ "grade": false,
+ "grade_id": "cell-ab7755944d46f9ca",
+ "locked": false,
+ "schema_version": 3,
+ "solution": true
+ }
+ },
+ "outputs": [],
+ "source": [
+ "# YOUR ANSWER HERE"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "cacdd08a8a267c1173304e319ffff563",
+ "grade": true,
+ "grade_id": "cell-cf3821f2d33fb0f6",
+ "locked": true,
+ "points": 0,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "assert 'Camilo José Cela' in solution()['columns']['nombre']\n",
+ "assert 'Javier Marías' in solution()['columns']['nombre']\n",
+ "assert all(x > '1850-12-31' and x < '2001-01-01' for x in solution()['columns']['nac'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "In our last example, we were missing many novelists that are do not have birth information in DBpedia.\n",
+ "\n",
+ "We can specify optional values in a query using the `OPTIONAL` keyword.\n",
+ "When a set of clauses are inside an OPTIONAL group, the SPARQL endpoint will try to use them in the query.\n",
+ "If there are no results for that part of the query, the variables it specifies will not be bound (i.e. they will be empty).\n",
+ "\n",
+ "Using that, let us retrieve all the novelists, their birth and death date (if they are available)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "f4170cbbf042644e394d1eb9acf12ce3",
+ "grade": false,
+ "grade_id": "cell-254a18dd973e82ed",
+ "locked": false,
+ "schema_version": 3,
+ "solution": true
+ }
+ },
+ "outputs": [],
+ "source": [
+ "%%sparql http://dbpedia.org/sparql\n",
+ "\n",
+ "PREFIX rdfs: \n",
+ "PREFIX dct:\n",
+ "PREFIX dbc:\n",
+ "PREFIX dbo:\n",
+ "\n",
+ "SELECT ?escritor ?nombre ?fechaNac ?fechaDef\n",
+ "\n",
+ "WHERE {\n",
+ "# YOUR ANSWER HERE\n",
+ "}\n",
+ "# YOUR ANSWER HERE\n",
+ "LIMIT 200"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "29c6362adbdb5606e158f696594e1052",
+ "grade": true,
+ "grade_id": "cell-4d6a64dde67f0e11",
+ "locked": true,
+ "points": 0,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "assert 'Wenceslao Fernández Flórez' in solution()['columns']['nombre']\n",
+ "assert '1879-2-11' in solution()['columns']['fechaNac']\n",
+ "assert '' in solution()['columns']['fechaNac'] # Not all birthdates are defined\n",
+ "assert '' in solution()['columns']['fechaDef'] # Some deathdates are not defined"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Bound"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can check whether the optional value for a key was bound in a SPARQL query using `BOUND(?key)`.\n",
+ "\n",
+ "This is very useful for two purposes.\n",
+ "First, it allows us to look for patterns that **do not occur** in the graph, such as missing properties.\n",
+ "For instance, we could search for the authors with missing birth information so we can add it.\n",
+ "Secondly, we can use bound in filters to get conditional filters.\n",
+ "We will explore both uses in this exercise."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Get the list of Spanish novelists that are still alive.\n",
+ "A person is alive if their death date is not defined and the were born less than 100 years ago"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "f3c11121eb0d1328d2f5da3580f8d648",
+ "grade": false,
+ "grade_id": "cell-474b1a72dec6827c",
+ "locked": false,
+ "schema_version": 3,
+ "solution": true
+ }
+ },
+ "outputs": [],
+ "source": [
+ "%%sparql http://dbpedia.org/sparql\n",
+ "\n",
+ "PREFIX rdfs: \n",
+ "PREFIX dct:\n",
+ "PREFIX dbc:\n",
+ "PREFIX dbo:\n",
+ "\n",
+ "SELECT ?escritor, ?nombre, year(?fechaNac) as ?nac\n",
+ "\n",
+ "WHERE {\n",
+ " \n",
+ "# YOUR ANSWER HERE\n",
+ "}\n",
+ "\n",
+ "# YOUR ANSWER HERE\n",
+ "LIMIT 1000"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "770bbddef5210c28486a1929e4513ada",
+ "grade": true,
+ "grade_id": "cell-46b62dd2856bc919",
+ "locked": true,
+ "points": 0,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "assert 'Fernando Arrabal' in solution()['columns']['nombre']\n",
+ "assert 'Albert Espinosa' in solution()['columns']['nombre']\n",
+ "for year in solution()['columns']['nac']:\n",
+ " assert int(year) >= 1918"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Now, get the list of Spanish novelists that died before their fifties (i.e. younger than 50 years old), or that aren't 50 years old yet.\n",
+ "\n",
+ "Hint: you can use boolean logic in your filters (e.g. `&&` and `||`).\n",
+ "\n",
+ "Hint 2: Some dates are not formatted properly, which makes some queries fail when they shouldn't. You might need to convert between different types as a workaround. For instance, you could get the year from a date like this: `year(xsd:dateTime(str(?date)))`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "ed34857649c9a6926eb0a3a0e1d8198d",
+ "grade": false,
+ "grade_id": "cell-ceefd3c8fbd39d79",
+ "locked": false,
+ "schema_version": 3,
+ "solution": true
+ }
+ },
+ "outputs": [],
+ "source": [
+ "%%sparql http://dbpedia.org/sparql\n",
+ "\n",
+ "PREFIX rdfs: \n",
+ "PREFIX dct:\n",
+ "PREFIX dbc:\n",
+ "PREFIX dbo:\n",
+ "\n",
+ "SELECT ?escritor, ?nombre, YEAR(?fechaNac) as ?nac, ?fechaDef\n",
+ "\n",
+ "WHERE {\n",
+ "# YOUR ANSWER HERE\n",
+ "}\n",
+ "# YOUR ANSWER HERE\n",
+ "LIMIT 100"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "18bb2d8d586bf4a5231973e69958ab75",
+ "grade": true,
+ "grade_id": "cell-461cd6ccc6c2dc79",
+ "locked": true,
+ "points": 0,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "assert 'Javier Sierra' in solution()['columns']['nombre']\n",
+ "assert 'http://dbpedia.org/resource/Sanmao_(author)' in solution()['columns']['escritor']"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Finding unique elements"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "In our last example, our results show some authors more than once.\n",
+ "This is because some properties are defined more than once.\n",
+ "For instance, birth date is giving using different formats.\n",
+ "Even if we exclude that property from our results by not adding it in our `SELECT`, we will get duplicated lines.\n",
+ "\n",
+ "To solve this, we can use the `DISTINCT` keyword."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Modify your last query to remove duplicated lines.\n",
+ "In other words, authors should only appear once."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "34163ddb0400cd8ddd2c2e2cdf29c20b",
+ "grade": false,
+ "grade_id": "cell-2a39adc71d26ae73",
+ "locked": false,
+ "schema_version": 3,
+ "solution": true
+ }
+ },
+ "outputs": [],
+ "source": [
+ "%%sparql http://dbpedia.org/sparql\n",
+ "\n",
+ "PREFIX rdfs: \n",
+ "PREFIX dct:\n",
+ "PREFIX dbc:\n",
+ "PREFIX dbo:\n",
+ "\n",
+ "SELECT DISTINCT ?escritor, ?nombre, year(?fechaNac) as ?nac\n",
+ "\n",
+ "WHERE {\n",
+ "# YOUR ANSWER HERE\n",
+ "}\n",
+ "# YOUR ANSWER HERE\n",
+ "LIMIT 100"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "84ab7d64a45e03e6dd902216a2aad030",
+ "grade": true,
+ "grade_id": "cell-542e0e36347fd5d1",
+ "locked": true,
+ "points": 0,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "assert 'Javier Sierra' in solution()['columns']['nombre']\n",
+ "assert 'http://dbpedia.org/resource/Albert_Espinosa' in solution()['columns']['escritor']\n",
+ "\n",
+ "from collections import Counter\n",
+ "c = Counter(solution()['columns']['nombre'])\n",
+ "for count in c.values():\n",
+ " assert count == 1\n",
+ " \n",
+ "c1 = Counter(solution()['columns']['escritor'])\n",
+ "assert all(count==1 for count in c1.values())\n",
+ "# c = Counter(solution()['columns']['nombre'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Using other resources"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Get the list of living Spanish novelists born in Madrid.\n",
+ "\n",
+ "Hint: use `dbr:Madrid` and `dbo:birthPlace`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "25c8edcee216d536aac98fc9aa2b6422",
+ "grade": false,
+ "grade_id": "cell-d175e41da57c889b",
+ "locked": false,
+ "schema_version": 3,
+ "solution": true
+ }
+ },
+ "outputs": [],
+ "source": [
+ "%%sparql http://dbpedia.org/sparql\n",
+ "\n",
+ "PREFIX rdfs: \n",
+ "PREFIX dct:\n",
+ "PREFIX dbc:\n",
+ "PREFIX dbr:\n",
+ "PREFIX dbo:\n",
+ "\n",
+ "SELECT DISTINCT ?escritor, ?nombre, ?lugarNac, year(?fechaNac) as ?nac\n",
+ "\n",
+ "WHERE {\n",
+ "# YOUR ANSWER HERE\n",
+ "}\n",
+ "# YOUR ANSWER HERE\n",
+ "LIMIT 100"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "443608e177f514f2cddafa6c1d1e3cc7",
+ "grade": true,
+ "grade_id": "cell-fadd095862db6bc8",
+ "locked": true,
+ "points": 0,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "assert 'José Ángel Mañas' in solution()['columns']['nombre']\n",
+ "assert 'http://dbpedia.org/resource/Madrid' in solution()['columns']['lugarNac']\n",
+ "MADRID_QUERY = solution()['columns'].copy()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Traversing the graph"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Get the list of works of the authors in the previous query (i.e. authors born in Madrid), if they have any.\n",
+ "\n",
+ "Hint: use `dbo:author`, which is a **property of a literary work** that points to the author."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "c1f22b82c4d0bd4102a6c38f7f933dc6",
+ "grade": false,
+ "grade_id": "cell-e4b99af9ef91ff6f",
+ "locked": false,
+ "schema_version": 3,
+ "solution": true
+ }
+ },
+ "outputs": [],
+ "source": [
+ "%%sparql http://dbpedia.org/sparql\n",
+ "\n",
+ "PREFIX rdfs: \n",
+ "PREFIX dct:\n",
+ "PREFIX dbc:\n",
+ "PREFIX dbr:\n",
+ "PREFIX dbo:\n",
+ "\n",
+ "SELECT DISTINCT ?escritor, ?nombre, ?obra\n",
+ "\n",
+ "WHERE {\n",
+ "# YOUR ANSWER HERE\n",
+ "}\n",
+ "# YOUR ANSWER HERE\n",
+ "LIMIT 10000"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "51acaeb26379c6bd2f8c767001ef79ec",
+ "grade": true,
+ "grade_id": "cell-68661b73c2140e4f",
+ "locked": true,
+ "points": 0,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "assert 'http://dbpedia.org/resource/A_Heart_So_White' in solution()['columns']['obra']\n",
+ "assert 'http://dbpedia.org/resource/Tomorrow_in_the_Battle_Think_on_Me' in solution()['columns']['obra']\n",
+ "assert '' in solution()['columns']['obra'] # Some authors don't have works in dbpedia"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Traversing the graph"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Get a list of living Spanish novelists born in Madrid, their name in Spanish, a link to their foto and a website (if they have one).\n",
+ "\n",
+ "If the query is right, you should see a list of writers after running the test code.\n",
+ "\n",
+ "Hint: `foaf:depiction` and `foaf: homepage`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "e3f8e18a006a763f5cdbe49c97b73f5f",
+ "grade": false,
+ "grade_id": "cell-b1f71c67dd71dad4",
+ "locked": false,
+ "schema_version": 3,
+ "solution": true
+ }
+ },
+ "outputs": [],
+ "source": [
+ "%%sparql http://dbpedia.org/sparql\n",
+ "\n",
+ "PREFIX rdfs: \n",
+ "PREFIX dct:\n",
+ "PREFIX dbc:\n",
+ "PREFIX dbr:\n",
+ "PREFIX dbo:\n",
+ "\n",
+ "SELECT ?escritor ?web ?foto\n",
+ "\n",
+ "WHERE {\n",
+ "# YOUR ANSWER HERE\n",
+ "}\n",
+ "ORDER BY ?nombre\n",
+ "LIMIT 100"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "2d40e7ceb7774b29a709092ee8dfa9f5",
+ "grade": true,
+ "grade_id": "cell-8b8ba7cca701c652",
+ "locked": true,
+ "points": 0,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "fotos = set(filter(lambda x: x != '', solution()['columns']['foto']))\n",
+ "assert len(fotos) > 2\n",
+ "show_photos(fotos) #show the pictures of the writers!"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Union"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can merge the results of several queries, just like using `JOIN` in SQL.\n",
+ "The keyword in SPARQL is `UNION`, because we are merging graphs.\n",
+ "\n",
+ "`UNION` is useful in many situations.\n",
+ "For instance, when there are equivalent properties, or when you want to use two search terms and FILTER would be too inefficient.\n",
+ "\n",
+ "The syntax is as follows:\n",
+ "\n",
+ "```sparql\n",
+ "SELECT ?title\n",
+ "WHERE {\n",
+ " { ?book dc10:title ?title }\n",
+ " UNION\n",
+ " { ?book dc11:title ?title }\n",
+ " \n",
+ " ... REST OF YOUR QUERY ...\n",
+ "\n",
+ "}\n",
+ "```\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Using UNION, get a list of distinct spanish novelists AND poets.\n",
+ "\n",
+ "Hint: Category: Spanish_poets"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "9c0da379841474601397f5623abc6a9c",
+ "grade": false,
+ "grade_id": "cell-21eb6323b6d0011d",
+ "locked": false,
+ "schema_version": 3,
+ "solution": true
+ }
+ },
+ "outputs": [],
+ "source": [
+ "%%sparql http://dbpedia.org/sparql\n",
+ "\n",
+ "PREFIX rdfs: \n",
+ "PREFIX dct:\n",
+ "PREFIX dbc:\n",
+ "PREFIX dbr:\n",
+ "PREFIX dbo:\n",
+ "\n",
+ "SELECT DISTINCT ?escritor, ?nombre\n",
+ "\n",
+ "WHERE {\n",
+ "# YOUR ANSWER HERE\n",
+ "}\n",
+ "# YOUR ANSWER HERE\n",
+ "LIMIT 10000"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "f22c7db423410fcf3e8fce4ec0a8e9f9",
+ "grade": true,
+ "grade_id": "cell-004e021e877c6ace",
+ "locked": true,
+ "points": 0,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "assert 'Garcilaso de la Vega' in solution()['columns']['nombre']"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "You can also get the count of results either by inspecting the result (we will not cover this) or by aggregating the results using the `COUNT` operation.\n",
+ "\n",
+ "The syntax is:\n",
+ " \n",
+ "```sparql\n",
+ "SELECT COUNT(?variable) as ?count_name\n",
+ "```\n",
+ "\n",
+ "Try it yourself with our previous example:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "cd7ce9212f587afe311c7631b3908de2",
+ "grade": false,
+ "grade_id": "cell-e35414e191c5bf16",
+ "locked": false,
+ "schema_version": 3,
+ "solution": true
+ }
+ },
+ "outputs": [],
+ "source": [
+ "%%sparql http://dbpedia.org/sparql\n",
+ "\n",
+ "PREFIX rdfs: \n",
+ "PREFIX dct:\n",
+ "PREFIX dbc:\n",
+ "PREFIX dbr:\n",
+ "PREFIX dbo:\n",
+ "\n",
+ "# YOUR ANSWER HERE\n",
+ "\n",
+ "WHERE {\n",
+ "# YOUR ANSWER HERE\n",
+ "}\n",
+ "LIMIT 10000"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "68609fa02dcf7480e16f0e5eb7849e65",
+ "grade": true,
+ "grade_id": "cell-7a7ef8255a5662e2",
+ "locked": true,
+ "points": 0,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "assert len(solution()['columns']) == 1\n",
+ "column_name = list(solution()['columns'].keys())[0]\n",
+ "assert int(solution()['columns'][column_name][0]) > 200"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Additional exercises"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Find out if there are more dbpedia entries for writers (dbo:Writer) than for football players (dbo:SoccerPlayers)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Get a list of European countries with a population higher than 20 million, in decreasing order of population, including their URI, name in English and population."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Find the country in the world that speaks the most languages. Show its name in Spanish, if available."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## References"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "* [RDFLib documentation](https://rdflib.readthedocs.io/en/stable/).\n",
+ "* [Wikidata Query Service query examples](https://www.wikidata.org/wiki/Wikidata:SPARQL_query_service/queries/examples)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Licence\n",
+ "The notebook is freely licensed under under the [Creative Commons Attribution Share-Alike license](https://creativecommons.org/licenses/by/2.0/). \n",
+ "\n",
+ "© 2018 Universidad Politécnica de Madrid."
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.1"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/lod/04_SPARQL_Advanced.ipynb b/lod/04_SPARQL_Advanced.ipynb
new file mode 100644
index 0000000..20d399b
--- /dev/null
+++ b/lod/04_SPARQL_Advanced.ipynb
@@ -0,0 +1,661 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "markdown",
+ "checksum": "7276f055a8c504d3c80098c62ed41a4f",
+ "grade": false,
+ "grade_id": "cell-0bfe38f97f6ab2d2",
+ "locked": true,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "source": [
+ "\n",
+ " \n",
+ "
Course Notes for Learning Intelligent Systems
\n",
+ " Department of Telematic Engineering Systems
\n",
+ " Universidad Politécnica de Madrid
\n",
+ " \n",
+ " \n",
+ ""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "markdown",
+ "checksum": "bd478e6253226d24ba7f33cb9f6ba706",
+ "grade": false,
+ "grade_id": "cell-0cd673883ee592d1",
+ "locked": true,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "source": [
+ "## Advanced SPARQL\n",
+ "\n",
+ "This notebook complements [the SPARQL notebook](./01_SPARQL.ipynb) with some advanced commands.\n",
+ "\n",
+ "If you have not completed the exercises in the previous notebook, please do so before continuing.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "markdown",
+ "checksum": "9ea4fd529653214745b937d5fc4559e5",
+ "grade": false,
+ "grade_id": "cell-10264483046abcc4",
+ "locked": true,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "source": [
+ "## Objectives\n",
+ "\n",
+ "* To cover some SPARQL concepts that are less frequently used "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "markdown",
+ "checksum": "2fedf0d73fc90104d1ab72c3413dfc83",
+ "grade": false,
+ "grade_id": "cell-4f8492996e74bf20",
+ "locked": true,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "source": [
+ "## Tools\n",
+ "\n",
+ "See [the SPARQL notebook](./01_SPARQL_Introduction.ipynb#Tools)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "markdown",
+ "checksum": "c5f8646518bd832a47d71f9d3218237a",
+ "grade": false,
+ "grade_id": "cell-eb13908482825e42",
+ "locked": true,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "source": [
+ "Run this line to enable the `%%sparql` magic command."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from helpers import *"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Exercises"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Working with dates"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "To explore dates, we will focus on our Writers example.\n",
+ "\n",
+ "First, search for writers born in the XX century.\n",
+ "You can use a special filter, knowing that `\"2000\"^^xsd:date` is the first date of year 2000."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "69e23e6e3dc06ca9d2b5d878c2baba94",
+ "grade": false,
+ "grade_id": "cell-ab7755944d46f9ca",
+ "locked": false,
+ "schema_version": 3,
+ "solution": true
+ }
+ },
+ "outputs": [],
+ "source": [
+ "%%sparql\n",
+ "\n",
+ "PREFIX rdfs: \n",
+ "PREFIX dct:\n",
+ "PREFIX dbc:\n",
+ "PREFIX dbo:\n",
+ "\n",
+ "SELECT ?escritor, ?nombre, year(?fechaNac) as ?nac\n",
+ "\n",
+ "WHERE {\n",
+ " ?escritor dct:subject dbc:Spanish_novelists .\n",
+ " ?escritor rdfs:label ?nombre .\n",
+ " ?escritor dbo:birthDate ?fechaNac .\n",
+ " FILTER(lang(?nombre) = \"es\") .\n",
+ " # YOUR ANSWER HERE\n",
+ "}\n",
+ "# YOUR ANSWER HERE\n",
+ "LIMIT 1000"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "211c632634327a1fd805326fa0520cdd",
+ "grade": true,
+ "grade_id": "cell-cf3821f2d33fb0f6",
+ "locked": true,
+ "points": 0,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "assert 'Camilo José Cela' in solution()['columns']['nombre']\n",
+ "assert 'Javier Marías' in solution()['columns']['nombre']\n",
+ "assert all(int(x) > 1899 and int(x) < 2001 for x in solution()['columns']['nac'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Now, get the list of Spanish novelists that are still alive.\n",
+ "\n",
+ "A person is alive if their death date is not defined and the were born less than 100 years ago.\n",
+ "\n",
+ "Remember, we can check whether the optional value for a key was bound in a SPARQL query using `BOUND(?key)`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "e4579d551790c33ba4662562c6a05d99",
+ "grade": false,
+ "grade_id": "cell-474b1a72dec6827c",
+ "locked": false,
+ "schema_version": 3,
+ "solution": true
+ }
+ },
+ "outputs": [],
+ "source": [
+ "%%sparql\n",
+ "\n",
+ "PREFIX rdfs: \n",
+ "PREFIX dct:\n",
+ "PREFIX dbc:\n",
+ "PREFIX dbo:\n",
+ "\n",
+ "SELECT ?escritor, ?nombre, year(?fechaNac) as ?nac\n",
+ "\n",
+ "WHERE {\n",
+ " ?escritor dct:subject dbc:Spanish_novelists .\n",
+ " ?escritor rdfs:label ?nombre .\n",
+ " ?escritor dbo:birthDate ?fechaNac .\n",
+ "# YOUR ANSWER HERE\n",
+ " FILTER(lang(?nombre) = \"es\") .\n",
+ "}\n",
+ "# YOUR ANSWER HERE\n",
+ "LIMIT 1000"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "770bbddef5210c28486a1929e4513ada",
+ "grade": true,
+ "grade_id": "cell-46b62dd2856bc919",
+ "locked": true,
+ "points": 0,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "assert 'Fernando Arrabal' in solution()['columns']['nombre']\n",
+ "assert 'Albert Espinosa' in solution()['columns']['nombre']\n",
+ "for year in solution()['columns']['nac']:\n",
+ " assert int(year) >= 1918"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Working with badly formatted dates (OPTIONAL!)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Now, get the list of Spanish novelists that died before their fifties (i.e. younger than 50 years old), or that aren't 50 years old yet.\n",
+ "\n",
+ "For the sake of simplicity, you can use the `year()` function.\n",
+ "\n",
+ "Hint: you can use boolean logic in your filters (e.g. `&&` and `||`).\n",
+ "\n",
+ "Hint 2: Some dates are not formatted properly, which makes some queries fail when they shouldn't. As a workaround, you could convert the date to string, and back to date again: `xsd:dateTime(str(?date))`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "2a24f623c23116fd23877facb487dd16",
+ "grade": false,
+ "grade_id": "cell-ceefd3c8fbd39d79",
+ "locked": false,
+ "schema_version": 3,
+ "solution": true
+ }
+ },
+ "outputs": [],
+ "source": [
+ "%%sparql\n",
+ "\n",
+ "PREFIX rdfs: \n",
+ "PREFIX dct:\n",
+ "PREFIX dbc:\n",
+ "PREFIX dbo:\n",
+ "\n",
+ "SELECT ?escritor, ?nombre, year(?fechaNac) as ?nac, ?fechaDef\n",
+ "\n",
+ "WHERE {\n",
+ " ?escritor dct:subject dbc:Spanish_novelists .\n",
+ " ?escritor rdfs:label ?nombre .\n",
+ " ?escritor dbo:birthDate ?fechaNac .\n",
+ " # YOUR ANSWER HERE\n",
+ "}\n",
+ "# YOUR ANSWER HERE\n",
+ "LIMIT 100"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "18bb2d8d586bf4a5231973e69958ab75",
+ "grade": true,
+ "grade_id": "cell-461cd6ccc6c2dc79",
+ "locked": true,
+ "points": 0,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "assert 'Javier Sierra' in solution()['columns']['nombre']\n",
+ "assert 'http://dbpedia.org/resource/Sanmao_(author)' in solution()['columns']['escritor']"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Regular expressions"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "[Regular expressions](https://www.w3.org/TR/rdf-sparql-query/#funcex-regex) are a very powerful tool, but we will only cover the basics in this exercise.\n",
+ "\n",
+ "In essence, regular expressions match strings against patterns.\n",
+ "In their simplest form, they can be used to find substrings within a variable.\n",
+ "For instance, using `regex(?label, \"substring\")` would only match if and only if the `?label` variable contains `substring`.\n",
+ "But regular expressions can be more complex than that.\n",
+ "For instance, we can find patterns such as: a 10 digit number, a 5 character long string, or variables without whitespaces.\n",
+ "\n",
+ "The syntax of the regex function is the following:\n",
+ "\n",
+ "```\n",
+ "regex(?variable, \"pattern\", \"flags\")\n",
+ "```\n",
+ "\n",
+ "Flags are optional configuration options for the regular expression, such as *do not care about case* (`i` flag).\n",
+ "\n",
+ "As an example, let us find the cities in Madrid that contain \"de\" in their name."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%%sparql\n",
+ "\n",
+ "SELECT ?localidad\n",
+ "WHERE {\n",
+ " ?localidad .\n",
+ " ?localidad rdfs:label ?nombre .\n",
+ " FILTER (lang(?nombre) = \"es\" ).\n",
+ " FILTER regex(?nombre, \"de\", \"i\")\n",
+ "}\n",
+ "LIMIT 10"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Now, use regular expressions to find Spanish novelists whose **first name** is Juan.\n",
+ "In other words, their name **starts with** \"Juan\"."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "6e444c20b411033a6c45fd5a566018fa",
+ "grade": false,
+ "grade_id": "cell-a57d3546a812f689",
+ "locked": false,
+ "schema_version": 3,
+ "solution": true
+ }
+ },
+ "outputs": [],
+ "source": [
+ "%%sparql\n",
+ "\n",
+ "PREFIX rdfs: \n",
+ "PREFIX dct:\n",
+ "PREFIX dbc:\n",
+ "PREFIX dbr:\n",
+ "PREFIX dbo:\n",
+ "\n",
+ "# YOUR ANSWER HERE\n",
+ "\n",
+ "WHERE {\n",
+ " {\n",
+ " ?escritor dct:subject dbc:Spanish_poets .\n",
+ " }\n",
+ " UNION {\n",
+ " ?escritor dct:subject dbc:Spanish_novelists .\n",
+ " }\n",
+ " ?escritor rdfs:label ?nombre\n",
+ " FILTER(lang(?nombre) = \"es\") .\n",
+ "# YOUR ANSWER HERE\n",
+ "}\n",
+ "ORDER BY ?nombre\n",
+ "LIMIT 1000"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "66db9abddfafa91c2dc25577457f71fb",
+ "grade": true,
+ "grade_id": "cell-c149fe65008f39a9",
+ "locked": true,
+ "points": 0,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "assert len(solution()['columns']['nombre']) > 15\n",
+ "for i in solution()['columns']['nombre']:\n",
+ " assert 'Juan' in i\n",
+ "assert \"Robert Juan-Cantavella\" not in solution()['columns']['nombre']"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "markdown",
+ "checksum": "1be6d6e4d8e74240ef07deffcbe5e71a",
+ "grade": false,
+ "grade_id": "cell-0c2f0113d97dc9de",
+ "locked": true,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "source": [
+ "## Group concat"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "markdown",
+ "checksum": "c8dbb73a781bd24080804f289a1cea0b",
+ "grade": false,
+ "grade_id": "asdasdasdddddddddddasdasdsad",
+ "locked": true,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "source": [
+ "Sometimes, it is useful to aggregate results from form different rows.\n",
+ "For instance, we might want to get a comma-separated list of the names in each each autonomous community in Spain.\n",
+ "\n",
+ "In those cases, we can use the `GROUP_CONCAT` function."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%%sparql\n",
+ "\n",
+ "PREFIX rdfs: \n",
+ "PREFIX dbo: \n",
+ "PREFIX dbr: \n",
+ " \n",
+ "SELECT ?com, GROUP_CONCAT(?name, \",\") as ?places # notice how we rename the variable\n",
+ "\n",
+ "WHERE {\n",
+ " ?localidad dbo:isPartOf ?com .\n",
+ " ?com dbo:type dbr:Autonomous_communities_of_Spain .\n",
+ " ?localidad rdfs:label ?name .\n",
+ " FILTER (lang(?name)=\"es\")\n",
+ "}\n",
+ "\n",
+ "ORDER BY ?com\n",
+ "LIMIT 100"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "deletable": false,
+ "editable": false,
+ "nbgrader": {
+ "cell_type": "markdown",
+ "checksum": "e100e2f89c832cf832add62c107e4008",
+ "grade": false,
+ "grade_id": "asdiopjasdoijasdoijasd",
+ "locked": true,
+ "schema_version": 3,
+ "solution": false
+ }
+ },
+ "source": [
+ "Try it yourself, to get a list of works by each of these authors:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "deletable": false,
+ "nbgrader": {
+ "cell_type": "code",
+ "checksum": "9f6e26faab2be98c72fb7a917ac5a421",
+ "grade": false,
+ "grade_id": "cell-2e3de17c75047652",
+ "locked": false,
+ "schema_version": 3,
+ "solution": true
+ }
+ },
+ "outputs": [],
+ "source": [
+ "%%sparql\n",
+ "\n",
+ "PREFIX rdfs: \n",
+ "PREFIX dct:\n",
+ "PREFIX dbc:\n",
+ "PREFIX dbr:\n",
+ "PREFIX dbo:\n",
+ "\n",
+ "# YOUR ANSWER HERE\n",
+ "\n",
+ "WHERE {\n",
+ " ?escritor dct:subject dbc:Spanish_novelists .\n",
+ " ?escritor rdfs:label ?nombre .\n",
+ " ?escritor dbo:birthDate ?fechaNac .\n",
+ " ?escritor dbo:birthPlace dbr:Madrid .\n",
+ " OPTIONAL {\n",
+ " ?obra dbo:author ?escritor .\n",
+ " ?obra rdfs:label ?titulo .\n",
+ " }\n",
+ " OPTIONAL {\n",
+ " ?escritor dbo:deathDate ?fechaDef .\n",
+ " }\n",
+ " FILTER (?fechaNac <= \"2000\"^^xsd:date).\n",
+ " FILTER (?fechaNac >= \"1918\"^^xsd:date).\n",
+ " FILTER (!bound(?fechaDef) || (?fechaNac >= \"1918\"^^xsd:date)) .\n",
+ " FILTER(lang(?nombre) = \"es\") .\n",
+ " FILTER(!bound(?titulo) || lang(?titulo) = \"en\") .\n",
+ "\n",
+ "}\n",
+ "ORDER BY ?nombre\n",
+ "LIMIT 10000"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## References"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Licence\n",
+ "The notebook is freely licensed under under the [Creative Commons Attribution Share-Alike license](https://creativecommons.org/licenses/by/2.0/). \n",
+ "\n",
+ "© 2018 Universidad Politécnica de Madrid."
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.1"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/lod/helpers.py b/lod/helpers.py
index 7798189..e73a0d5 100644
--- a/lod/helpers.py
+++ b/lod/helpers.py
@@ -20,7 +20,9 @@ display_javascript(js, raw=True)
def send_query(query, endpoint):
- FORMATS = ",".join(["application/sparql-results+json", "text/javascript", "application/json"])
+ FORMATS = ",".join(["application/sparql-results+json",
+ "text/javascript",
+ "application/json"])
data = {'query': query}
# b = quote_plus(query)
@@ -33,7 +35,11 @@ def send_query(query, endpoint):
res = urlopen(r)
data = res.read().decode('utf-8')
if res.getcode() == 200:
- return json.loads(data)
+ try:
+ return json.loads(data)
+ except Exception:
+ print('Got: ', data, file=sys.stderr)
+ raise
raise Exception('Error getting results: {}'.format(data))
@@ -60,7 +66,7 @@ def solution():
def query(query, endpoint=None, print_table=False):
global LAST_QUERY
- endpoint = endpoint or "http://fuseki.cluster.gsi.dit.upm.es/sitc/"
+ endpoint = endpoint or "http://fuseki.gsi.upm.es/sitc/"
results = send_query(query, endpoint)
tuples = to_table(results)
diff --git a/lod/upload.sh b/lod/upload.sh
new file mode 100644
index 0000000..01a70a9
--- /dev/null
+++ b/lod/upload.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+# This is a bit messy
+if [ "$#" -lt 1 ]; then
+ graph="http://example.com/sitc/submission/"
+ endpoint="http://fuseki.gsi.upm.es/hotels/data"
+else if [ "$#" -lt 2 ]; then
+ endpoint=$1
+ graph_base="http://example.com/sitc"
+ else
+ if [ "$#" -lt 3 ]; then
+ endpoint=$1
+ graph=$2
+ else
+ echo "Usage: $0 [] []"
+ echo
+ exit 1
+ fi
+ fi
+fi
+
+
+upload(){
+ name=$1
+ file=$2
+ echo '###'
+ echo "Uploading: $graph"
+ echo "Graph: $graph"
+ echo "Endpoint: $endpoint"
+ curl -X POST \
+ --digest -u admin:$PASSWORD \
+ -H Content-Type:text/turtle \
+ -T "$file" \
+ --data-urlencode graph=$graph_base/$name \
+ -G $endpoint
+
+}
+
+
+total=0
+echo -n "Password: "
+read -s PASSWORD
+
+echo "Uploading synthethic"
+upload "synthetic" synthetic/reviews.ttl || exit 1
+
+for i in *.ttl; do
+ identifier=$(echo ${i%.ttl} | md5sum | awk '{print $1}')
+ echo "Uploading $i"
+ upload $identifier $i
+ total=$((total + 1))
+done
+echo Uploaded $total
diff --git a/rdf/RDF.ipynb b/rdf/RDF.ipynb
index 1dc4938..07c4a6e 100644
--- a/rdf/RDF.ipynb
+++ b/rdf/RDF.ipynb
@@ -6,11 +6,12 @@
"deletable": false,
"editable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "1fba29f718bbaa14890b305223712474",
"grade": false,
"grade_id": "cell-2bd9e19ffed99f81",
"locked": true,
- "schema_version": 1,
+ "schema_version": 3,
"solution": false
}
},
@@ -31,11 +32,12 @@
"deletable": false,
"editable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "845cf125f1c5eb7aa3653ef461bffc67",
"grade": false,
"grade_id": "cell-51338a0933103db9",
"locked": true,
- "schema_version": 1,
+ "schema_version": 3,
"solution": false
}
},
@@ -86,11 +88,12 @@
"deletable": false,
"editable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "5c2cccdf6463262a0f8bc89c64f97fb2",
"grade": false,
"grade_id": "cell-d8db3c16cee92ac1",
"locked": true,
- "schema_version": 1,
+ "schema_version": 3,
"solution": false
}
},
@@ -175,11 +178,12 @@
"deletable": false,
"editable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "d2849a6154d4807b405e6ec84601c231",
"grade": false,
"grade_id": "cell-14e2327285737802",
"locked": true,
- "schema_version": 1,
+ "schema_version": 3,
"solution": false
}
},
@@ -222,11 +226,12 @@
"deletable": false,
"editable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "fe9a246ba580c71385e9b83d414a1216",
"grade": false,
"grade_id": "cell-a1b60daabb1a9d00",
"locked": true,
- "schema_version": 1,
+ "schema_version": 3,
"solution": false
}
},
@@ -240,11 +245,12 @@
"deletable": false,
"editable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "63879c425ec11742c95c728a578d109e",
"grade": false,
"grade_id": "cell-d9289e96b2b0f265",
"locked": true,
- "schema_version": 1,
+ "schema_version": 3,
"solution": false
}
},
@@ -258,11 +264,12 @@
"deletable": false,
"editable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "32f1f607adb584aaea9fb90ae4d805b5",
"grade": false,
"grade_id": "cell-bb418e9bae1fef1a",
"locked": true,
- "schema_version": 1,
+ "schema_version": 3,
"solution": false
}
},
@@ -277,11 +284,12 @@
"deletable": false,
"editable": false,
"nbgrader": {
+ "cell_type": "code",
"checksum": "892f8491591c25defdea5fdcdd289489",
"grade": false,
"grade_id": "cell-4a1b60bd9974bbb1",
"locked": true,
- "schema_version": 1,
+ "schema_version": 3,
"solution": false
}
},
@@ -295,12 +303,13 @@
"metadata": {
"deletable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "a855d3d63be5ea7f73fd85d645b21bfe",
"grade": true,
"grade_id": "cell-9ac392294d5708a1",
"locked": false,
"points": 0,
- "schema_version": 1,
+ "schema_version": 3,
"solution": true
}
},
@@ -320,11 +329,12 @@
"deletable": false,
"editable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "9a73f79f8f282874fb60011e6019e387",
"grade": false,
"grade_id": "cell-57f67d1e662b7f09",
"locked": true,
- "schema_version": 1,
+ "schema_version": 3,
"solution": false
}
},
@@ -341,11 +351,12 @@
"deletable": false,
"editable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "18ad887c2f326ee59139b96860ce8893",
"grade": false,
"grade_id": "cell-16214ea73a9b689e",
"locked": true,
- "schema_version": 1,
+ "schema_version": 3,
"solution": false
}
},
@@ -359,11 +370,12 @@
"deletable": false,
"editable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "ed2466715f57356f22ddeabfb101eb11",
"grade": false,
"grade_id": "cell-da88c2f8170436fe",
"locked": true,
- "schema_version": 1,
+ "schema_version": 3,
"solution": false
}
},
@@ -382,11 +394,12 @@
"metadata": {
"deletable": false,
"nbgrader": {
+ "cell_type": "code",
"checksum": "69182e8fadb9c9751f76786e0fcb8803",
"grade": false,
"grade_id": "cell-808cfcbf3891f39f",
"locked": false,
- "schema_version": 1,
+ "schema_version": 3,
"solution": true
}
},
@@ -403,11 +416,12 @@
"deletable": false,
"editable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "60a9934c544eee9fc2c3745c36beb049",
"grade": false,
"grade_id": "cell-1c2ca86de107dec3",
"locked": true,
- "schema_version": 1,
+ "schema_version": 3,
"solution": false
}
},
@@ -424,11 +438,12 @@
"deletable": false,
"editable": false,
"nbgrader": {
+ "cell_type": "code",
"checksum": "12b5c7170326932ff3c7e1688a5769b2",
"grade": false,
"grade_id": "cell-0154f8481bf393e8",
"locked": true,
- "schema_version": 1,
+ "schema_version": 3,
"solution": false
}
},
@@ -444,11 +459,12 @@
"deletable": false,
"editable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "b534d998c6d2e9f6bef8c2d88687a96b",
"grade": false,
"grade_id": "cell-adc7e6b7e96e8788",
"locked": true,
- "schema_version": 1,
+ "schema_version": 3,
"solution": false
}
},
@@ -478,11 +494,12 @@
"deletable": false,
"editable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "67540252804835faea83d96aab87aa29",
"grade": false,
"grade_id": "cell-e73f1933742f7ab3",
"locked": true,
- "schema_version": 1,
+ "schema_version": 3,
"solution": false
}
},
@@ -528,11 +545,12 @@
"deletable": false,
"editable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "d6f1bf2230282256e5fcb85dba0eef45",
"grade": false,
"grade_id": "cell-3241bf07ae153beb",
"locked": true,
- "schema_version": 1,
+ "schema_version": 3,
"solution": false
}
},
@@ -563,11 +581,12 @@
"metadata": {
"deletable": false,
"nbgrader": {
+ "cell_type": "code",
"checksum": "44f8be14db3d3e42b5b85f0485206346",
"grade": false,
"grade_id": "definition",
"locked": false,
- "schema_version": 1,
+ "schema_version": 3,
"solution": true
}
},
@@ -594,12 +613,13 @@
"deletable": false,
"editable": false,
"nbgrader": {
+ "cell_type": "code",
"checksum": "e8ba71b32e6d4f15aef9dc7fe70387fe",
"grade": true,
"grade_id": "cell-2fb6e144a6691ede",
"locked": true,
"points": 10,
- "schema_version": 1,
+ "schema_version": 3,
"solution": false
}
},
@@ -615,11 +635,12 @@
"deletable": false,
"editable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "75d90c9a83c694f61e51bd5c47a672d9",
"grade": false,
"grade_id": "cell-63a55e7b8b195d59",
"locked": true,
- "schema_version": 1,
+ "schema_version": 3,
"solution": false
}
},
@@ -633,11 +654,12 @@
"deletable": false,
"editable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "23632182da48df109721378408e57f01",
"grade": false,
"grade_id": "cell-3843c3ce98a77c56",
"locked": true,
- "schema_version": 1,
+ "schema_version": 3,
"solution": false
}
},
@@ -660,11 +682,12 @@
"deletable": false,
"editable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "6c4b25718f493ad5964370f412519543",
"grade": false,
"grade_id": "cell-f42c087c9065bb23",
"locked": true,
- "schema_version": 1,
+ "schema_version": 3,
"solution": false
}
},
@@ -706,12 +729,13 @@
"metadata": {
"deletable": false,
"nbgrader": {
+ "cell_type": "code",
"checksum": "c7af0b9af5a64773785cc890f2431c78",
"grade": true,
"grade_id": "cell-c2e5b58ea74e8276",
"locked": false,
"points": 1,
- "schema_version": 1,
+ "schema_version": 3,
"solution": true
}
},
@@ -728,11 +752,12 @@
"deletable": false,
"editable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "a29112f51cc3299c7cae27841feb7410",
"grade": false,
"grade_id": "cell-9bf9c7d7516fae75",
"locked": true,
- "schema_version": 1,
+ "schema_version": 3,
"solution": false
}
},
@@ -750,12 +775,13 @@
"metadata": {
"deletable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "56a77e133b532997723bf2f8116389e4",
"grade": true,
"grade_id": "cell-17508ecf96884653",
"locked": false,
"points": 1,
- "schema_version": 1,
+ "schema_version": 3,
"solution": true
}
},
@@ -769,11 +795,12 @@
"deletable": false,
"editable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "9311bca044d7057c86dd753f5343e19b",
"grade": false,
"grade_id": "cell-d36826d6323c96e8",
"locked": true,
- "schema_version": 1,
+ "schema_version": 3,
"solution": false
}
},
@@ -786,12 +813,13 @@
"metadata": {
"deletable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "ba7b24b557d627e2665ca31c75c24c23",
"grade": true,
"grade_id": "cell-17508ecf96884655",
"locked": false,
"points": 1,
- "schema_version": 1,
+ "schema_version": 3,
"solution": true
}
},
@@ -805,11 +833,12 @@
"deletable": false,
"editable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "853651c95cbcd69cd5f495f03d29d19a",
"grade": false,
"grade_id": "cell-e25a0db3fe8a6b4b",
"locked": true,
- "schema_version": 1,
+ "schema_version": 3,
"solution": false
}
},
@@ -822,12 +851,13 @@
"metadata": {
"deletable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "779f0f750508eb52b2d98b92689e426b",
"grade": true,
"grade_id": "cell-30797c9ac87cc7e1",
"locked": false,
"points": 1,
- "schema_version": 1,
+ "schema_version": 3,
"solution": true
}
},
@@ -841,11 +871,12 @@
"deletable": false,
"editable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "f8fff644855ca50a5219598322aa9b32",
"grade": false,
"grade_id": "cell-33862c8e38173d9c",
"locked": true,
- "schema_version": 1,
+ "schema_version": 3,
"solution": false
}
},
@@ -858,12 +889,13 @@
"metadata": {
"deletable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "8ef0ebd54eefb44ff7019f17f58be3ec",
"grade": true,
"grade_id": "cell-17508ecf96884657",
"locked": false,
"points": 1,
- "schema_version": 1,
+ "schema_version": 3,
"solution": true
}
},
@@ -877,11 +909,12 @@
"deletable": false,
"editable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "33e1ec78415c85a795e86211d88316c2",
"grade": false,
"grade_id": "cell-5f922dc14ad3236a",
"locked": true,
- "schema_version": 1,
+ "schema_version": 3,
"solution": false
}
},
@@ -894,12 +927,13 @@
"metadata": {
"deletable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "b5f208a95a8803e97f82c5f2cdf319dd",
"grade": true,
"grade_id": "answer-missing",
"locked": false,
"points": 1,
- "schema_version": 1,
+ "schema_version": 3,
"solution": true
}
},
@@ -913,11 +947,12 @@
"deletable": false,
"editable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "26eb04e562aa6c7d29efa8318982a337",
"grade": false,
"grade_id": "cell-7a3c1553c4d6a9b7",
"locked": true,
- "schema_version": 1,
+ "schema_version": 3,
"solution": false
}
},
@@ -961,12 +996,13 @@
"metadata": {
"deletable": false,
"nbgrader": {
+ "cell_type": "code",
"checksum": "bf8d215c42321236b783601e7d072a05",
"grade": true,
"grade_id": "cell-ff2413f45311f086",
"locked": false,
"points": 0,
- "schema_version": 1,
+ "schema_version": 3,
"solution": true
}
},
@@ -981,11 +1017,12 @@
"deletable": false,
"editable": false,
"nbgrader": {
+ "cell_type": "markdown",
"checksum": "cffc12120c51a7d994063f66d788570a",
"grade": false,
"grade_id": "cell-ec8df1a53c3d3f23",
"locked": true,
- "schema_version": 1,
+ "schema_version": 3,
"solution": false
}
},
@@ -1027,7 +1064,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.7.2"
+ "version": "3.8.1"
}
},
"nbformat": 4,