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 package org.sat4j.pb.reader;
53
54 import java.io.BufferedReader;
55 import java.io.IOException;
56 import java.io.LineNumberReader;
57 import java.io.PrintWriter;
58 import java.io.Serializable;
59 import java.math.BigInteger;
60
61 import org.sat4j.core.Vec;
62 import org.sat4j.core.VecInt;
63 import org.sat4j.pb.IPBSolver;
64 import org.sat4j.pb.ObjectiveFunction;
65 import org.sat4j.reader.ParseFormatException;
66 import org.sat4j.reader.Reader;
67 import org.sat4j.specs.ContradictionException;
68 import org.sat4j.specs.IProblem;
69 import org.sat4j.specs.IVec;
70 import org.sat4j.specs.IVecInt;
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86 public class OPBReader2005 extends Reader implements Serializable {
87
88
89
90
91 private static final long serialVersionUID = 1L;
92
93 protected final IPBSolver solver;
94
95 protected final IVecInt lits;
96
97 protected final IVec<BigInteger> coeffs;
98
99 protected BigInteger d;
100
101 protected String operator;
102
103 private final IVecInt objectiveVars = new VecInt();
104
105 private final IVec<BigInteger> objectiveCoeffs = new Vec<BigInteger>();
106
107
108 protected boolean hasObjFunc = false;
109
110
111 protected boolean hasVariablesExplanation = false;
112
113 protected int nbVars, nbConstr;
114
115
116 protected int nbConstraintsRead;
117
118
119
120
121
122
123
124
125
126
127 protected void metaData(int nbvar, int nbconstr) {
128 solver.newVar(nbvar);
129 }
130
131
132
133
134 protected void beginObjective() {
135 }
136
137
138
139
140 protected void endObjective() {
141 assert lits.size() == coeffs.size();
142 assert lits.size() == coeffs.size();
143 for (int i = 0; i < lits.size(); i++) {
144 objectiveVars.push(lits.get(i));
145 objectiveCoeffs.push(coeffs.get(i));
146 }
147 }
148
149
150
151
152 protected void beginConstraint() {
153 lits.clear();
154 coeffs.clear();
155 assert lits.size() == 0;
156 assert coeffs.size() == 0;
157 }
158
159
160
161
162
163
164
165 protected void endConstraint() throws ContradictionException {
166
167 assert !(lits.size() == 0);
168 assert !(coeffs.size() == 0);
169 assert lits.size() == coeffs.size();
170
171 if ("<=".equals(operator) || "=".equals(operator)) {
172 solver.addPseudoBoolean(lits, coeffs, false, d);
173 }
174 if (">=".equals(operator) || "=".equals(operator)) {
175 solver.addPseudoBoolean(lits, coeffs, true, d);
176 }
177 nbConstraintsRead++;
178 }
179
180
181
182
183
184
185
186
187
188
189 private void constraintTerm(BigInteger coeff, String var)
190 throws ParseFormatException {
191 coeffs.push(coeff);
192 lits.push(translateVarToId(var));
193 }
194
195 protected int translateVarToId(String var) throws ParseFormatException {
196 int id = Integer.parseInt(var.substring(1));
197 return ((savedChar == '-') ? -1 : 1) * id;
198 }
199
200
201
202
203
204
205
206 protected void constraintRelOp(String relop) {
207 operator = relop;
208 }
209
210
211
212
213
214
215
216
217 protected void constraintRightTerm(BigInteger val) {
218 d = val;
219 }
220
221 transient BufferedReader in;
222
223 char savedChar;
224
225 boolean charAvailable = false;
226
227 boolean eofReached = false;
228
229 private boolean eolReached = false;
230
231
232
233
234
235
236 protected char get() throws IOException {
237 int c;
238
239 if (charAvailable) {
240 charAvailable = false;
241 return savedChar;
242 }
243
244 c = in.read();
245 if (c == -1)
246 eofReached = true;
247 if (c == '\n' || c == '\r') {
248 eolReached = true;
249 } else {
250 eolReached = false;
251 }
252 return (char) c;
253 }
254
255 public IVecInt getVars() {
256 return objectiveVars;
257 }
258
259 public IVec<BigInteger> getCoeffs() {
260 return objectiveCoeffs;
261 }
262
263
264
265
266 protected void putback(char c) {
267 savedChar = c;
268 charAvailable = true;
269 }
270
271
272
273
274 protected boolean eof() {
275 return eofReached;
276 }
277
278 protected boolean eol() {
279 return eolReached;
280 }
281
282
283
284
285
286
287 protected void skipSpaces() throws IOException {
288 char c;
289
290 do {
291 c = get();
292 } while (Character.isWhitespace(c));
293
294 putback(c);
295 }
296
297
298
299
300
301
302
303 public String readWord() throws IOException {
304 StringBuffer s = new StringBuffer();
305 char c;
306
307 skipSpaces();
308
309 while (!Character.isWhitespace(c = get()) && !eol() && !eof())
310 s.append(c);
311
312 putback(c);
313 return s.toString();
314 }
315
316
317
318
319
320
321
322
323 public void readInteger(StringBuffer s) throws IOException {
324 char c;
325
326 skipSpaces();
327 s.setLength(0);
328
329 c = get();
330 if (c == '-' || Character.isDigit(c))
331 s.append(c);
332
333
334 while (Character.isDigit(c = get()) && !eol() && !eof())
335 s.append(c);
336
337 putback(c);
338 }
339
340
341
342
343
344
345
346
347 protected boolean readIdentifier(StringBuffer s) throws IOException,
348 ParseFormatException {
349 char c;
350
351 s.setLength(0);
352
353 skipSpaces();
354
355
356 c = get();
357 if (eof())
358 return false;
359
360 if (!isGoodFirstCharacter(c)) {
361 putback(c);
362 return false;
363 }
364
365 s.append(c);
366
367
368 while (true) {
369 c = get();
370 if (eof())
371 break;
372
373 if (isGoodFollowingCharacter(c))
374 s.append(c);
375 else {
376 putback(c);
377 break;
378 }
379 }
380 checkId(s);
381 return true;
382 }
383
384 protected boolean isGoodFirstCharacter(char c) {
385 return Character.isLetter(c) || c == '_';
386 }
387
388 protected boolean isGoodFollowingCharacter(char c) {
389 return Character.isLetter(c) || Character.isDigit(c) || c == '_';
390 }
391
392 protected void checkId(StringBuffer s) throws ParseFormatException {
393
394 int varID = Integer.parseInt(s.substring(1));
395 if (varID > nbVars) {
396 throw new ParseFormatException(
397 "Variable identifier larger than #variables in metadata.");
398 }
399 }
400
401
402
403
404
405
406
407 private String readRelOp() throws IOException {
408 char c;
409
410 skipSpaces();
411
412 c = get();
413 if (eof())
414 return null;
415
416 if (c == '=')
417 return "=";
418
419 char following = get();
420 if (c == '>' && following == '=')
421 return ">=";
422 if (c == '<' && following == '=')
423 return "<=";
424
425 return null;
426 }
427
428
429
430
431
432
433
434
435 protected void readMetaData() throws IOException, ParseFormatException {
436 char c;
437 String s;
438
439
440 c = get();
441 if (c != '*')
442 throw new ParseFormatException(
443 "First line of input file should be a comment");
444
445 s = readWord();
446 if (eof() || !"#variable=".equals(s))
447 throw new ParseFormatException(
448 "First line should contain #variable= as first keyword");
449
450 nbVars = Integer.parseInt(readWord());
451
452 s = readWord();
453 if (eof() || !"#constraint=".equals(s))
454 throw new ParseFormatException(
455 "First line should contain #constraint= as second keyword");
456
457 nbConstr = Integer.parseInt(readWord());
458
459
460 in.readLine();
461
462
463 metaData(nbVars, nbConstr);
464 }
465
466
467
468
469
470
471 private void skipComments() throws IOException {
472 char c = ' ';
473
474
475
476 while (!eof() && (c = get()) == '*') {
477 in.readLine();
478 }
479
480 putback(c);
481 }
482
483
484
485
486
487
488
489
490
491
492
493 protected void readTerm(StringBuffer coeff, StringBuffer var)
494 throws IOException, ParseFormatException {
495 char c;
496
497 readInteger(coeff);
498
499 skipSpaces();
500 c = get();
501 if (c != '*')
502 throw new ParseFormatException(
503 "'*' expected between a coefficient and a variable");
504
505 if (!readIdentifier(var))
506 throw new ParseFormatException("identifier expected");
507 }
508
509
510
511
512
513 protected void readVariablesExplanation() throws IOException,
514 ParseFormatException {
515 }
516
517
518
519
520
521
522
523
524 protected void readObjective() throws IOException, ParseFormatException {
525 char c;
526 StringBuffer var = new StringBuffer();
527 StringBuffer coeff = new StringBuffer();
528
529
530
531 skipSpaces();
532 c = get();
533 if (c != 'm') {
534
535 putback(c);
536 return;
537 }
538
539 hasObjFunc = true;
540 if (get() == 'i' && get() == 'n' && get() == ':') {
541 beginObjective();
542
543 while (!eof()) {
544 readTerm(coeff, var);
545 constraintTerm(new BigInteger(coeff.toString()), var.toString());
546
547 skipSpaces();
548 c = get();
549 if (c == ';')
550 break;
551
552 else if (c == '-' || c == '+' || Character.isDigit(c))
553 putback(c);
554 else
555 throw new ParseFormatException(
556 "unexpected character in objective function");
557 }
558
559 endObjective();
560 } else
561 throw new ParseFormatException(
562 "input format error: 'min:' expected");
563 }
564
565
566
567
568
569
570
571
572 protected void readConstraint() throws IOException, ParseFormatException,
573 ContradictionException {
574 StringBuffer var = new StringBuffer();
575 StringBuffer coeff = new StringBuffer();
576 char c;
577
578 beginConstraint();
579
580 while (!eof()) {
581 readTerm(coeff, var);
582 constraintTerm(new BigInteger(coeff.toString()), var.toString());
583
584 skipSpaces();
585 c = get();
586 if (c == '>' || c == '=' || c == '<') {
587
588 putback(c);
589 break;
590 } else if (c == '-' || c == '+' || Character.isDigit(c))
591 putback(c);
592 else {
593 throw new ParseFormatException(
594 "unexpected character in constraint");
595 }
596 }
597
598 if (eof())
599 throw new ParseFormatException(
600 "unexpected EOF before end of constraint");
601
602 String relop;
603 if ((relop = readRelOp()) == null) {
604 throw new ParseFormatException(
605 "unexpected relational operator in constraint");
606
607 }
608 constraintRelOp(relop);
609 readInteger(coeff);
610 constraintRightTerm(new BigInteger(coeff.toString()));
611
612 skipSpaces();
613 c = get();
614 if (eof() || c != ';')
615 throw new ParseFormatException(
616 "semicolon expected at end of constraint");
617
618 endConstraint();
619 }
620
621 public OPBReader2005(IPBSolver solver) {
622 this.solver = solver;
623 lits = new VecInt();
624 coeffs = new Vec<BigInteger>();
625 }
626
627
628
629
630
631
632
633
634
635 public void parse() throws IOException, ParseFormatException,
636 ContradictionException {
637 readMetaData();
638
639 skipComments();
640
641 readObjective();
642
643 readVariablesExplanation();
644
645
646 nbConstraintsRead = 0;
647 char c;
648 while (!eof()) {
649 skipSpaces();
650 if (eof())
651 break;
652
653 c = get();
654 putback(c);
655 if (c == '*')
656 skipComments();
657
658 if (eof())
659 break;
660
661 readConstraint();
662
663 }
664
665 if (nbConstraintsRead != nbConstr) {
666 throw new ParseFormatException("Number of constraints read ("
667 + nbConstraintsRead + ") is different from metadata ("
668 + nbConstr + ")");
669 }
670 }
671
672 @Override
673 public IProblem parseInstance(final java.io.Reader input)
674 throws ParseFormatException, ContradictionException {
675 IProblem problem = parseInstance(new LineNumberReader(input));
676 solver.setObjectiveFunction(getObjectiveFunction());
677 return problem;
678 }
679
680 private IProblem parseInstance(LineNumberReader input)
681 throws ParseFormatException, ContradictionException {
682 solver.reset();
683 this.in = input;
684 try {
685 parse();
686 return solver;
687 } catch (ContradictionException ce) {
688 throw ce;
689 } catch (Exception e) {
690 String message;
691
692 if (e instanceof ParseFormatException) {
693 message = e.getMessage().substring(
694 "DIMACS Format error: ".length());
695 } else {
696 message = e.getMessage();
697 }
698 throw new ParseFormatException(" line " + input.getLineNumber()
699 + ", " + message);
700
701 }
702 }
703
704 @Override
705 public String decode(int[] model) {
706 StringBuffer stb = new StringBuffer();
707
708 for (int i = 0; i < model.length; i++) {
709 if (model[i] < 0) {
710 stb.append("-x");
711 stb.append(-model[i]);
712 } else {
713 stb.append("x");
714 stb.append(model[i]);
715 }
716 stb.append(" ");
717 }
718 return stb.toString();
719 }
720
721 @Override
722 public void decode(int[] model, PrintWriter out) {
723 for (int i = 0; i < model.length; i++) {
724 if (model[i] < 0) {
725 out.print("-x");
726 out.print(-model[i]);
727 } else {
728 out.print("x");
729 out.print(model[i]);
730 }
731 out.print(" ");
732 }
733 }
734
735 public ObjectiveFunction getObjectiveFunction() {
736 if (hasObjFunc) {
737 return new ObjectiveFunction(getVars(), getCoeffs());
738 }
739 return null;
740 }
741
742 public IVecInt getListOfVariables() {
743 return null;
744 }
745
746 }