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.IOException;
55 import java.io.PrintWriter;
56 import java.math.BigInteger;
57 import java.util.HashMap;
58 import java.util.Iterator;
59 import java.util.Map;
60
61 import org.sat4j.core.Vec;
62 import org.sat4j.core.VecInt;
63 import org.sat4j.pb.IPBSolver;
64 import org.sat4j.reader.ParseFormatException;
65 import org.sat4j.specs.ContradictionException;
66 import org.sat4j.specs.IVec;
67 import org.sat4j.specs.IVecInt;
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82 public class OPBReader2007 extends OPBReader2006 {
83
84
85
86
87 private static final long serialVersionUID = 1L;
88
89
90
91
92 public OPBReader2007(IPBSolver solver) {
93 super(solver);
94 }
95
96 @Override
97 protected boolean isGoodFirstCharacter(char c) {
98 return Character.isLetter(c) || c == '_' || c == '~';
99 }
100
101 @Override
102 protected void checkId(StringBuffer s) throws ParseFormatException {
103
104 int cpt = 1;
105 if (s.charAt(0) == '~') {
106 cpt = 2;
107 }
108 int varID = Integer.parseInt(s.substring(cpt));
109 if (varID > this.nbVars) {
110 throw new ParseFormatException(
111 "Variable identifier larger than #variables in metadata.");
112 }
113 }
114
115
116
117
118 protected int nbNewSymbols;
119
120 @Override
121 protected void readTerm(StringBuffer coeff, StringBuffer var)
122 throws IOException, ParseFormatException {
123 readInteger(coeff);
124
125 skipSpaces();
126
127 var.setLength(0);
128 IVec<String> tmpLit = new Vec<String>();
129 StringBuffer tmpVar = new StringBuffer();
130 while (readIdentifier(tmpVar)) {
131 tmpLit = tmpLit.push(tmpVar.toString());
132 skipSpaces();
133 }
134 if (tmpLit.size() == 0) {
135 throw new ParseFormatException("identifier expected");
136 }
137 if (tmpLit.size() == 1) {
138
139 var.append(tmpLit.last());
140 tmpLit.pop();
141 } else {
142
143 try {
144 var.append(linearizeProduct(tmpLit));
145 } catch (ContradictionException e) {
146 throw new ParseFormatException(e);
147 }
148 }
149 }
150
151
152
153
154
155
156
157
158
159
160
161 protected void literalInAProduct(String var, IVecInt lits)
162 throws ParseFormatException {
163 int beginning = var.charAt(0) == '~' ? 2 : 1;
164 int id = Integer.parseInt(var.substring(beginning));
165 int lid = (var.charAt(0) == '~' ? -1 : 1) * id;
166 if (lid == 0 || Math.abs(lid) >= this.nbNewSymbols) {
167 throw new ParseFormatException("Wrong variable id");
168 }
169 lits.push(lid);
170 }
171
172
173
174
175
176
177
178
179
180
181 protected void negateLiteralInAProduct(String var, IVecInt lits) {
182 int beginning = var.charAt(0) == '~' ? 2 : 1;
183 int id = Integer.parseInt(var.substring(beginning));
184 int lid = (var.charAt(0) == '~' ? 1 : -1) * id;
185 lits.push(lid);
186 }
187
188
189
190
191
192
193
194
195 @Override
196 protected void readMetaData() throws IOException, ParseFormatException {
197 char c;
198 String s;
199
200
201 c = get();
202 if (c != '*') {
203 throw new ParseFormatException(
204 "First line of input file should be a comment");
205 }
206 s = readWord();
207 if (eof() || !"#variable=".equals(s)) {
208 throw new ParseFormatException(
209 "First line should contain #variable= as first keyword");
210 }
211
212 this.nbVars = Integer.parseInt(readWord());
213 this.nbNewSymbols = this.nbVars + 1;
214
215 s = readWord();
216 if (eof() || !"#constraint=".equals(s)) {
217 throw new ParseFormatException(
218 "First line should contain #constraint= as second keyword");
219 }
220
221 this.nbConstr = Integer.parseInt(readWord());
222 this.charAvailable = false;
223 if (!eol()) {
224 String rest = this.in.readLine();
225
226 if (rest != null && rest.indexOf("#product=") != -1) {
227 String[] splitted = rest.trim().split(" ");
228 if (splitted[0].equals("#product=")) {
229 Integer.parseInt(splitted[1]);
230 }
231
232
233
234
235 }
236 }
237
238 metaData(this.nbVars, this.nbConstr);
239 }
240
241 @Override
242 protected int translateVarToId(String var) throws ParseFormatException {
243 int beginning = var.charAt(0) == '~' ? 2 : 1;
244 int id = Integer.parseInt(var.substring(beginning));
245 if (id == 0 || id >= this.nbNewSymbols) {
246 throw new ParseFormatException("Wrong variable id format: " + var);
247 }
248 return (var.charAt(0) == '~' ? -1 : 1) * id;
249 }
250
251 private String linearizeProduct(IVec<String> tmpLit)
252 throws ContradictionException, ParseFormatException {
253 tmpLit.sort(String.CASE_INSENSITIVE_ORDER);
254 String newVar = getProductVariable(tmpLit);
255 if (newVar == null) {
256
257 newVar = "X" + this.nbNewSymbols++;
258
259
260
261
262 if (tmpLit.size() == 2) {
263 Map<String, String> map1 = this.binaryProductToVar.get(tmpLit
264 .get(0));
265 if (map1 == null) {
266 map1 = new HashMap<String, String>();
267 this.binaryProductToVar.put(tmpLit.get(0), map1);
268 }
269 map1.put(tmpLit.get(1), newVar);
270 }
271 this.varToProduct.put(newVar, tmpLit);
272 IVecInt newLits = new VecInt();
273 for (Iterator<String> iterator = tmpLit.iterator(); iterator
274 .hasNext();) {
275 negateLiteralInAProduct(iterator.next(), newLits);
276 }
277 literalInAProduct(newVar, newLits);
278 this.solver.addClause(newLits);
279
280
281
282 newLits.clear();
283 IVec<BigInteger> newCoefs = new Vec<BigInteger>();
284 for (Iterator<String> iterator = tmpLit.iterator(); iterator
285 .hasNext();) {
286 literalInAProduct(iterator.next(), newLits);
287 newCoefs.push(BigInteger.ONE);
288 }
289 literalInAProduct(newVar, newLits);
290 newCoefs.push(new BigInteger(String.valueOf(-tmpLit.size())));
291 this.solver.addPseudoBoolean(newLits, newCoefs, true,
292 BigInteger.ZERO);
293
294 }
295 return newVar;
296 }
297
298 private final Map<String, IVec<String>> varToProduct = new HashMap<String, IVec<String>>();
299
300 private final Map<String, Map<String, String>> binaryProductToVar = new HashMap<String, Map<String, String>>();
301
302 private String getProductVariable(IVec<String> lits) {
303 if (lits.size() == 2) {
304 Map<String, String> map = this.binaryProductToVar.get(lits.get(0));
305 if (map == null) {
306 return null;
307 }
308 return map.get(lits.get(1));
309 }
310 for (Map.Entry<String, IVec<String>> c : this.varToProduct.entrySet()) {
311 if (c.getValue().equals(lits)) {
312 return c.getKey();
313 }
314 }
315 return null;
316 }
317
318 @Override
319 public String decode(int[] model) {
320 StringBuffer stb = new StringBuffer();
321 int p;
322 for (int element : model) {
323 p = element;
324 if (Math.abs(p) <= this.nbVars) {
325 if (p < 0) {
326 stb.append("-x");
327 stb.append(-p);
328 } else {
329 stb.append("x");
330 stb.append(p);
331 }
332 stb.append(" ");
333 }
334 }
335 return stb.toString();
336 }
337
338 @Override
339 public void decode(int[] model, PrintWriter out) {
340 int p;
341 for (int element : model) {
342 p = element;
343 if (Math.abs(p) <= this.nbVars) {
344 if (element < 0) {
345 out.print("-x");
346 out.print(-p);
347 } else {
348 out.print("x");
349 out.print(p);
350 }
351 out.print(" ");
352 }
353 }
354 }
355
356 }