1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
|
<html>
<head>
<title>SemWeb: Querying</title>
<link rel="stylesheet" type="text/css" href="stylesheet.css"/>
</head>
<body>
<p><a href="index.html">SemWeb Documentation</a></p>
<h1>Inferencing: RDFS and the Euler Proof Engine</h1>
<p>SemWeb provides two inferencing classes in the <tt>SemWeb.Inference</tt> namespace: <tt>RDFS</tt>, which implements a subset of RDFS reasoning, and <tt>Euler</tt> which implements general rule-based reasoning based on the <a href="http://www.agfa.com/w3c/euler/">Euler proof mechanism</a>.</p>
<p>The two reasoning engines work similarly. They are initialized with axioms and then perform reasoning on an arbitrary target data model. For the <tt>RDFS</tt> class, the axioms are an RDFS schema that contains subClassOf relations between classes and subPropertyOf relations between properties. For the <tt>Euler</tt> class, the axioms are rules of entailment (and possibly some basic instance data). The data model contains an arbitrarily large data set that the axioms are applied to in order to answer some question about the data.</p>
<p>The best way to use these <tt>Reasoner</tt> classes is to apply them to a <tt>Store</tt> with the <tt>AddReasoner</tt> method. When this is done, the <tt>Contains</tt>, <tt>Select</tt>, and <tt>Query</tt> methods on the store will make use of the reasoner applied.</p>
<h2>RDFS Reasoning</h2>
<p>SemWeb's <tt>RDFS</tt> class provides limited RDFS reasoning over a data model. See the API documentation for a complete list of what reasoning the class provides.</p>
<p>To use the class, create an instance of it and then load in RDF schemas.</p>
<pre class="code">
RDFS engine = new RDFS();
engine.LoadSchema(RdfReader.LoadFromUri(new Uri("http://xmlns.com/foaf/0.1/index.rdf")));
</pre>
<p>Besides passing it an <tt>RdfReader</tt>, you may also pass it any <tt>SelectableSource</tt> with RDFS schema statements, such as a <tt>MemoryStore</tt> that you might construct with your own schema. You can call <tt>LoadSchema</tt> any number of times.</p>
<p>Then apply the <tt>RDFS</tt> instance to a <tt>Store</tt> object.</p>
<pre class="code">
dataModel.AddReasoner(engine);
</pre>
<p>The <tt>Contains</tt>, <tt>Select</tt>, and <tt>Query</tt> methods on the store will make use of the RDFS reasoner and will return anything entailed by the instance data in the data model and the schema.</p>
<p>For instance, if the dataModel contains the following:</p>
<pre class="code">
:me rdf:type foaf:Person .
:you rdf:type foaf:Person .
:me foaf:name "John Doe" .
:you foaf:name "Sam Smith" .
</pre>
<p>and you load in the FOAF schema, then the following will result</p>
<pre class="code">
dataModel.Contains(new Statement(me, rdfType, foafAgent)) => Returns True
dataModel.SelectSubjects(rdfType, foafAgent)) => Returns [ me , you ]
dataModel.Select(new Statement(null, rdfsLabel, null))
=> me rdfsLabel "John Doe"
=> you rdfsLabel "Sam Smith"
</pre>
<p>Note that when RDFS returns statements that were found by applying a subproperty closure, the returned statements do not show the subproperty actually in the instance data, but rather the property that was provided in the call to <tt>Select</tt>. Think of it this way: Select does not return statements in the data model that are relavent to the template, but rather it returns <i>all</i> possible statements that are entailed by the data model and schema that <i>match the template</i>.</p>
<p>A complete example of using the <tt>RDFS</tt> class is below:</p>
<pre class="code" file="../examples/rdfs.cs">// This example demonstrates basic RDFS reasoning.
using System;
using System.IO;
using SemWeb;
using SemWeb.Inference;
public class EulerTest {
public static void Main() {
// Create the instance data
MemoryStore dataModel = new MemoryStore();
BNode me = new BNode("me");
BNode you = new BNode("you");
Entity rdfType = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type";
Entity rdfsLabel= "http://www.w3.org/2000/01/rdf-schema#label";
Entity foafPerson = "http://xmlns.com/foaf/0.1/Person";
Entity foafAgent = "http://xmlns.com/foaf/0.1/Agent";
Entity foafName = "http://xmlns.com/foaf/0.1/name";
dataModel.Add(new Statement(me, rdfType, foafPerson));
dataModel.Add(new Statement(you, rdfType, foafPerson));
dataModel.Add(new Statement(me, foafName, (Literal)"John Doe"));
dataModel.Add(new Statement(you, foafName, (Literal)"Sam Smith"));
// Create the RDFS engine and apply it to the data model.
RDFS engine = new RDFS();
engine.LoadSchema(RdfReader.LoadFromUri(new Uri("http://xmlns.com/foaf/0.1/index.rdf")));
dataModel.AddReasoner(engine);
// Query the data model
// Ask for who are typed as Agents. Note that the people are
// typed as foaf:Person, and the schema asserts that foaf:Person
// is a subclass of foaf:Agent.
Console.WriteLine("Who are Agents?");
foreach (Entity r in dataModel.SelectSubjects(rdfType, foafAgent))
Console.WriteLine("\t" + r);
// Ask for the rdfs:labels of everyone. Note that the data model
// has foaf:names for the people, and the schema asserts that
// foaf:name is a subproperty of rdfs:label.
Console.WriteLine("People's labels:");
foreach (Statement s in dataModel.Select(new Statement(null, rdfsLabel, null)))
Console.WriteLine("\t" + s);
}
}
</pre>
<h2>General reasoning with the Euler engine</h2>
<p>SemWeb has an adaptation of the <a href="http://www.agfa.com/w3c/euler/">Euler proof mechanism</a> by Jos De Roo in the class <tt>Euler</tt> in the namespace <tt>SemWeb.Inference</tt>.</p>
<p>To use the class, create an instance of it and pass it a <tt>StatementSource</tt> with the rules of inference:</p>
<pre class="code">
string rules =
"@prefix : <http://www.agfa.com/w3c/euler/graph.axiom#>. " +
"{ ?a :oneway ?b } => { ?a :path ?b } . " +
"{ ?a :path ?b . ?b :path ?c . } => { ?a :path ?c } . ";
Euler engine = new Euler(new N3Reader(new StringReader(rules)));
</pre>
<p>Then form the question to be proved in the form a statement:</p>
<pre class="code">
Statement question = new Statement(paris, path, nantes);
</pre>
<p>One way to ask the question is to have the Euler engine return an array of proofs.</p>
<pre class="code">
Proof[] proofs = engine.Prove(dataModel, new Statement[] { question });
foreach (Proof p in proofs)
Console.WriteLine(p.ToString());
</pre>
<p>If it can't find a proof, a zero-length array is returned.</p>
<p>Alternatively, you may add the engine to a <tt>Store</tt> so that its <tt>Contains</tt>, <tt>Select</tt>, and <tt>Query</tt> methods make use of reasoning. With reasoning, the <tt>Contains</tt> method returns not just whether the statement is directly in the data model, but also whether it can be proved to be entailed by the data model.</p>
<pre class="code">
dataModel.AddReasoner(engine);
Console.WriteLine("Euler Says the Question is: " + dataModel.Contains(question));
</pre>
<p>A complete example for using <tt>Euler</tt> is below:</p>
<pre class="code" file="../examples/euler.cs">// This example demonstrates general reasoning with
// the Euler engine based on Jos De Roo's Euler proof
// mechanism. The example is based on the "graph"
// example from Euler.
using System;
using System.IO;
using SemWeb;
using SemWeb.Inference;
public class EulerTest {
public static void Main() {
// Create the instance data
MemoryStore dataModel = new MemoryStore();
BNode paris = new BNode("paris");
BNode orleans = new BNode("orleans");
BNode chartres = new BNode("chartres");
BNode amiens = new BNode("amiens");
BNode blois = new BNode("blois");
BNode bourges = new BNode("bourges");
BNode tours = new BNode("tours");
BNode lemans = new BNode("lemans");
BNode angers = new BNode("angers");
BNode nantes = new BNode("nantes");
Entity oneway = new Entity("http://www.agfa.com/w3c/euler/graph.axiom#oneway");
Entity path = new Entity("http://www.agfa.com/w3c/euler/graph.axiom#path");
dataModel.Add(new Statement(paris, oneway, orleans));
dataModel.Add(new Statement(paris, oneway, chartres));
dataModel.Add(new Statement(paris, oneway, amiens));
dataModel.Add(new Statement(orleans, oneway, blois));
dataModel.Add(new Statement(orleans, oneway, bourges));
dataModel.Add(new Statement(blois, oneway, tours));
dataModel.Add(new Statement(chartres, oneway, lemans));
dataModel.Add(new Statement(lemans, oneway, angers));
dataModel.Add(new Statement(lemans, oneway, tours));
dataModel.Add(new Statement(angers, oneway, nantes));
// Create the inference rules by reading them from a N3 string.
string rules =
"@prefix : <http://www.agfa.com/w3c/euler/graph.axiom#>.\n" +
"\n" +
"{ ?a :oneway ?b } => { ?a :path ?b } .\n" +
"{ ?a :path ?b . ?b :path ?c . } => { ?a :path ?c } .\n";
// Create our question in the form of a statement to test.
Statement question = new Statement(paris, path, nantes);
// Create the Euler engine
Euler engine = new Euler(new N3Reader(new StringReader(rules)));
// First Method of Inference:
// Ask the engine whether there is a path from paris to nantes.
// The Prove method will return a list of proofs, or an empty
// array if it could not find a proof.
foreach (Proof p in engine.Prove(dataModel, new Statement[] { question })) {
Console.WriteLine(p.ToString());
}
// Second Method of Inference:
// Apply the engine to the data model and then use the data
// model's Contains method to see if the statement is "in"
// the model + reasoning.
dataModel.AddReasoner(engine);
Console.WriteLine("Euler Says the Question is: " + dataModel.Contains(question));
}
}
</pre>
</body>
</html>
|