1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.sat4j.reader;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.InputStreamReader;
24 import java.io.LineNumberReader;
25 import java.io.PrintWriter;
26 import java.util.HashMap;
27 import java.util.LinkedHashMap;
28 import java.util.Map;
29 import java.util.Scanner;
30
31 import org.sat4j.core.Vec;
32 import org.sat4j.csp.Clausifiable;
33 import org.sat4j.csp.Constant;
34 import org.sat4j.csp.Domain;
35 import org.sat4j.csp.EnumeratedDomain;
36 import org.sat4j.csp.Evaluable;
37 import org.sat4j.csp.Predicate;
38 import org.sat4j.csp.RangeDomain;
39 import org.sat4j.csp.Var;
40 import org.sat4j.csp.constraints.AllDiff;
41 import org.sat4j.csp.constraints.Nogoods;
42 import org.sat4j.csp.constraints.Relation;
43 import org.sat4j.csp.constraints.WalshSupports;
44 import org.sat4j.specs.ContradictionException;
45 import org.sat4j.specs.IProblem;
46 import org.sat4j.specs.ISolver;
47 import org.sat4j.specs.IVec;
48
49
50
51
52
53
54
55
56
57
58
59
60
61 public class CSPReader extends Reader implements org.sat4j.csp.xml.ICSPCallback {
62
63 private final ISolver solver;
64
65
66
67 protected Relation[] relations;
68
69 private int valueindex;
70
71
72
73 private int relindex;
74
75 private int[] currentdomain;
76
77 private Domain rangedomain;
78
79 private String currentdomainid;
80
81 private int currentdomainsize;
82
83 private final Map<String, Domain> domainmapping = new HashMap<String, Domain>();
84
85 private final Map<String, Var> varmapping = new LinkedHashMap<String, Var>();
86
87 private final Map<String, Integer> relmapping = new HashMap<String, Integer>();
88
89 private final Map<String, Clausifiable> predmapping = new HashMap<String, Clausifiable>();
90
91 private int nbvarstocreate;
92
93 private int tupleindex;
94
95 private Clausifiable currentclausifiable;
96
97 private Predicate currentpredicate;
98
99 private final IVec<Evaluable> variables = new Vec<Evaluable>();
100
101 private final IVec<Var> scope = new Vec<Var>();
102
103 private int nbvars;
104
105 private int nbconstraints;
106
107 private int currentconstraint;
108
109 public CSPReader(ISolver solver) {
110 this.solver = solver;
111 Clausifiable allDiff = new AllDiff();
112 predmapping.put("global:allDifferent",allDiff);
113 predmapping.put("global:alldifferent",allDiff);
114 }
115
116 @Override
117 public final IProblem parseInstance(final java.io.Reader in)
118 throws ParseFormatException, ContradictionException, IOException {
119 return parseInstance(new LineNumberReader(in));
120
121 }
122
123 private IProblem parseInstance(LineNumberReader in)
124 throws ParseFormatException {
125 solver.reset();
126 try {
127 readProblem(in);
128 return solver;
129 } catch (NumberFormatException e) {
130 throw new ParseFormatException("integer value expected on line "
131 + in.getLineNumber(), e);
132 }
133 }
134
135 @Override
136 public void decode(int[] model, PrintWriter out) {
137
138 for (Var v : varmapping.values()) {
139 out.print(v.findValue(model));
140 out.print(" ");
141 }
142 }
143
144 @Override
145 public String decode(int[] model) {
146 StringBuilder stb = new StringBuilder();
147
148 for (Var v : varmapping.values()) {
149 stb.append(v.findValue(model));
150 stb.append(" ");
151 }
152 return stb.toString();
153 }
154
155 private void readProblem(LineNumberReader in) {
156 Scanner input = new Scanner(in);
157
158 beginInstance(input.nextLine());
159
160
161 int nbdomain = input.nextInt();
162 beginDomainsSection(nbdomain);
163
164 for (int i = 0; i < nbdomain; i++) {
165
166 int dnum = input.nextInt();
167 assert dnum == i;
168
169 int[] domain = readArrayOfInt(input);
170 beginDomain("" + dnum, domain.length);
171 for (int j = 0; j < domain.length; j++) {
172 addDomainValue(domain[j]);
173 }
174 endDomain();
175 }
176 endDomainsSection();
177 int nbvar = input.nextInt();
178 beginVariablesSection(nbvar);
179 for (int i = 0; i < nbvar; i++) {
180
181 int varnum = input.nextInt();
182 assert varnum == i;
183
184 int vardom = input.nextInt();
185 addVariable("" + varnum, "" + vardom);
186 }
187 endVariablesSection();
188
189
190
191 int nbrel = input.nextInt();
192 beginRelationsSection(nbrel);
193 for (int i = 0; i < nbrel; i++) {
194
195
196 int relnum = input.nextInt();
197 assert relnum == i;
198
199 boolean forbidden = input.nextInt() == 1 ? false : true;
200 int[] rdomains = readArrayOfInt(input);
201
202 int nbtuples = input.nextInt();
203
204 beginRelation("" + relnum, rdomains.length, nbtuples, !forbidden);
205
206 for (int j = 0; j < nbtuples; j++) {
207 int[] tuple = readArrayOfInt(input, relations[relnum].arity());
208
209 addRelationTuple(tuple);
210 }
211
212 endRelation();
213 }
214 endRelationsSection();
215 int nbconstr = input.nextInt();
216 beginConstraintsSection(nbconstr);
217
218 for (int i = 0; i < nbconstr; i++) {
219 int[] theVariables = readArrayOfInt(input);
220 beginConstraint("" + i, theVariables.length);
221 int relnum = input.nextInt();
222
223 constraintReference("" + relnum);
224 for (int v : theVariables) {
225 addEffectiveParameter("" + v);
226 }
227 endConstraint();
228 }
229 endConstraintsSection();
230 endInstance();
231 }
232
233 protected void manageAllowedTuples(int relnum, int arity, int nbtuples) {
234 relations[relnum] = new WalshSupports(arity, nbtuples);
235 }
236
237
238
239
240
241
242
243
244 private int[] readArrayOfInt(Scanner input) {
245 int size = input.nextInt();
246 return readArrayOfInt(input, size);
247 }
248
249 private int[] readArrayOfInt(Scanner input, int size) {
250 int[] tab = new int[size];
251 for (int i = 0; i < size; i++)
252 tab[i] = input.nextInt();
253 return tab;
254 }
255
256 public void beginInstance(String arg0) {
257 System.out.println("c reading problem named " + arg0);
258 }
259
260 public void beginDomainsSection(int nbdomain) {
261 System.out.print("c reading domains");
262 }
263
264 public void beginDomain(String id, int size) {
265 currentdomainsize = size;
266 currentdomain = null;
267 valueindex = -1;
268 currentdomainid = id;
269 rangedomain = null;
270 }
271
272 public void addDomainValue(int arg0) {
273 if (currentdomain == null) {
274 currentdomain = new int[currentdomainsize];
275 }
276 if (rangedomain != null) {
277 for (int i = 0; i < rangedomain.size(); i++)
278 currentdomain[++valueindex] = rangedomain.get(i);
279 rangedomain = null;
280 }
281 currentdomain[++valueindex] = arg0;
282 }
283
284 public void addDomainValue(int begin, int end) {
285 if (currentdomainsize == end - begin + 1)
286 rangedomain = new RangeDomain(begin, end);
287 else {
288 if (currentdomain == null) {
289 currentdomain = new int[currentdomainsize];
290 }
291 for (int v = begin; v <= end; v++)
292 currentdomain[++valueindex] = v;
293 }
294 }
295
296 public void endDomain() {
297 assert rangedomain != null || valueindex == currentdomain.length - 1;
298 if (rangedomain == null)
299 domainmapping.put(currentdomainid, new EnumeratedDomain(
300 currentdomain));
301 else
302 domainmapping.put(currentdomainid, rangedomain);
303 }
304
305 public void endDomainsSection() {
306 System.out.println(" done.");
307 }
308
309 public void beginVariablesSection(int expectedNumberOfVariables) {
310 System.out.print("c reading variables");
311 nbvarstocreate = 0;
312 this.nbvars = expectedNumberOfVariables;
313 }
314
315 public void addVariable(String idvar, String iddomain) {
316 Domain vardom = domainmapping.get(iddomain);
317 varmapping.put(idvar, new Var(idvar, vardom, nbvarstocreate));
318 nbvarstocreate += vardom.size();
319 if (isVerbose())
320 System.out.print("\rc reading variables " + varmapping.size() + "/"
321 + nbvars);
322
323 }
324
325 public void endVariablesSection() {
326 if (isVerbose())
327 System.out.println("\rc reading variables (" + nbvars + ") done.");
328 else
329 System.out.println(" done.");
330 solver.newVar(nbvarstocreate);
331 try {
332 for (Evaluable v : varmapping.values()) {
333 v.toClause(solver);
334 }
335 } catch (ContradictionException ce) {
336 assert false;
337 }
338
339 }
340
341 public void beginRelationsSection(int nbrel) {
342 System.out.print("c reading relations");
343 relations = new Relation[nbrel];
344 relindex = -1;
345 }
346
347 public void beginRelation(String name, int arity, int nbTuples,
348 boolean isSupport) {
349 relmapping.put(name, ++relindex);
350 if (isVerbose())
351 System.out.print("\rc reading relations " + relindex + "/"
352 + relations.length);
353 if (isSupport) {
354 manageAllowedTuples(relindex, arity, nbTuples);
355 } else {
356 relations[relindex] = new Nogoods(arity, nbTuples);
357 }
358 tupleindex = -1;
359 }
360
361 public void addRelationTuple(int[] tuple) {
362 relations[relindex].addTuple(++tupleindex, tuple);
363 }
364
365 public void endRelation() {
366 }
367
368 public void endRelationsSection() {
369 if (isVerbose())
370 System.out.println("\rc reading relations (" + relations.length
371 + ") done.");
372 else
373 System.out.println(" done.");
374 }
375
376 public void beginPredicatesSection(int arg0) {
377 System.out.print("c reading predicates ");
378 }
379
380 public void beginPredicate(String name) {
381 currentpredicate = new Predicate();
382 predmapping.put(name, currentpredicate);
383 if (isVerbose())
384 System.out.print("\rc reading predicate " + predmapping.size());
385 }
386
387 public void addFormalParameter(String name, String type) {
388 currentpredicate.addVariable(name);
389
390 }
391
392 public void predicateExpression(String expr) {
393 currentpredicate.setExpression(expr);
394 }
395
396 public void endPredicate() {
397
398 }
399
400 public void endPredicatesSection() {
401 if (isVerbose())
402 System.out.println("\rc reading relations (" + predmapping.size()
403 + ") done.");
404 else
405 System.out.println(" done.");
406 }
407
408 public void beginConstraintsSection(int arg0) {
409 System.out.println("c reading constraints");
410 nbconstraints = arg0;
411 currentconstraint = 0;
412 }
413
414 public void beginConstraint(String name, int arity) {
415 variables.clear();
416 variables.ensure(arity);
417 scope.clear();
418 scope.ensure(arity);
419 if (isVerbose())
420 System.out.print("\rc grounding constraint " + name + "("
421 + (++currentconstraint * 100 / nbconstraints) + "%)");
422 }
423
424 public void constraintReference(String ref) {
425 Integer id = relmapping.get(ref);
426 if (id == null) {
427 currentclausifiable = predmapping.get(ref);
428 } else {
429 currentclausifiable = relations[id];
430 }
431 if (currentclausifiable ==null) {
432 throw new IllegalArgumentException("Reference not supported: "+ref);
433 }
434 }
435
436 public void addVariableToConstraint(String arg0) {
437 scope.push(varmapping.get(arg0));
438 }
439
440 public void addEffectiveParameter(String arg0) {
441 variables.push(varmapping.get(arg0));
442 }
443
444 public void addEffectiveParameter(int arg0) {
445 variables.push(new Constant(arg0));
446 }
447
448 public void beginParameterList() {
449 throw new UnsupportedOperationException(
450 "I do not handle parameter list yet!");
451
452 }
453
454 public void addIntegerItem(int arg0) {
455
456
457 }
458
459 public void addVariableItem(String arg0) {
460
461
462 }
463
464 public void endParamaterList() {
465
466
467 }
468
469 public void addConstantParameter(String arg0, int arg1) {
470 throw new UnsupportedOperationException(
471 "I do not handle constant parameter yet!");
472 }
473
474 public void constraintExpression(String arg0) {
475 throw new UnsupportedOperationException(
476 "I do not handle constraint expression yet!");
477 }
478
479 public void endConstraint() {
480 try {
481 currentclausifiable.toClause(solver, scope, variables);
482 } catch (ContradictionException e) {
483 System.err.println("c INSTANCE TRIVIALLY UNSAT");
484 }
485 }
486
487 public void endConstraintsSection() {
488 if (isVerbose())
489 System.out.println("\rc reading constraints done.");
490 else
491 System.out.println("c done with constraints.");
492 }
493
494 public void endInstance() {
495
496 }
497
498 IProblem getProblem() {
499 return solver;
500 }
501
502 @Override
503 public IProblem parseInstance(final InputStream in)
504 throws ParseFormatException, ContradictionException, IOException {
505 return parseInstance(new InputStreamReader(in));
506 }
507 }