$$%% examples \newcommand{\exGraph}{\graph_{\mathrm{ex}}} \newcommand{\exOnto}{\onto_{\mathrm{ex}}} \newcommand{\exMappings}{\mappings_{\mathrm{ex}}} \newcommand{\exExtensions}{\extensions_{\mathrm{ex}}} \newcommand{\exRule}{r_{\mathrm{ex}}} \newcommand{\RDFSrules}{\rules_{\mathrm{RDFS}}} %% RDF \newcommand{\triple}[3]{(#1, #2, #3)} \newcommand{\tuple}[1]{\langle #1 \rangle} \newcommand{\subject}{\mathtt{s}} \newcommand{\prop}{\mathtt{p}} \newcommand{\object}{\mathtt{o}} \newcommand{\blank}{\_{:}b} \newcommand{\blankn}[1]{\_{:}#1} \newcommand{\irin}[1]{{:}\mathrm{#1}} \newcommand{\class}{\mathtt{c}} \newcommand{\nsrdf}{\mathrm{rdf{:}}} \newcommand{\nsrdfs}{\mathrm{rdfs{:}}} \newcommand{\rdftype}{\mathrm{rdf{:}type}} \newcommand{\rdfLiteral}{\mathrm{rdf{:}Literal}} \newcommand{\rdfssubClassOf}{\mathrm{rdfs{:}subClassOf}} \newcommand{\rdfssubPropertyOf}{\mathrm{rdfs{:}subPropertyOf}} \newcommand{\rdfsdomain}{\mathrm{rdfs{:}domain}} \newcommand{\rdfsrange}{\mathrm{rdfs{:}range}} \newcommand{\rdfsClass}{\mathrm{rdfs{:}Class}} \newcommand{\rdfProperty}{\mathrm{rdf{:}Property}} \newcommand{\xsdint}{\mathrm{xsd{:}int}} %% \newcommand{\type}{\tau} \newcommand{\subclass}{\prec_{sc}} \newcommand{\subproperty}{\prec_{sp}} \newcommand{\domain}{\hookleftarrow_{d}} \newcommand{\range}{\hookrightarrow_{r}} \newcommand{\rdfentailment}{\vdash_{^\mathrm{RDF}}} \newcommand{\RDFS}[1]{\mathrm{RDFS}(#1)} \newcommand{\aka}{a.k.a.~} \newcommand{\etc}{etc} \newcommand{\wrt}{w.r.t.~} \newcommand{\st}{s.t.~} \newcommand{\ie}{i.e.,~} \newcommand{\eg}{e.g.,~} \newcommand{\graph}{G} \newcommand{\rules}{\mathcal{R}} \newcommand{\sources}{\mathcal{S}} \newcommand{\views}{\mathcal{V}} \newcommand{\extensions}{\mathcal{E}} \newcommand{\onto}{\mathcal{O}} \newcommand{\mappings}{\mathcal{M}} \newcommand{\modelsrdf}{\models_\rules} \newcommand{\bgp}{P} \newcommand{\Bl}[1]{\mathrm{Bl}(#1)} \newcommand{\Val}[1]{\mathrm{Val}(#1)} \newcommand{\Var}[1]{\mathrm{Var(#1)}} \newcommand{\ext}[1]{\mathrm{ext}(#1)} \newcommand{\cert}{\mathrm{cert}} \newcommand{\ans}{\mathrm{ans}} \newcommand{\query}{\leftarrow} \newcommand{\body}[1]{\textrm{body}(#1)} \newcommand{\head}[1]{\textrm{head}(#1)} \newcommand{\cs}{\mathrm{cs}} \newcommand{\lcs}{\mathrm{lcs}} \newcommand{\cl}{\mathrm{cl}} \newcommand{\lua}{\mathrm{lua}} \newcommand{\lur}{\mathrm{lur}} \newtheorem{lemma}{Lemma} \newtheorem{definition}{Definition} \newtheorem{problem}{Problem} \newtheorem{property}{Property} \newtheorem{corollary}{Corollary} \newtheorem{example}{Example} \newtheorem{theorem}{Theorem} \newcommand{\URIs}{\mathscr U} \newcommand{\IRIs}{\mathscr I} \newcommand{\BNodes}{\mathscr B} \newcommand{\Literals}{\mathscr L} \newcommand{\Variables}{\mathscr V} % DB \newcommand{\CQ}{\ensuremath{\mathtt{CQ}}\xspace} \newcommand{\UCQ}{\ensuremath{\mathtt{UCQ}}\xspace} \newcommand{\SQL}{\ensuremath{\mathtt{SQL}}\xspace} \newcommand{\rel}[1]{\mathsf{#1}} % Cost model \newcommand{\cans}[1]{|#1|_t} \newcommand{\cref}[1]{|#1|_r} \newcommand{\db}{\mathtt{db}} % DL \newcommand{\cn}{\ensuremath{N_{C}}\xspace} \newcommand{\rn}{\ensuremath{N_{R}}\xspace} \newcommand{\inds}{\ensuremath{N_{I}}\xspace} \newcommand{\ainds}{\ensuremath{\mathrm{Ind}}\xspace} \newcommand{\funct}{\mathit{funct} \ } \newcommand{\KB}{\mathcal{K}\xspace} \newcommand{\dlr}{DL-Lite$_{\mathcal{R}}$\xspace} % Logics \newcommand{\FOL}{\ensuremath{\mathtt{FOL}}\xspace} \newcommand{\datalog}{\ensuremath{\mathtt{Datalog}}\xspace} \newcommand{\dllite}{DL-Lite\xspace} \newcommand{\true}{\mathrm{true}} \newcommand{\false}{\mathrm{false}} \newcommand{\dis}{\mathtt{dis}} \newcommand{\vars}[1]{\ensuremath{\mathrm{vars}(#1)}} %\newcommand{\terms}[1]{\ensuremath{\mathrm{terms}(#1)}} %math \renewcommand{\phi}{\varphi} \newcommand\eqdef{\stackrel{\mathclap{\normalfont\mbox{def}}}{=}} \newcommand\restr[2]{#1_{|#2}} \newcommand{\ontoBody}[1]{\mathrm{body}_\onto(#1)} %proof of the rewriting theorem \newcommand{\rdfGraph}{\graph^{\mappings}_{\extensions}} \newcommand\systemGraph{\graph^{\mappings \cup \mappings^{\text{STD}}_\onto}_{\extensions \cup \extensions_\onto}} \newcommand\viewsGraph{\graph^{\mappings^{\rules,\onto} \cup \mappings^{\text{STD}}_\onto}_{\extensions \cup \extensions_\onto}} \newcommand{\standMappings}{\mappings^{\text{STD}}_\onto} \newcommand{\reminder}[1]{[\vadjust{\vbox to0pt{\vss\hbox to0pt{\hss{\Large $\Longrightarrow$}}}}{{\textsf{\small #1}}}]} %\newcommand{\FG}[1]{\textcolor{blue}{\reminder{FG:~#1}}} \newcommand{\extVersion}{false} \newcommand{\printIfExtVersion}[2] { \ifthenelse{\equal{\extVersion}{true}}{#1}{} \ifthenelse{\equal{\extVersion}{false}}{#2}{} } \newcommand{\bda}{\true} \newcommand{\ifBDA}[2]% {% \ifthenelse{\equal{\bda}{true}}{#1}{}% \ifthenelse{\equal{\bda}{false}}{#2}{}% } %%% Local Variables: %%% TeX-master: "paper" %%% End: $$

Query Answering Test

Test graph

There are 12 initial triples in the graph:

<Maxime> <phoneNumber> "245470000" .
<Maxime> <livesIn> <Orsay> .
<Ioana> <livesIn> <Palaiseau> .
<Ioana> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <Person> .
<François> <livesIn> <Lannion> .
<François> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <Person> .
<Marie-Laure> <livesIn> <Montpellier> .
<Marie-Laure> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <Person> .
<Thing> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <Thing> .
<Person> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <Thing> .
<Place> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <Thing> .
<City> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <Place> .
<livesIn> <http://www.w3.org/2000/01/rdf-schema#range> <City> .
<contact> <http://www.w3.org/2000/01/rdf-schema#domain> <Person> .
<phoneNumber> <http://www.w3.org/2000/01/rdf-schema#subPropertyOf> <contact> .
<contact> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> .
<Place> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> .

qa-test.png

Schema

Overview of the schema

                                                                                         subClassOf
                                                                                       +------------+
                                                                                       v            |
+-------------+  subPropertyOf   +----------+  domain       +--------+  subClassOf   +----------------+
| phoneNumber | ---------------> | contact  | ------------> | Person | ------------> |     Thing      |
+-------------+                  +----------+               +--------+               +----------------+
                                   |                                                   ^
                                   | type                                              |
                                   v                                                   |
+-------------+                  +----------+                                          |
|   livesIn   |                  | Property |                                          |
+-------------+                  +----------+                                          |
  |                                                                                    |
  | range                                                                              |
  v                                                                                    |
+-------------+  subClassOf      +----------+  subClassOf                              |
|    City     | ---------------> |  Place   | -----------------------------------------+
+-------------+                  +----------+
                                   |
                                   | type
                                   v
                                 +----------+
                                 |  Class   |
                                 +----------+

Scenarios

Evaluation

In this scenario, we simply evaluate the query on the graph described above without reasoning.

Tests

/**
 * 1 answer: 
 *   - <> 
 */
@Test
public void shouldAnswerBooleanQuery() throws Exception {
    Set<Tuple<Term>> answers = new HashSet<Tuple<Term>>();
    Tuple t = new Tuple();
    answers.add(t);

    String queryString = "Q<> :- triple(<Maxime>, <livesIn>, <Orsay>) ;";
    assertAnswer(queryString, answers);
}

/**
 * 0 answer: 
 */
@Test
public void shouldAnswerBooleanQueryWithInvalidType() throws Exception {
    Set<Tuple<Term>> answers = new HashSet<Tuple<Term>>();

    String queryString = "Q<> :- triple($s, <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, <Orsay>) ;";
    assertAnswer(queryString, answers);
}

/**
 * 0 answer: 
 */
@Test
public void shouldAnswerBooleanQueryWithVariableAsSubject() throws Exception {
    Set<Tuple<Term>> answers = new HashSet<Tuple<Term>>();
    Tuple t = new Tuple();

    String queryString = "Q<> :- triple($s, <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, <City>) ;";
    assertAnswer(queryString, answers);
}

/**
 * 0 answer
 */
@Test
public void shouldAnswerBooleanQueryWithVariableAsProperty() throws Exception {
    Set<Tuple<Term>> answers = new HashSet<Tuple<Term>>();

    String queryString = "Q<> :- triple(<Maxime>, $p, <Montpellier>) ;";
    assertAnswer(queryString, answers);
}

/**
 * 0 answer: 
 */
@Test
public void shouldAnswerBooleanQueryWithVariableAsObject() throws Exception {
    Set<Tuple<Term>> answers = new HashSet<Tuple<Term>>();

    String queryString = "Q<> :- triple(<Orsay>, <contact>, $o) ;";
    assertAnswer(queryString, answers);
}

/**
 * 1 answer: 
 *   - <Maxime> 
 */
@Test
public void shouldSelectSubject() throws Exception {
    TupleSet answers = new TupleSet();
    Tuple t = new Tuple(new IRI("Maxime"));
    answers.add(t);

    String queryString = "Q<$subject> :- triple($subject, <livesIn>, <Orsay>) ;";
    assertAnswer(queryString, answers);
}

/**
 * 1 answer: 
 *   - <livesIn>
 */
@Test
public void shouldSelectProperty() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("livesIn")));

    String queryString = "Q<$prop> :- triple(<Maxime>, $prop, <Orsay>) ;";
    assertAnswer(queryString, answers);
}

