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 }