aboutsummaryrefslogtreecommitdiff
path: root/src/uk/ac/ox/cs/pagoda/rules/approximators
diff options
context:
space:
mode:
authorRncLsn <rnc.lsn@gmail.com>2015-05-13 11:57:06 +0100
committerRncLsn <rnc.lsn@gmail.com>2015-05-13 11:57:06 +0100
commit7e0ecc07285209e65f9d4d022065d06a4997fc86 (patch)
tree3c3faa6684e49444c7078903d2e5762fc44bb3a6 /src/uk/ac/ox/cs/pagoda/rules/approximators
parent0c2726db44b562cbda9bfa87e76d829927c31ec8 (diff)
downloadACQuA-7e0ecc07285209e65f9d4d022065d06a4997fc86.tar.gz
ACQuA-7e0ecc07285209e65f9d4d022065d06a4997fc86.zip
Implementing Limited Skolemisation, in particular SkolemTermsDispenser.
Diffstat (limited to 'src/uk/ac/ox/cs/pagoda/rules/approximators')
-rw-r--r--src/uk/ac/ox/cs/pagoda/rules/approximators/Approximator.java42
-rw-r--r--src/uk/ac/ox/cs/pagoda/rules/approximators/LimitedSkolemisationApproximator.java74
-rw-r--r--src/uk/ac/ox/cs/pagoda/rules/approximators/OverApproxBoth.java24
-rw-r--r--src/uk/ac/ox/cs/pagoda/rules/approximators/OverApproxDisj.java100
-rw-r--r--src/uk/ac/ox/cs/pagoda/rules/approximators/OverApproxExist.java265
-rw-r--r--src/uk/ac/ox/cs/pagoda/rules/approximators/SkolemTermsDispenser.java74
-rw-r--r--src/uk/ac/ox/cs/pagoda/rules/approximators/TupleDependentApproximator.java16
7 files changed, 595 insertions, 0 deletions
diff --git a/src/uk/ac/ox/cs/pagoda/rules/approximators/Approximator.java b/src/uk/ac/ox/cs/pagoda/rules/approximators/Approximator.java
new file mode 100644
index 0000000..f910c64
--- /dev/null
+++ b/src/uk/ac/ox/cs/pagoda/rules/approximators/Approximator.java
@@ -0,0 +1,42 @@
1package uk.ac.ox.cs.pagoda.rules.approximators;
2
3import org.semanticweb.HermiT.model.DLClause;
4
5import java.util.Collection;
6
7public interface Approximator {
8
9 Collection<DLClause> convert(DLClause clause, DLClause originalClause);
10
11}
12
13// TODO remove
14//class IgnoreExist implements Approximator {
15//
16// @Override
17// public Collection<DLClause> convert(DLClause clause, DLClause originalClause) {
18// Collection<DLClause> ret = new LinkedList<DLClause>();
19// DLPredicate p;
20// for (Atom headAtom: clause.getHeadAtoms()) {
21// p = headAtom.getDLPredicate();
22// if (p instanceof AtLeast) return ret;
23// }
24//
25// ret.add(clause);
26// return ret;
27// }
28//
29//}
30//
31//
32//
33//class IgnoreDisj implements Approximator {
34//
35// @Override
36// public Collection<DLClause> convert(DLClause clause, DLClause originalClause) {
37// Collection<DLClause> ret = new LinkedList<DLClause>();
38// if (clause.getHeadLength() > 1) return ret;
39// ret.add(clause);
40// return ret;
41// }
42//}
diff --git a/src/uk/ac/ox/cs/pagoda/rules/approximators/LimitedSkolemisationApproximator.java b/src/uk/ac/ox/cs/pagoda/rules/approximators/LimitedSkolemisationApproximator.java
new file mode 100644
index 0000000..8fc6b77
--- /dev/null
+++ b/src/uk/ac/ox/cs/pagoda/rules/approximators/LimitedSkolemisationApproximator.java
@@ -0,0 +1,74 @@
1package uk.ac.ox.cs.pagoda.rules.approximators;
2
3import org.semanticweb.HermiT.model.DLClause;
4import uk.ac.ox.cs.pagoda.multistage.AnswerTupleID;
5import uk.ac.ox.cs.pagoda.rules.ExistConstantApproximator;
6
7import java.util.*;
8
9/**
10 * Approximates existential rules by a limited form of Skolemisation.
11 * <p>
12 * Given a rule and a grounding substitution,
13 * it Skolemises the rule if
14 * all the terms in the substitution have depth less than a given depth,
15 * otherwise it approximates using an alternative <tt>TupleDependentApproximator</tt>.
16 *
17 * */
18public class LimitedSkolemisationApproximator implements TupleDependentApproximator {
19
20 private final int maxTermDepth;
21 private final TupleDependentApproximator alternativeApproximator;
22
23 private Map<AnswerTupleID, Integer> mapIndividualsToDepth;
24
25 public LimitedSkolemisationApproximator(int maxTermDepth) {
26 this(maxTermDepth, new ExistConstantApproximator());
27 }
28
29 public LimitedSkolemisationApproximator(int maxTermDepth, TupleDependentApproximator alternativeApproximator) {
30 this.maxTermDepth = maxTermDepth;
31 this.alternativeApproximator = alternativeApproximator;
32 this.mapIndividualsToDepth = new HashMap<>();
33 }
34
35 @Override
36 public Collection<DLClause> convert(DLClause clause, DLClause originalClause, Collection<AnswerTupleID> violationTuples) {
37 switch (clause.getHeadLength()) {
38 case 1:
39 return overApprox(clause, originalClause, violationTuples);
40 case 0:
41 return Arrays.asList(clause);
42 default:
43 ArrayList<DLClause> result = new ArrayList<>();
44 // TODO implement
45 return result;
46 }
47
48
49 }
50
51 private Collection<DLClause> overApprox(DLClause clause, DLClause originalClause, Collection<AnswerTupleID> violationTuples) {
52 ArrayList<DLClause> result = new ArrayList<>();
53
54 for (AnswerTupleID violationTuple : violationTuples)
55 if (getDepth(violationTuple) > maxTermDepth)
56 result.addAll(alternativeApproximator.convert(clause, originalClause, null));
57 else
58 result.add(getInstantiatedSkolemisation(clause, originalClause, violationTuple));
59
60 return result;
61 }
62
63
64 private DLClause getInstantiatedSkolemisation(DLClause clause, DLClause originalClause, AnswerTupleID violationTuple) {
65 // TODO implement
66 // filter the violation tuples appearing on both the sides of the rule
67 return null;
68 }
69
70 private int getDepth(AnswerTupleID violationTuple) {
71 if (!mapIndividualsToDepth.containsKey(violationTuple)) return 0;
72 return mapIndividualsToDepth.get(violationTuple);
73 }
74}
diff --git a/src/uk/ac/ox/cs/pagoda/rules/approximators/OverApproxBoth.java b/src/uk/ac/ox/cs/pagoda/rules/approximators/OverApproxBoth.java
new file mode 100644
index 0000000..ae2a2cf
--- /dev/null
+++ b/src/uk/ac/ox/cs/pagoda/rules/approximators/OverApproxBoth.java
@@ -0,0 +1,24 @@
1package uk.ac.ox.cs.pagoda.rules.approximators;
2
3import org.semanticweb.HermiT.model.AtLeastDataRange;
4import org.semanticweb.HermiT.model.DLClause;
5
6import java.util.Collection;
7import java.util.LinkedList;
8
9public class OverApproxBoth implements Approximator {
10
11 Approximator approxDist = new OverApproxDisj(), approxExist = new OverApproxExist();
12
13 @Override
14 public Collection<DLClause> convert(DLClause clause, DLClause originalClause) {
15 Collection<DLClause> ret = new LinkedList<DLClause>();
16 for (DLClause tClause: approxDist.convert(clause, originalClause)) {
17 if (tClause.getHeadLength() > 0 && tClause.getHeadAtom(0).getDLPredicate() instanceof AtLeastDataRange)
18 continue;
19 ret.addAll(approxExist.convert(tClause, originalClause));
20 }
21 return ret;
22 }
23
24}
diff --git a/src/uk/ac/ox/cs/pagoda/rules/approximators/OverApproxDisj.java b/src/uk/ac/ox/cs/pagoda/rules/approximators/OverApproxDisj.java
new file mode 100644
index 0000000..05d9442
--- /dev/null
+++ b/src/uk/ac/ox/cs/pagoda/rules/approximators/OverApproxDisj.java
@@ -0,0 +1,100 @@
1package uk.ac.ox.cs.pagoda.rules.approximators;
2
3import org.semanticweb.HermiT.model.*;
4import uk.ac.ox.cs.pagoda.hermit.DLClauseHelper;
5
6import java.util.*;
7
8public class OverApproxDisj implements Approximator {
9
10 /**
11 * Splits a disjunctive rule into a bunch of rules.
12 * <p>
13 * It returns a collection containing a rule for each atom in the head of the input rule.
14 * Each rule has the same body of the input rule,
15 * and the relative head atom as head.
16 * */
17 @Override
18 public Collection<DLClause> convert(DLClause clause, DLClause originalClause) {
19 LinkedList<DLClause> distincts = new LinkedList<DLClause>();
20 Atom[] headAtoms = clause.getHeadAtoms(), bodyAtoms = clause.getBodyAtoms();
21 LinkedList<DLClause> newClauses = new LinkedList<DLClause>();
22 DLClause newClause;
23 if (headAtoms.length > 1) {
24 for (Atom headAtom: headAtoms) {
25 newClause = DLClause.create(new Atom[] {headAtom}, bodyAtoms);
26 newClauses.add(newClause);
27// distincts.add(newClause);
28 }
29
30 for (DLClause cls: newClauses) {
31 newClause = DLClauseHelper.simplified(cls);
32 if (!isSubsumedBy(newClause, distincts))
33 distincts.add(newClause);
34 }
35 }
36 else distincts.add(clause);
37
38 return distincts;
39 }
40
41 public static boolean isSubsumedBy(DLClause newClause, Collection<DLClause> distinctClauses) {
42 Map<Variable, Term> unifier;
43 Set<Atom> bodyAtoms = new HashSet<Atom>();
44 for (DLClause clause: distinctClauses) {
45 if (newClause.getHeadLength() > 0 && clause.getHeadLength() > 0 &&
46 (unifier = isSubsumedBy(newClause.getHeadAtom(0), clause.getHeadAtom(0))) == null)
47 continue;
48 else
49 unifier = new HashMap<Variable, Term>();
50
51 for (Atom atom: clause.getBodyAtoms())
52 bodyAtoms.add(rename(atom, unifier));
53 unifier.clear();
54
55 for (Atom atom: newClause.getBodyAtoms())
56 if (!bodyAtoms.contains(atom))
57 continue;
58
59 return true;
60 }
61
62 return false;
63 }
64
65 public static Map<Variable, Term> isSubsumedBy(Atom atom1, Atom atom2) {
66 DLPredicate predicate = atom1.getDLPredicate();
67 if (!predicate.equals(atom2.getDLPredicate()))
68 return null;
69
70 Map<Variable, Term> unifier = new HashMap<Variable, Term>();
71 Term term1, term2;
72 for (int index = 0; index < predicate.getArity(); ++index) {
73 term1 = rename(atom1.getArgument(index), unifier);
74 term2 = rename(atom2.getArgument(index), unifier);
75
76 if (term1.equals(term2));
77 else if (term1 instanceof Variable)
78 unifier.put((Variable) term1, term2);
79 else
80 return null;
81 }
82 return unifier;
83 }
84
85 public static Atom rename(Atom atom, Map<Variable, Term> unifier) {
86 Term[] arguments = new Term[atom.getArity()];
87 for (int i = 0; i < atom.getArity(); ++i)
88 arguments[i] = rename(atom.getArgument(i), unifier);
89 return Atom.create(atom.getDLPredicate(), arguments);
90 }
91
92 public static Term rename(Term argument, Map<Variable, Term> unifier) {
93 Term newArg;
94 while ((newArg = unifier.get(argument)) != null)
95 return newArg;
96 return argument;
97 }
98
99
100}
diff --git a/src/uk/ac/ox/cs/pagoda/rules/approximators/OverApproxExist.java b/src/uk/ac/ox/cs/pagoda/rules/approximators/OverApproxExist.java
new file mode 100644
index 0000000..e0bafe0
--- /dev/null
+++ b/src/uk/ac/ox/cs/pagoda/rules/approximators/OverApproxExist.java
@@ -0,0 +1,265 @@
1package uk.ac.ox.cs.pagoda.rules.approximators;
2
3import org.semanticweb.HermiT.model.*;
4import uk.ac.ox.cs.pagoda.hermit.DLClauseHelper;
5import uk.ac.ox.cs.pagoda.util.Namespace;
6
7import java.util.*;
8
9public class OverApproxExist implements Approximator {
10
11 public static final String negativeSuffix = "_neg";
12 public static final String skolemisedIndividualPrefix = Namespace.PAGODA_ANONY + "individual";
13 private static final Variable X = Variable.create("X");
14 //DEBUG
15 public static Collection<String> createdIndividualIRIs = new HashSet<>();
16 private static int individualCounter = 0;
17 private static Map<DLClause, Integer> individualNumber = new HashMap<DLClause, Integer>();
18
19 private static int noOfExistential(DLClause originalClause) {
20 int no = 0;
21 for (Atom atom: originalClause.getHeadAtoms())
22 if (atom.getDLPredicate() instanceof AtLeast)
23 no += ((AtLeast) atom.getDLPredicate()).getNumber();
24 return no;
25 }
26
27 private static int indexOfExistential(Atom headAtom, DLClause originalClause) {
28 if (!(headAtom.getDLPredicate() instanceof AtLeast)) return -1;
29 AtLeastConcept alc = (AtLeastConcept) headAtom.getDLPredicate();
30 if (alc.getToConcept() instanceof AtomicConcept) {
31 AtomicConcept ac = (AtomicConcept) alc.getToConcept();
32 if (ac.getIRI().endsWith(negativeSuffix)) {
33 alc = AtLeastConcept.create(alc.getNumber(), alc.getOnRole(), AtomicNegationConcept.create(getNegationConcept(ac)));
34 headAtom = Atom.create(alc, headAtom.getArgument(0));
35 }
36 }
37
38 int index = 0;
39 for (Atom atom: originalClause.getHeadAtoms()) {
40 if (atom.equals(headAtom))
41 return index;
42 if (atom.getDLPredicate() instanceof AtLeast)
43 index += ((AtLeast) atom.getDLPredicate()).getNumber();
44 }
45 return -1;
46 }
47
48 public static AtomicConcept getNegationConcept(DLPredicate p) {
49 if (p.equals(AtomicConcept.THING)) return AtomicConcept.NOTHING;
50 if (p.equals(AtomicConcept.NOTHING)) return AtomicConcept.THING;
51
52 if (p instanceof AtomicConcept) {
53 String iri = ((AtomicConcept) p).getIRI();
54 if (iri.endsWith(negativeSuffix))
55 iri = iri.substring(0, iri.length() - 4);
56 else
57 iri += negativeSuffix;
58
59 return AtomicConcept.create(iri);
60 }
61 if (p instanceof AtLeastConcept) {
62 // FIXME !!! here
63 return null;
64 }
65 return null;
66 }
67
68 public static int getNumberOfSkolemisedIndividual() {
69 return individualCounter;
70 }
71 //DEBUG
72
73 public static Individual getNewIndividual(DLClause originalClause, int offset) {
74 Individual ret;
75 int individualID;
76 if (individualNumber.containsKey(originalClause)) {
77 individualID = individualNumber.get(originalClause) + offset;
78 ret = Individual.create(skolemisedIndividualPrefix + individualID);
79 }
80 else {
81 individualNumber.put(originalClause, individualCounter);
82 individualID = individualCounter + offset;
83 ret = Individual.create(skolemisedIndividualPrefix + individualID);
84 individualCounter += noOfExistential(originalClause);
85 }
86 return ret;
87 }
88
89 public static int indexOfSkolemisedIndividual(Atom atom) {
90 Term t;
91 for (int index = 0; index < atom.getArity(); ++index) {
92 t = atom.getArgument(index);
93 if (t instanceof Individual && ((Individual) t).getIRI().contains(skolemisedIndividualPrefix)) return index;
94 }
95 return -1;
96 }
97
98 @Override
99 public Collection<DLClause> convert(DLClause clause, DLClause originalClause) {
100 Collection<DLClause> ret;
101 switch (clause.getHeadLength()) {
102 case 1:
103 return overApprox(clause.getHeadAtom(0), clause.getBodyAtoms(), originalClause);
104 case 0:
105 ret = new LinkedList<DLClause>();
106 ret.add(clause);
107 return ret;
108 default:
109 ret = new LinkedList<DLClause>();
110 for (Iterator<DLClause> iter = new DisjunctiveHeads(clause, originalClause); iter.hasNext(); )
111 ret.add(iter.next());
112 return ret;
113 }
114 }
115
116 public Collection<DLClause> overApprox(Atom headAtom, Atom[] bodyAtoms, DLClause originalClause) {
117 return overApprox(headAtom, bodyAtoms, originalClause, indexOfExistential(headAtom, originalClause));
118 }
119
120 public Collection<DLClause> overApprox(Atom headAtom, Atom[] bodyAtoms, DLClause originalClause, int offset) {
121 Collection<DLClause> ret = new LinkedList<DLClause>();
122 DLPredicate predicate = headAtom.getDLPredicate();
123 if (predicate instanceof AtLeastConcept) {
124 AtLeastConcept atLeastConcept = (AtLeastConcept) predicate;
125 LiteralConcept concept = atLeastConcept.getToConcept();
126 Role role = atLeastConcept.getOnRole();
127 AtomicConcept atomicConcept = null;
128
129 if (concept instanceof AtomicNegationConcept) {
130 // TODO CHECK: is this already in MultiStageUpperProgram?
131 Atom atom1 = Atom.create(atomicConcept = ((AtomicNegationConcept) concept).getNegatedAtomicConcept(), X);
132 Atom atom2 = Atom.create(atomicConcept = getNegationConcept(atomicConcept), X);
133 ret.add(DLClause.create(new Atom[0], new Atom[] {atom1, atom2}));
134 }
135 else {
136 atomicConcept = (AtomicConcept) concept;
137 if (atomicConcept.equals(AtomicConcept.THING))
138 atomicConcept = null;
139 }
140
141 int card = atLeastConcept.getNumber();
142 Individual[] individuals = new Individual[card];
143 for (int i = 0; i < card; ++i) individuals[i] = getNewIndividual(originalClause, offset + i);
144
145 for (int i = 0; i < card; ++i) {
146 if (atomicConcept != null)
147 ret.add(DLClause.create(new Atom[] {Atom.create(atomicConcept, individuals[i])}, bodyAtoms));
148
149 Atom atom = role instanceof AtomicRole ?
150 Atom.create((AtomicRole) role, X, individuals[i]) :
151 Atom.create(((InverseRole) role).getInverseOf(), individuals[i], X);
152
153 ret.add(DLClause.create(new Atom[] {atom}, bodyAtoms));
154 }
155
156 for (int i = 0; i < card; ++i)
157 for (int j = i + 1; j < card; ++j)
158 // TODO to be checked ... different as
159 ret.add(DLClause.create(new Atom[] {Atom.create(Inequality.INSTANCE, individuals[i], individuals[j])}, bodyAtoms));
160 //DLClauseHelper.contructor_differentAs(individuals[i], individuals[j]));
161
162 }
163 else if (predicate instanceof AtLeastDataRange) {
164 // TODO to be implemented ...
165 }
166 else
167 ret.add(DLClause.create(new Atom[] {headAtom}, bodyAtoms));
168
169 return ret;
170 }
171
172 class DisjunctiveHeads implements Iterator<DLClause> {
173
174 Atom[] bodyAtoms;
175 Atom[][] disjunctHeadAtoms;
176 int[] pointer;
177 int length, l;
178 LinkedList<DLClause> auxiliaryClauses = new LinkedList<DLClause>();
179
180 public DisjunctiveHeads(DLClause clause, DLClause originalClause) {
181 length = clause.getHeadLength();
182
183 bodyAtoms = clause.getBodyAtoms();
184 disjunctHeadAtoms = new Atom[length][];
185 pointer = new int[length];
186 if (length > 0) l = length - 1;
187 else length = 0;
188
189 int index = 0, offset = 0;
190 Collection<DLClause> datalogRules;
191 DLClause newClause;
192 for (Atom headAtom: clause.getHeadAtoms()) {
193 pointer[index] = 0;
194
195 datalogRules = overApprox(headAtom, bodyAtoms, originalClause, offset);
196
197 if (datalogRules.isEmpty()) {
198 l = -1;
199 auxiliaryClauses.clear();
200 return ;
201 }
202
203 for (Iterator<DLClause> iter = datalogRules.iterator(); iter.hasNext(); ) {
204 newClause = iter.next();
205 if (!DLClauseHelper.hasSubsetBodyAtoms(newClause, clause)) {
206 auxiliaryClauses.add(newClause);
207 iter.remove();
208 }
209 }
210
211 disjunctHeadAtoms[index] = new Atom[datalogRules.size()];
212
213 int j = 0;
214 for (DLClause disjunct: datalogRules) {
215 disjunctHeadAtoms[index][j++] = disjunct.getHeadAtom(0);
216 }
217
218 ++index;
219 if (headAtom.getDLPredicate() instanceof AtLeast)
220 offset += ((AtLeast) headAtom.getDLPredicate()).getNumber();
221
222 }
223
224 }
225
226 @Override
227 public boolean hasNext() {
228 return l != -1 || !auxiliaryClauses.isEmpty();
229 }
230
231 @Override
232 public DLClause next() {
233 if (l == -1)
234 return auxiliaryClauses.removeFirst();
235
236 if (length > 0) {
237 Atom[] headAtoms = new Atom[length];
238 for (int i = 0; i < length; ++i)
239 headAtoms[i] = disjunctHeadAtoms[i][pointer[i]];
240
241 ++pointer[l];
242 while (l >= 0 && pointer[l] >= disjunctHeadAtoms[l].length) {
243 pointer[l] = 0;
244 --l;
245 if (l >= 0)
246 ++pointer[l];
247 }
248
249 if (l >= 0) l = length - 1;
250
251 return DLClauseHelper.simplified(DLClause.create(headAtoms, bodyAtoms));
252// return DLClause.create(headAtoms, bodyAtoms);
253 }
254 else {
255 --l;
256 return DLClauseHelper.simplified(DLClause.create(new Atom[0], bodyAtoms));
257// return DLClause.create(new Atom[0], bodyAtoms);
258 }
259 }
260
261 @Override
262 public void remove() { }
263
264 }
265}
diff --git a/src/uk/ac/ox/cs/pagoda/rules/approximators/SkolemTermsDispenser.java b/src/uk/ac/ox/cs/pagoda/rules/approximators/SkolemTermsDispenser.java
new file mode 100644
index 0000000..a920ec5
--- /dev/null
+++ b/src/uk/ac/ox/cs/pagoda/rules/approximators/SkolemTermsDispenser.java
@@ -0,0 +1,74 @@
1package uk.ac.ox.cs.pagoda.rules.approximators;
2
3import org.semanticweb.HermiT.model.AtLeast;
4import org.semanticweb.HermiT.model.Atom;
5import org.semanticweb.HermiT.model.DLClause;
6import org.semanticweb.HermiT.model.Individual;
7import uk.ac.ox.cs.pagoda.multistage.AnswerTupleID;
8import uk.ac.ox.cs.pagoda.util.Namespace;
9
10import java.util.HashMap;
11import java.util.Map;
12
13/**
14 * If you need a Skolem term (i.e. fresh individual), ask this class.
15 */
16public class SkolemTermsDispenser {
17
18 public static final String skolemisedIndividualPrefix = Namespace.PAGODA_ANONY + "individual";
19 private static SkolemTermsDispenser skolemTermsDispenser;
20 private int individualCounter = 0;
21 private Map<DLClause, Integer> termNumber = new HashMap<>();
22 private Map<SkolemTermId, Integer> mapTermToDepth = new HashMap<>();
23 private int dependenciesCounter = 0;
24 private Map<AnswerTupleID, Integer> mapDependencyToId = new HashMap<>();
25
26 private SkolemTermsDispenser() {
27 }
28
29 public static SkolemTermsDispenser getInstance() {
30 if (skolemTermsDispenser == null) skolemTermsDispenser = new SkolemTermsDispenser();
31 return skolemTermsDispenser;
32 }
33
34 private int getDependencyId(AnswerTupleID answerTupleID) {
35 if (mapDependencyToId.containsKey(answerTupleID)) return mapDependencyToId.get(answerTupleID);
36 else return mapDependencyToId.put(answerTupleID, dependenciesCounter++);
37 }
38
39 public Individual getNewIndividual(DLClause originalClause, int offset, AnswerTupleID dependency) {
40 if (!termNumber.containsKey(originalClause)) {
41 termNumber.put(originalClause, individualCounter);
42 individualCounter += noOfExistential(originalClause);
43 }
44 if (!mapDependencyToId.containsKey(dependency)) {
45 mapDependencyToId.put(dependency, dependenciesCounter++);
46 }
47
48 SkolemTermId termId = new SkolemTermId(termNumber.get(originalClause) + offset, getDependencyId(dependency));
49 return Individual.create(skolemisedIndividualPrefix + termId);
50 }
51
52 private int noOfExistential(DLClause originalClause) {
53 int no = 0;
54 for (Atom atom : originalClause.getHeadAtoms())
55 if (atom.getDLPredicate() instanceof AtLeast)
56 no += ((AtLeast) atom.getDLPredicate()).getNumber();
57 return no;
58 }
59
60 private class SkolemTermId {
61 private final int idBase;
62 private final int idOffset;
63
64 private SkolemTermId(int idBase, int idOffset) {
65 this.idBase = idBase;
66 this.idOffset = idOffset;
67 }
68
69 @Override
70 public String toString() {
71 return idBase + "_" + idOffset;
72 }
73 }
74}
diff --git a/src/uk/ac/ox/cs/pagoda/rules/approximators/TupleDependentApproximator.java b/src/uk/ac/ox/cs/pagoda/rules/approximators/TupleDependentApproximator.java
new file mode 100644
index 0000000..1a729e5
--- /dev/null
+++ b/src/uk/ac/ox/cs/pagoda/rules/approximators/TupleDependentApproximator.java
@@ -0,0 +1,16 @@
1package uk.ac.ox.cs.pagoda.rules.approximators;
2
3import org.semanticweb.HermiT.model.DLClause;
4import uk.ac.ox.cs.pagoda.multistage.AnswerTupleID;
5
6import java.util.Collection;
7
8/**
9 * It approximates rules according to a specific instantiation of the body.
10 */
11public interface TupleDependentApproximator {
12
13 Collection<DLClause> convert(DLClause clause,
14 DLClause originalClause,
15 Collection<AnswerTupleID> violationTuples);
16}