/**
 * 1 answer: 
 *   - <Orsay>
 */
@Test
public void shouldSelectObject() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("Orsay")));

    String queryString = "Q<$object> :- triple(<Maxime>, <livesIn>, $object) ;";
    assertAnswer(queryString, answers);
}

/**
 * 1 answer: 
 *   - "245470000"
 */
@Test
public void shouldSelectLiteralObject() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new Literal("245470000")));

    String queryString = "Q<$object> :- triple(<Maxime>, <phoneNumber>, $object) ;";
    assertAnswer(queryString, answers);
}

/**
 * 1 answer: 
 *   - <Maxime>
 */
@Test
public void shouldSelectSubjectWithExistentialProperty() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("Maxime")));

    String queryString = "Q<$subject> :- triple($subject, $prop, <Orsay>) ;";
    assertAnswer(queryString, answers);
}

/**
 * 1 answer: 
 *   - <Maxime>
 */
@Test
public void shouldSelectSubjectWithExistentialObject() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("Maxime")));

    String queryString = "Q<$subject> :- triple($subject, <phoneNumber>, $object) ;";
    assertAnswer(queryString, answers);
}

/**
 * 1 answer: 
 *   - <phoneNumber>
 */
@Test
public void shouldSelectPropertyWithExistentialSubject() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("phoneNumber")));

    String queryString = "Q<$prop> :- triple($subject, $prop, \"245470000\") ;";
    assertAnswer(queryString, answers);
}

