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 package org.sat4j.reader;
27
28 import java.io.IOException;
29 import java.io.LineNumberReader;
30 import java.io.PrintWriter;
31 import java.io.Serializable;
32 import java.math.BigInteger;
33 import java.util.HashMap;
34 import java.util.Map;
35 import java.util.Scanner;
36
37 import org.sat4j.core.Vec;
38 import org.sat4j.core.VecInt;
39 import org.sat4j.specs.ContradictionException;
40 import org.sat4j.specs.IProblem;
41 import org.sat4j.specs.ISolver;
42 import org.sat4j.specs.IVec;
43 import org.sat4j.specs.IVecInt;
44
45
46
47
48
49
50
51
52
53 public class GoodOPBReader extends Reader implements Serializable {
54
55
56
57
58 private static final long serialVersionUID = 1L;
59
60 private static final String COMMENT_SYMBOL = "*";
61
62 private final ISolver solver;
63
64 private final Map<String, Integer> map = new HashMap<String, Integer>();
65
66 private final IVec<String> decode = new Vec<String>();
67
68
69
70
71 public GoodOPBReader(ISolver solver) {
72 this.solver = solver;
73 }
74
75 @Override
76 public final IProblem parseInstance(final java.io.Reader in)
77 throws ParseFormatException, ContradictionException, IOException {
78 return parseInstance(new LineNumberReader(in));
79 }
80
81 private IProblem parseInstance(LineNumberReader in)
82 throws ContradictionException, IOException {
83 solver.reset();
84 String line;
85 while ((line = in.readLine()) != null) {
86
87 line = line.trim();
88 if (line.endsWith(";")) {
89 line = line.substring(0, line.length() - 1);
90 }
91 parseLine(line);
92 }
93 return solver;
94 }
95
96 void parseLine(String line) throws ContradictionException {
97
98 if (line.startsWith(COMMENT_SYMBOL))
99 return;
100 if (line.startsWith("p"))
101 return;
102 if (line.startsWith("min:") || line.startsWith("min :"))
103 return;
104 if (line.startsWith("max:") || line.startsWith("max :"))
105 return;
106
107
108 int index = line.indexOf(":");
109 if (index != -1) {
110 line = line.substring(index + 1);
111 }
112
113 IVecInt lits = new VecInt();
114 IVec<BigInteger> coeffs = new Vec<BigInteger>();
115 Scanner stk = new Scanner(line)
116 .useDelimiter("\\s*\\*\\s*|\\s*\\+\\s*|\\s+");
117 while (stk.hasNext()) {
118 String token = stk.next();
119 if (">=".equals(token) || "<=".equals(token) || "=".equals(token)) {
120 assert stk.hasNext();
121 String tok = stk.next();
122
123 if (tok.startsWith("+")) {
124 tok = tok.substring(1);
125 }
126 BigInteger d = new BigInteger(tok);
127
128 try {
129 if (">=".equals(token) || "=".equals(token)) {
130 solver.addPseudoBoolean(lits, coeffs, true, d);
131 }
132 if ("<=".equals(token) || "=".equals(token)) {
133 solver.addPseudoBoolean(lits, coeffs, false, d);
134 }
135 } catch (ContradictionException ce) {
136 System.out.println("c inconsistent constraint: " + line);
137 System.out.println("c lits: " + lits);
138 System.out.println("c coeffs: " + coeffs);
139 throw ce;
140 }
141 } else {
142
143
144 if ("+".equals(token)) {
145 assert stk.hasNext();
146 token = stk.next();
147 } else if ("-".equals(token)) {
148 assert stk.hasNext();
149 token = token + stk.next();
150 }
151 BigInteger coef;
152
153 try {
154
155 if (token.startsWith("+")) {
156 token = token.substring(1);
157 }
158 coef = new BigInteger(token);
159 assert stk.hasNext();
160 token = stk.next();
161 } catch (NumberFormatException nfe) {
162
163 coef = BigInteger.ONE;
164 }
165 if ("-".equals(token) || "~".equals(token)) {
166 assert stk.hasNext();
167 token = token + stk.next();
168 }
169 boolean negative = false;
170 if (token.startsWith("+")) {
171 token = token.substring(1);
172 } else if (token.startsWith("-")) {
173 token = token.substring(1);
174 assert coef.equals(BigInteger.ONE);
175 coef = BigInteger.ONE.negate();
176 } else if (token.startsWith("~")) {
177 token = token.substring(1);
178 negative = true;
179 }
180 Integer id = map.get(token);
181 if (id == null) {
182 map.put(token, id = solver.newVar());
183 decode.push(token);
184 assert decode.size() == id.intValue();
185 }
186 coeffs.push(coef);
187 int lid = (negative ? -1 : 1) * id.intValue();
188 lits.push(lid);
189 assert coeffs.size() == lits.size();
190 }
191 }
192 }
193
194 @Override
195 public String decode(int[] model) {
196 StringBuffer stb = new StringBuffer();
197 for (int i = 0; i < model.length; i++) {
198 if (model[i] < 0) {
199 stb.append("-");
200 stb.append(decode.get(-model[i] - 1));
201 } else {
202 stb.append(decode.get(model[i] - 1));
203 }
204 stb.append(" ");
205 }
206 return stb.toString();
207 }
208
209 @Override
210 public void decode(int[] model, PrintWriter out) {
211 for (int i = 0; i < model.length; i++) {
212 if (model[i] < 0) {
213 out.print("-");
214 out.print(decode.get(-model[i] - 1));
215 } else {
216 out.print(decode.get(model[i] - 1));
217 }
218 out.print(" ");
219 }
220 }
221 }