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