/**
 * 3 answers: 
 *   - <phoneNumber>
 *   - <livesIn>
 *   - <rdf:type>
 */
@Test
public void shouldSelectPropertyWithExistentialObject() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("phoneNumber")));
    answers.add(new Tuple(new IRI("livesIn")));
    answers.add(new Tuple(new IRI("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")));

    String queryString = "Q<$prop> :- triple(<Maxime>, $prop, $object) ;";
    assertAnswer(queryString, answers);
}

/**
 * 4 answers: 
 *   - <Orsay>
 *   - <Palaiseau>
 *   - <Montpellier>
 *   - <Lannion>
 */
@Test
public void shouldSelectObjectWithExistentialSubject() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("Orsay")));
    answers.add(new Tuple(new IRI("Palaiseau")));
    answers.add(new Tuple(new IRI("Montpellier")));
    answers.add(new Tuple(new IRI("Lannion")));

    String queryString = "Q<$object> :- triple($subject, <livesIn>, $object) ;";
    assertAnswer(queryString, answers);
}

/**
 * 2 answers: 
 *   - "245470000"
 *   - <Orsay>
 */
@Test
public void shouldSelectObjectWithExistentialProperty() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new Literal("245470000")));
    answers.add(new Tuple(new IRI("Orsay")));

    String queryString = "Q<$object> :- triple(<Maxime>, $prop, $object) ;";
    assertAnswer(queryString, answers);
}

