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