swish/commit

Updated examples to exploit notebooks.

authorJan Wielemaker
Mon Jul 6 15:42:02 2015 +0200
committerJan Wielemaker
Mon Jul 6 15:42:02 2015 +0200
commit52c420147ebdb024e0473994123663c823016dd7
treeb8e4b62906d0e9576ccb285e0bb7c0bcfa6ce0f3
parent608500aa2ee900170ebc126989eafb5888af777e
Diff style: patch stat
diff --git a/examples/basic_graph_examples.swinb b/examples/basic_graph_examples.swinb
new file mode 100644
index 0000000..2354c32
--- /dev/null
+++ b/examples/basic_graph_examples.swinb
@@ -0,0 +1,79 @@
+<div class="notebook">
+
+<div class="nb-cell markdown">
+# Basic graph queries
+
+The core predicates of the RDF library are rdf/3 and rdf/4, using the signature below.
+
+  - rdf(?Subject, ?Predicate, ?Object)
+  - rdf(?Subject, ?Predicate, ?Object, ?Graph)
+
+If you run the query below by pressing the *play* button SWISH generates a table.  The solutions are _rendered_ using the RDF renderer, which renders
+
+  - *resources* in abbreviated form, trying to show the _prefix_, followed
+  by a label.  The label is formed from `rdfs:label`, `skos:prefLabel`,
+  etc., eventually using the _local name_.  By *hovering over the top-left
+  corner* of the result, the raw Prolog form can be requested, which
+  is a Prolog atom representing the full IRI.
+  - *literals* are represented in their _Turtle_ representation.  Again,
+  by hovering and selecting _Prolog term_, you can view the actual
+  representation.
+
+Clicking a resource will open the ClioPatria _Local View_ on the resource.
+</div>
+
+<div data-tabled="true" class="nb-cell query">
+rdf(S, P, O).
+</div>
+
+<div class="nb-cell markdown">
+The rdf/3 and rdf/4 relations are _pure_, i.e., they behave completely logically if part of their arguments is instantiated.  So, to get the
+`rdf:type` triples, we can use the query below.  The _RDF_ prefix is defined using rdf_register_prefix/2, and therefore we can also abbreviate the query:
+</div>
+
+<div data-tabled="true" class="nb-cell query">
+rdf(S, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type', O).
+</div>
+
+<div data-tabled="true" class="nb-cell query">
+rdf(S, rdf:type, O).
+</div>
+
+<div class="nb-cell markdown">
+## Combining graph queries
+
+Basic rdf/3 patterns can be combined using Prolog's logical connectives.
+The basic ones are `A,B` for conjuction (join) and `A;B` for disjunction
+(union).  SPARQL OPTIONAL is realised by the *-&gt;/2 control structure:
+`(A *-&gt; true ; true)`, where the first `true` is excuted if `A` has no
+solutions and the second for each solution of `A`.
+
+Here is a simple pattern, expressing instances of a direct subclass of
+`foaf:Agent`.  Note that we need to put single quotes around `Agent` to
+turn it into an _atom_; identifiers that start with a capital letter are
+Prolog _variables_.
+</div>
+
+<div data-tabled="true" class="nb-cell query">
+rdf(S, rdf:type, C),
+rdf(C, rdfs:subClassOf, foaf:'Agent').
+</div>
+
+<div class="nb-cell markdown">
+## Naming queries
+
+One of the nicest things about using Prolog instead of e.g., SPARQL is that
+we can _name_ a pattern.  E.g.,
+</div>
+
+<div class="nb-cell program">
+foaf_agent_of_type(Agent, Type) :-
+    rdf(Agent, rdf:type, Type),
+	rdf(Type, rdfs:subClassOf, foaf:'Agent').
+</div>
+
+<div data-tabled="true" class="nb-cell query">
+foaf_agent_of_type(Agent, Type).
+</div>
+
+</div>
diff --git a/examples/demo.swinb b/examples/c3_examples.swinb
similarity index 100%
rename from examples/demo.swinb
rename to examples/c3_examples.swinb
diff --git a/examples/enumerating_examples.swinb b/examples/enumerating_examples.swinb
new file mode 100644
index 0000000..1ed8558
--- /dev/null
+++ b/examples/enumerating_examples.swinb
@@ -0,0 +1,36 @@
+<div class="notebook">
+
+<div class="nb-cell markdown">
+# Enumerating instances
+
+The RDF store contains various predicates for enumerating instances such as predicates,
+resources, graphs, etc.  These are strictly speaking not needed as one can enumerate all
+predicates using a call like this:
+</div>
+
+<div class="nb-cell query">
+distinct(rdf(_,P,_)).
+</div>
+
+<div class="nb-cell markdown">
+This however is rather slow as it enumerates all triples in the database and checks them against a table of already produced predicates.  The generator rdf_current_predicate/1 is much more efficient.  It however does not guarantee that the predicate still has triples.  In most cases
+generating too many resources will not change the result and a call to e.g., `rdf(_,P,_)` can
+be replaced by `rdf_current_predicate(P)`.  If it is necessary that there are triples known
+using this pattern:
+</div>
+
+<div class="nb-cell query">
+rdf_current_predicate(P), once(rdf(_,P,_)).
+</div>
+
+<div class="nb-cell markdown">
+The available enumerators are given below.  All of them, except for rdf_subject/1 may return too many answers, typically returning objects that have existed or exist inside a transaction or snapshot that is not visible from the current context.
+
+  - rdf_current_predicate/1
+  - rdf_current_literal/1
+  - rdf_graph/1
+  - rdf_resource/1
+  - rdf_subject/1
+</div>
+
+</div>
diff --git a/examples/examples.swinb b/examples/examples.swinb
new file mode 100644
index 0000000..facb125
--- /dev/null
+++ b/examples/examples.swinb
@@ -0,0 +1,34 @@
+<div class="notebook">
+
+<div class="nb-cell markdown">
+# Using SWISH with ClioPatria
+
+[SWISH](http://swish.swi-prolog.org) (SWI-Prolog for SHaring) provides a Prolog shell over the web that allows you to formulate queries in a modular fashion and handle results in several ways:
+
+  - As plain Prolog results.
+  - Using the SWISH [C3](http://www.c3js.org) chart renderer.
+  - Download as CSV.
+  - Query through the [Pengines](http://pengines.swi-prolog.org) API, which
+    allows for creating interactive (HTML5) web applications.
+  - See also the [client repository](https://github.com/SWI-Prolog/swish/tree/master/client).
+
+The rationale behind ClioPatria and querying it using Prolog is explained in [ClioPatria: A Logical Programming Infrastructure for the Semantic Web](http://www.semantic-web-journal.net/content/cliopatria-logical-programming-infrastructure-semantic-web-0).
+
+The ClioPatria version of SWISH can operate in two modes:
+
+  - In _anonymous_ mode, the user can only pose queries that do not
+    modify the database and are considered harmless.
+  - When logged in with *admin rights*, arbitrary Prolog queries can
+    be posed, which implies loading RDF, rewriting RDF data, updating
+    the loaded Prolog code using make/0, etc.
+
+We have composed several notebooks that explain the basic functionality of the SWI-Prolog RDF interface.
+
+  - [Basic graph queries](example/basic_graph_examples.swinb)
+  - [Using RDF prefixes](example/prefix_examples.swinb)
+  - [Using RDF Literals](example/literal_examples.swinb)
+  - [Enumerating instances](example/enumerating_examples.swinb)
+  - [Charting results](example/c3_examples.swinb)
+</div>
+
+</div>
diff --git a/examples/index.json b/examples/index.json
index b879053..0fbe5c8 100644
--- a/examples/index.json
+++ b/examples/index.json
@@ -1,10 +1,10 @@
 // list of examples, represented as a JSON list
 
 [
+{ "file":"examples.swinb",		  "title":"Examples" },
+"--",
 { "file":"rdf_queries.pl",		  "title":"General queries" },
 { "file":"rdf_literal.pl",		  "title":"Queries on literals" },
 { "file":"rdf_update.pl",		  "title":"Update queries" },
-{ "file":"maintenance.pl",		  "title":"Maintenance queries" },
-"--",
-{ "file":"demo.swinb",			  "title":"A very simple notebook" }
+{ "file":"maintenance.pl",		  "title":"Maintenance queries" }
 ]
diff --git a/examples/literal_examples.swinb b/examples/literal_examples.swinb
new file mode 100644
index 0000000..181700c
--- /dev/null
+++ b/examples/literal_examples.swinb
@@ -0,0 +1,50 @@
+<div class="notebook">
+
+<div class="nb-cell markdown">
+# Using RDF literals
+
+RDF literals are currently represented in one of the three formats below.  Note that RDF 1.1
+no longer has plain literals.  Plain literals are expected to be dropped.
+
+  - literal(Atom)
+  - literal(type(Type, Atom))
+  - literal(lang(Lang, Atom)).
+
+Also note that literals are expressed in their _lexical form_.  This means that the RDF
+literal value `42` is `literal(type('http://www.w3.org/2001/XMLSchema#integer', '42'))`.
+This is not very practical.  Future versions are likely to change this.  We consider the
+model below, following the _Turtle_ conventions.  In this case, `Value` will be a suitable
+Prolog representation for known values types.
+
+  - =|String@Lang|=
+  - =|Value^^Type|=
+  
+In addition to a simple direct match to a literal, rdf/3 and rdf/4 accept a query specification
+like below.  See rdf/3 for all possible specifications.  The _prefix_, _ge_ and _between_ searches exploit the fact that all literals are stored in a binary tree.
+</div>
+
+<div data-tabled="true" class="nb-cell query">
+rdf(S, P, literal(prefix('Jan'), Value)).
+</div>
+
+<div class="nb-cell markdown">
+## Full text search
+
+The library(semweb/rdf_litindex) indexes _tokens_ inside literal values.  The primary predicate is rdf_find_literal/2.  The following example finds all literals that contain a token that has the same stem as `exploit`.
+</div>
+
+<div class="nb-cell query">
+rdf_find_literal(stem(exploit), L).
+</div>
+
+<div class="nb-cell markdown">
+## Matching languages
+
+The predicate lang_matches/2 is provided to match a language pattern against a concrete language.  For example:
+</div>
+
+<div class="nb-cell query">
+lang_matches('EN.gb', 'en').
+</div>
+
+</div>
diff --git a/examples/prefix_examples.swinb b/examples/prefix_examples.swinb
new file mode 100644
index 0000000..ec1d5b2
--- /dev/null
+++ b/examples/prefix_examples.swinb
@@ -0,0 +1,104 @@
+<div class="notebook">
+
+<div class="nb-cell markdown">
+# Using RDF prefixes
+
+RDF prefixes make long RDF resources readable and consistent renaming of resources.
+They are supported by the Prolog predicates rdf_register_prefix/2, rdf_register_prefix/3 and rdf_current_prefix/2.  In the current version, RDF prefixes are _global_ to the SWI-Prolog instance, i.e., all parts of the program share the same prefix declarations.
+
+A consequence of this is that prefixes cannot be defined if SWISH operates in anonymous query mode.
+
+The currently known prefixes are easily enumerated:
+</div>
+
+<div data-chunk="100" data-tabled="true" class="nb-cell query">
+rdf_current_prefix(Prefix, IRI).
+</div>
+
+<div class="nb-cell markdown">
+## Where can I use prefixes?
+
+Prefix abbreviations can be inserted into arguments of the RDF API that expect a resource.  Here is an example.  Note `'Person'` is quoted to ensure it is an atom
+and not a Prolog _variable_.
+</div>
+
+<div data-tabled="true" class="nb-cell query">
+rdf(P, rdf:type, foaf:'Person').
+</div>
+
+<div class="nb-cell markdown">
+## How are prefixes handled?
+
+All resources in the RDF store are represented as Prolog _atoms_, exploiting the unique (_interned_) representation of atoms in Prolog to reduce storage requirements and speed up comparison.  The `rdf:type` notation is handled by Prolog _goal_ (macro) _expansion_ mechanism (see expand_goal/2).  We demonstate that in the program below.  Use the *play* button to see the expanded program.
+</div>
+
+<div class="nb-cell program">
+person(P) :-
+    rdf(P, rdf:type, foaf:'Person').
+</div>
+
+<div class="nb-cell query">
+listing(person/1).
+</div>
+
+<div class="nb-cell markdown">
+The main advantage of the macro-based handling of prefixes is that the expensive prefix expansion is done at compile time.  The price is that we must ensure it can be found and expanded at compile time.  For example, the following does *not* work:
+</div>
+
+<div class="nb-cell program">
+person(P) :-
+    Class = foaf:'Person',
+    rdf(P, rdf:type, Class).
+</div>
+
+<div class="nb-cell query">
+person(P).
+</div>
+
+<div class="nb-cell markdown">
+Something similar to the above example happens less obviously in real code.  We discuss these cases below.
+
+### A &lt;prefix&gt;:&lt;local&gt; term is passed to a user defined predicate. 
+
+In this case Prolog does not know that the user predicates expects a resource and thus does not expand the resource.  This can be fixed using an rdf_meta/1 declaration as shown in the code below, but unfortunately this is *not yet supported by SWISH*.
+    
+    ```
+    :- rdf_meta
+    	instance_of(r,r).
+
+    instance_of(I, Class) :-
+    	rdf(I, rdf:type, Class).
+
+    person(P) :-
+    	instance_of(P, foaf:'Person').
+    ```
+The work-around is to use rdf_equal/2.  This predicate is defines normal _unification_, but is annotated to expect an RDF resource as argument.  This
+results in the following definition:
+</div>
+
+<div class="nb-cell program">
+instance_of(I, Class) :-
+    rdf(I, rdf:type, Class).
+
+person(P) :-
+    rdf_equal(PersonClass, foaf:'Person'),
+    instance_of(P, PersonClass).
+</div>
+
+<div class="nb-cell query">
+listing(person/1).
+</div>
+
+<div class="nb-cell markdown">
+### The prefix or local name is not known at compile time
+
+Compile time expansion of course requires the prefix to be declared and the local name to be known at compile time.  If this is not the case, there is the predicate
+rdf_global_id/2, which can both be used to create an atomic resource and to split
+one into the prefix and local name.  Note the rendering of `Resource` as an abbreviated link and the rendering of `Term` as an ordinary Prolog term.
+</div>
+
+<div class="nb-cell query">
+Term = foaf:'Person', rdf_global_id(Term, Resource).
+</div>
+
+</div>