/**
 * no answer 
 */
@Test
public void shouldSelectSubjectOfType() throws Exception {
    TupleSet answers = new TupleSet();

    String queryString = "Q<$subject> :- triple($subject, <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, <Place>);";
    assertAnswer(queryString, answers);
}

/**
 *  no answer: 
 */
@Test
public void shouldSelectSubjectOfType2() throws Exception {
    TupleSet answers = new TupleSet();

    String queryString = "Q<$subject> :- triple($subject, <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, <Thing>);";
    assertAnswer(queryString, answers);
}

/**
 * 3 answers:
 */
@Test
public void shouldSelectSubjectOfType3() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("Marie-Laure")));
    answers.add(new Tuple(new IRI("Ioana")));
    answers.add(new Tuple(new IRI("François")));

    String queryString = "Q<$subject> :- triple($subject, <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, <Person>);";
    assertAnswer(queryString, answers);
}

/**
 * no answer: 
 */
@Test
public void shouldSelectTypeOfSubject() throws Exception {
    TupleSet answers = new TupleSet();

    String queryString = "Q<$type> :- triple(<Maxime>, <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, $type);";
    assertAnswer(queryString, answers);
}

/**
 * 1 answer: 
 */
@Test
public void shouldSelectTypeOfSubject2() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("Person")));

    String queryString = "Q<$type> :- triple(<Ioana>, <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, $type);";
    assertAnswer(queryString, answers);
}

/**
 * 3 answers: 
 *   - <Person>
 *   - <Class>
 *   - <Property>
 */
@Test
public void shouldSelectAllTypes() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("Person")));
    answers.add(new Tuple(new IRI("http://www.w3.org/2000/01/rdf-schema#Class")));
    answers.add(new Tuple(new IRI("http://www.w3.org/1999/02/22-rdf-syntax-ns#Property")));

    String queryString = "Q<$type> :- triple($subject, <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, $type);";
    assertAnswer(queryString, answers);
}

/**
 * 7 answers: 
 *   - <rdf:type>
 *   - <phoneNumber>
 *   - <livesIn>
 *   - <rdfs:subClassOf>
 *   - <rdfs:subProperty>
 *   - <rdfs:domain>
 *   - <rdfs:range>
 */
@Test
public void shouldSelectAllProperties() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")));
    answers.add(new Tuple(new IRI("phoneNumber")));
    answers.add(new Tuple(new IRI("livesIn")));
    answers.add(new Tuple(new IRI("http://www.w3.org/2000/01/rdf-schema#subClassOf")));
    answers.add(new Tuple(new IRI("http://www.w3.org/2000/01/rdf-schema#subPropertyOf")));
    answers.add(new Tuple(new IRI("http://www.w3.org/2000/01/rdf-schema#domain")));
    answers.add(new Tuple(new IRI("http://www.w3.org/2000/01/rdf-schema#range")));

    String queryString = "Q<$prop> :- triple($subject, $prop, $object);";
    assertAnswer(queryString, answers);
}

/**
 * no answer:
 */
@Test
public void shouldJoin() throws Exception {
    TupleSet answers = new TupleSet();

    String queryString = "Q<$city, $number> :- triple($name, <livesIn>, $city), triple($name, <contact>, $number) ;";
    assertAnswer(queryString, answers);
}

/**
 * 1 answer:
 */
@Test
public void shouldJoin2() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("Orsay"), new Literal("245470000")));

    String queryString = "Q<$city, $number> :- triple($name, <livesIn>, $city), triple($name, <phoneNumber>, $number) ;";
    assertAnswer(queryString, answers);
}

/**
 * 1 answers:
 *   - <Thing>, <subClassOf>
 */
@Test
public void shouldSelectOnVariableEquality() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("Thing"), new IRI("http://www.w3.org/2000/01/rdf-schema#subClassOf")));

    String queryString = "Q<$var, $prop> :- triple($var, $prop, $var);";
    assertAnswer(queryString, answers);
}

/**
 * no answer
 *
 */
@Test
public void shouldDoProduct() throws Exception {
    TupleSet answers = new TupleSet();

    String queryString = "Q<$prop, $city> :- triple(<Ioana>, $prop, $object), triple($city,<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, <City>);";
    assertAnswer(queryString, answers);
}


/**
 * 8 answer
 *
 */
@Test
public void shouldDoProduct2() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), new IRI("Orsay")));
    answers.add(new Tuple(new IRI("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), new IRI("Lannion")));
    answers.add(new Tuple(new IRI("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), new IRI("Palaiseau")));
    answers.add(new Tuple(new IRI("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), new IRI("Montpellier")));
    answers.add(new Tuple(new IRI("livesIn"), new IRI("Orsay")));
    answers.add(new Tuple(new IRI("livesIn"), new IRI("Lannion")));
    answers.add(new Tuple(new IRI("livesIn"), new IRI("Palaiseau")));
    answers.add(new Tuple(new IRI("livesIn"), new IRI("Montpellier")));

    String queryString = "Q<$prop, $city> :- triple(<Ioana>, $prop, $object), triple($name ,<livesIn>, $city);";
    assertAnswer(queryString, answers);
}

Full RDFS Reasoning

Overview

The fully saturated graph looks like (nt file):

qa-test-full-saturation.png

Implementations

It concerns the following settings in query-session:

  • TranslatedUCQuery with FULL_REAS reasoner
  • TranslatedJUCQuery with FULL_REAS reasoner
  • TranslatedSCQuery with FULL_REAS reasoner

Tests

/**
 * 1 answer: 
 *   - <> 
 */
@Test
public void shouldAnswerBooleanQuery() throws Exception {
    Set<Tuple<Term>> answers = new HashSet<Tuple<Term>>();
    Tuple t = new Tuple();
    answers.add(t);

    String queryString = "Q<> :- triple(<Maxime>, <livesIn>, <Orsay>) ;";
    assertAnswer(queryString, answers);
}

/**
 * 0 answer: 
 */
@Test
public void shouldAnswerBooleanQueryWithInvalidType() throws Exception {
    Set<Tuple<Term>> answers = new HashSet<Tuple<Term>>();

    String queryString = "Q<> :- triple($s, <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, <Orsay>) ;";
    assertAnswer(queryString, answers);
}

/**
 * 1 answer: 
 * - <>
 */
@Test
public void shouldAnswerBooleanQueryWithVariableAsSubject() throws Exception {
    Set<Tuple<Term>> answers = new HashSet<Tuple<Term>>();
    Tuple t = new Tuple();
    answers.add(t);

    String queryString = "Q<> :- triple($s, <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, <City>) ;";
    assertAnswer(queryString, answers);
}

/**
 * 0 answer
 */
@Test
public void shouldAnswerBooleanQueryWithVariableAsProperty() throws Exception {
    Set<Tuple<Term>> answers = new HashSet<Tuple<Term>>();

    String queryString = "Q<> :- triple(<Maxime>, $p, <Montpellier>) ;";
    assertAnswer(queryString, answers);
}

/**
 * 0 answer: 
 */
@Test
public void shouldAnswerBooleanQueryWithVariableAsObject() throws Exception {
    Set<Tuple<Term>> answers = new HashSet<Tuple<Term>>();

    String queryString = "Q<> :- triple(<Orsay>, <contact>, $o) ;";
    assertAnswer(queryString, answers);
}

/**
 * 1 answer: 
 *   - <Maxime> 
 */
@Test
public void shouldSelectSubject() throws Exception {
    TupleSet answers = new TupleSet();
    Tuple t = new Tuple(new IRI("Maxime"));
    answers.add(t);

    String queryString = "Q<$subject> :- triple($subject, <livesIn>, <Orsay>) ;";
    assertAnswer(queryString, answers);
}

/**
 * 1 answer: 
 *   - <livesIn>
 */
@Test
public void shouldSelectProperty() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("livesIn")));

    String queryString = "Q<$prop> :- triple(<Maxime>, $prop, <Orsay>) ;";
    assertAnswer(queryString, answers);
}

/**
 * 1 answer: 
 *   - <Orsay>
 */
@Test
public void shouldSelectObject() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("Orsay")));

    String queryString = "Q<$object> :- triple(<Maxime>, <livesIn>, $object) ;";
    assertAnswer(queryString, answers);
}

/**
 * 1 answer: 
 *   - "245470000"
 */
@Test
public void shouldSelectLiteralObject() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new Literal("245470000")));

    String queryString = "Q<$object> :- triple(<Maxime>, <phoneNumber>, $object) ;";
    assertAnswer(queryString, answers);
}

/**
 * 1 answer: 
 *   - <Maxime>
 */
@Test
public void shouldSelectSubjectWithExistentialProperty() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("Maxime")));

    String queryString = "Q<$subject> :- triple($subject, $prop, <Orsay>) ;";
    assertAnswer(queryString, answers);
}

/**
 * 1 answer: 
 *   - <Maxime>
 */
@Test
public void shouldSelectSubjectWithExistentialObject() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("Maxime")));

    String queryString = "Q<$subject> :- triple($subject, <phoneNumber>, $object) ;";
    assertAnswer(queryString, answers);
}

/**
 * 2 answers: 
 *   - <contact>
 *   - <phoneNumber>
 */
@Test
public void shouldSelectPropertyWithExistentialSubject() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("contact")));
    answers.add(new Tuple(new IRI("phoneNumber")));

    String queryString = "Q<$prop> :- triple($subject, $prop, \"245470000\") ;";
    assertAnswer(queryString, answers);
}

/**
 * 4 answers: 
 *   - <contact>
 *   - <phoneNumber>
 *   - <livesIn>
 *   - <rdf:type>
 */
@Test
public void shouldSelectPropertyWithExistentialObject() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("contact")));
    answers.add(new Tuple(new IRI("phoneNumber")));
    answers.add(new Tuple(new IRI("livesIn")));
    answers.add(new Tuple(new IRI("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")));

    String queryString = "Q<$prop> :- triple(<Maxime>, $prop, $object) ;";
    assertAnswer(queryString, answers);
}

/**
 * 4 answers: 
 *   - <Orsay>
 *   - <Palaiseau>
 *   - <Montpellier>
 *   - <Lannion>
 */
@Test
public void shouldSelectObjectWithExistentialSubject() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("Orsay")));
    answers.add(new Tuple(new IRI("Palaiseau")));
    answers.add(new Tuple(new IRI("Montpellier")));
    answers.add(new Tuple(new IRI("Lannion")));

    String queryString = "Q<$object> :- triple($subject, <livesIn>, $object) ;";
    assertAnswer(queryString, answers);
}

/**
 * 4 answers: 
 *   - <Thing>
 *   - <Person>
 *   - "245470000"
 *   - <Orsay>
 */
@Test
public void shouldSelectObjectWithExistentialProperty() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("Thing")));
    answers.add(new Tuple(new IRI("Person")));
    answers.add(new Tuple(new Literal("245470000")));
    answers.add(new Tuple(new IRI("Orsay")));

    String queryString = "Q<$object> :- triple(<Maxime>, $prop, $object) ;";
    assertAnswer(queryString, answers);
}

/**
 * 4 answers: 
 *   - <Orsay>
 *   - <Palaiseau>
 *   - <Montpellier>
 *   - <Lannion>
 */
@Test
public void shouldSelectSubjectOfType() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("Orsay")));
    answers.add(new Tuple(new IRI("Palaiseau")));
    answers.add(new Tuple(new IRI("Montpellier")));
    answers.add(new Tuple(new IRI("Lannion")));

    String queryString = "Q<$subject> :- triple($subject, <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, <Place>);";
    assertAnswer(queryString, answers);
}

/**
 *  8 answers: 
 *   - <Orsay>
 *   - <Palaiseau>
 *   - <Montpellier>
 *   - <Lannion>
 *   - <Maxime>
 *   - <Marie-Laure>
 *   - <Ioana>
 *   - <François>
 */
@Test
public void shouldSelectSubjectOfType2() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("Orsay")));
    answers.add(new Tuple(new IRI("Palaiseau")));
    answers.add(new Tuple(new IRI("Montpellier")));
    answers.add(new Tuple(new IRI("Lannion")));
    answers.add(new Tuple(new IRI("Maxime")));
    answers.add(new Tuple(new IRI("Marie-Laure")));
    answers.add(new Tuple(new IRI("Ioana")));
    answers.add(new Tuple(new IRI("François")));

    String queryString = "Q<$subject> :- triple($subject, <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, <Thing>);";
    assertAnswer(queryString, answers);
}

/**
 * 2 answers: 
 *   - <Person>
 *   - <Thing>
 */
@Test
public void shouldSelectTypeOfSubject() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("Person")));
    answers.add(new Tuple(new IRI("Thing")));

    String queryString = "Q<$type> :- triple(<Maxime>, <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, $type);";
    assertAnswer(queryString, answers);
}

/**
 * 6 answers: 
 *   - <Person>
 *   - <Thing>
 *   - <Place>
 *   - <City>
 *   - <Class>
 *   - <Property>
 */
@Test
public void shouldSelectAllTypes() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("Person")));
    answers.add(new Tuple(new IRI("Thing")));
    answers.add(new Tuple(new IRI("Place")));
    answers.add(new Tuple(new IRI("City")));
    answers.add(new Tuple(new IRI("http://www.w3.org/2000/01/rdf-schema#Class")));
    answers.add(new Tuple(new IRI("http://www.w3.org/1999/02/22-rdf-syntax-ns#Property")));

    String queryString = "Q<$type> :- triple($subject, <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, $type);";
    assertAnswer(queryString, answers);
}

/**
 * 8 answers: 
 *   - <rdf:type>
 *   - <phoneNumber>
 *   - <contact>
 *   - <livesIn>
 *   - <rdfs:subClassOf>
 *   - <rdfs:subProperty>
 *   - <rdfs:domain>
 *   - <rdfs:range>
 */
@Test
public void shouldSelectAllProperties() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")));
    answers.add(new Tuple(new IRI("phoneNumber")));
    answers.add(new Tuple(new IRI("contact")));
    answers.add(new Tuple(new IRI("livesIn")));
    answers.add(new Tuple(new IRI("http://www.w3.org/2000/01/rdf-schema#subClassOf")));
    answers.add(new Tuple(new IRI("http://www.w3.org/2000/01/rdf-schema#subPropertyOf")));
    answers.add(new Tuple(new IRI("http://www.w3.org/2000/01/rdf-schema#domain")));
    answers.add(new Tuple(new IRI("http://www.w3.org/2000/01/rdf-schema#range")));

    String queryString = "Q<$prop> :- triple($subject, $prop, $object);";
    assertAnswer(queryString, answers);
}

/**
 * 33 answers
 * We found 39 triples, because of this issue https://gitlab.inria.fr/cedar/reasoning/issues/2,
 * the 6 added triples are the following: 
 * - | <phoneNumber> | <http://www.w3.org/2000/01/rdf-schema#subPropertyOf> | <phoneNumber> |,
 * - | <City> | <http://www.w3.org/2000/01/rdf-schema#subClassOf> | <City> |,
 * - | <Person> | <http://www.w3.org/2000/01/rdf-schema#subClassOf> | <Person> |,
 * - | <Place> | <http://www.w3.org/2000/01/rdf-schema#subClassOf> | <Place> |,
 * - | <contact> | <http://www.w3.org/2000/01/rdf-schema#subPropertyOf> | <contact> |,
 * - | <livesIn> | <http://www.w3.org/2000/01/rdf-schema#subPropertyOf> | <livesIn> |,
 * 
 */
// @Test
// public void shouldSelectEveryTriple() throws Exception {
//     String queryString = "Q<$subject, $prop, $object> :- triple($subject, $prop, $object);";
//     assertAnswerNumber(queryString, 33);
// }

/**
 * 1 answers:
 *   - <Orsay>, "245470000"
 */
@Test
public void shouldJoin() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("Orsay"), new Literal("245470000")));

    String queryString = "Q<$city, $number> :- triple($name, <livesIn>, $city), triple($name, <contact>, $number) ;";
    assertAnswer(queryString, answers);
}

/**
 * 1 answers:
 *   - <Thing>, <subClassOf>
 */
@Test
public void shouldSelectOnVariableEquality() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("Thing"), new IRI("http://www.w3.org/2000/01/rdf-schema#subClassOf")));

    String queryString = "Q<$var, $prop> :- triple($var, $prop, $var);";
    assertAnswer(queryString, answers);
}

/**
 * 8 answers
 *
 */
@Test
public void shouldDoProduct() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), new IRI("Orsay")));
    answers.add(new Tuple(new IRI("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), new IRI("Lannion")));
    answers.add(new Tuple(new IRI("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), new IRI("Palaiseau")));
    answers.add(new Tuple(new IRI("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), new IRI("Montpellier")));
    answers.add(new Tuple(new IRI("livesIn"), new IRI("Orsay")));
    answers.add(new Tuple(new IRI("livesIn"), new IRI("Lannion")));
    answers.add(new Tuple(new IRI("livesIn"), new IRI("Palaiseau")));
    answers.add(new Tuple(new IRI("livesIn"), new IRI("Montpellier")));

    String queryString = "Q<$prop, $city> :- triple(<Ioana>, $prop, $object), triple($city,<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, <City>);";
    assertAnswer(queryString, answers);
}

@Test
public void shouldFindAllSubPropertyOf() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("phoneNumber"), new IRI("contact")));

    String queryString = "Q<$X, $Y> :- triple($X, <http://www.w3.org/2000/01/rdf-schema#subPropertyOf>, $Y);";

    assertAnswer(queryString, answers);
}

@Test
public void shouldFindAllSubClassOf() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("Person"), new IRI("Thing")));
    answers.add(new Tuple(new IRI("Thing"), new IRI("Thing")));
    answers.add(new Tuple(new IRI("City"), new IRI("Thing")));
    answers.add(new Tuple(new IRI("City"), new IRI("Place")));
    answers.add(new Tuple(new IRI("Place"), new IRI("Thing")));
    String queryString = "Q<$X, $Y> :- triple($X, <http://www.w3.org/2000/01/rdf-schema#subClassOf>, $Y);";

    assertAnswer(queryString, answers);
}

@Test
public void shouldFindAllDomain() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("phoneNumber"), new IRI("Thing")));
    answers.add(new Tuple(new IRI("phoneNumber"), new IRI("Person")));
    answers.add(new Tuple(new IRI("contact"), new IRI("Thing")));
    answers.add(new Tuple(new IRI("contact"), new IRI("Person")));
    String queryString = "Q<$X, $Y> :- triple($X, <http://www.w3.org/2000/01/rdf-schema#domain>, $Y);";

    assertAnswer(queryString, answers);
}

@Test
public void shouldFindAllRange() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("livesIn"), new IRI("City")));
    answers.add(new Tuple(new IRI("livesIn"), new IRI("Place")));
    answers.add(new Tuple(new IRI("livesIn"), new IRI("Thing")));
    String queryString = "Q<$X, $Y> :- triple($X, <http://www.w3.org/2000/01/rdf-schema#range>, $Y);";

    assertAnswer(queryString, answers);
}

@Test
public void shouldFindAnswersOfQueryWithEmptyBody() throws Exception {
    TupleSet answers = new TupleSet();
    answers.add(new Tuple(new IRI("test")));

    String queryString = "Q<<test>> :- ;";

    assertAnswer(queryString, answers);
}