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.math.BigInteger;
56 import java.util.HashMap;
57 import java.util.Iterator;
58 import java.util.Map;
59
60 import org.sat4j.core.Vec;
61 import org.sat4j.core.VecInt;
62 import org.sat4j.pb.IPBSolver;
63 import org.sat4j.reader.ParseFormatException;
64 import org.sat4j.specs.ContradictionException;
65 import org.sat4j.specs.IVec;
66 import org.sat4j.specs.IVecInt;
67
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 private int nbProducts;
90
91
92
93
94
95
96 public OPBReader2007(IPBSolver solver) {
97 super(solver);
98 }
99
100 @Override
101 protected boolean isGoodFirstCharacter(char c) {
102 return Character.isLetter(c) || c == '_' || c == '~';
103 }
104
105 @Override
106 protected void checkId(StringBuffer s) throws ParseFormatException {
107
108 int cpt = 1;
109 if (s.charAt(0) == '~')
110 cpt = 2;
111 int varID = Integer.parseInt(s.substring(cpt));
112 if (varID > nbVars) {
113 throw new ParseFormatException(
114 "Variable identifier larger than #variables in metadata.");
115 }
116 }
117
118
119
120
121 private int nbNewSymbols;
122
123 @Override
124 protected void readTerm(StringBuffer coeff, StringBuffer var)
125 throws IOException, ParseFormatException, ContradictionException {
126 readInteger(coeff);
127
128 skipSpaces();
129
130 var.setLength(0);
131 IVec<String> tmpLit = new Vec<String>();
132 StringBuffer tmpVar = new StringBuffer();
133 while (readIdentifier(tmpVar)) {
134 tmpLit = tmpLit.push(tmpVar.toString());
135 skipSpaces();
136 }
137 if (tmpLit.size() == 0)
138 throw new ParseFormatException("identifier expected");
139 if (tmpLit.size() == 1) {
140
141 var.append(tmpLit.last());
142 tmpLit.pop();
143 } else {
144
145 var.append(linearizeProduct(tmpLit));
146 }
147 }
148
149
150
151
152
153
154
155
156
157
158 protected void literalInAProduct(String var, IVecInt lits) {
159 int beginning = ((var.charAt(0) == '~') ? 2 : 1);
160 int id = Integer.parseInt(var.substring(beginning));
161 int lid = ((var.charAt(0) == '~') ? -1 : 1) * id;
162 lits.push(lid);
163 }
164
165
166
167
168
169
170
171
172
173
174 protected void negateLiteralInAProduct(String var, IVecInt lits) {
175 int beginning = ((var.charAt(0) == '~') ? 2 : 1);
176 int id = Integer.parseInt(var.substring(beginning));
177 int lid = ((var.charAt(0) == '~') ? 1 : -1) * id;
178 lits.push(lid);
179 }
180
181
182
183
184
185
186
187
188 @Override
189 protected void readMetaData() throws IOException, ParseFormatException {
190 char c;
191 String s;
192
193
194 c = get();
195 if (c != '*')
196 throw new ParseFormatException(
197 "First line of input file should be a comment");
198 s = readWord();
199 if (eof() || !"#variable=".equals(s))
200 throw new ParseFormatException(
201 "First line should contain #variable= as first keyword");
202
203 nbVars = Integer.parseInt(readWord());
204 nbNewSymbols = nbVars + 1;
205
206 s = readWord();
207 if (eof() || !"#constraint=".equals(s))
208 throw new ParseFormatException(
209 "First line should contain #constraint= as second keyword");
210
211 nbConstr = Integer.parseInt(readWord());
212 charAvailable = false;
213 if (!eol()) {
214 String rest = in.readLine();
215
216 if (rest!=null&&rest.indexOf("#product=") != -1) {
217 String[] splitted = rest.trim().split(" ");
218 if (splitted[0].equals("#product=")) {
219 nbProducts = Integer.parseInt(splitted[1]);
220 nbVars += nbProducts;
221 nbConstr += 2 * nbProducts;
222 }
223
224
225
226
227 }
228 }
229
230 metaData(nbVars, nbConstr);
231 }
232
233 @Override
234 protected int translateVarToId(String var) {
235 int beginning = ((var.charAt(0) == '~') ? 2 : 1);
236 int id = Integer.parseInt(var.substring(beginning));
237 return ((var.charAt(0) == '~') ? -1 : 1) * id;
238 }
239
240 private String linearizeProduct(IVec<String> tmpLit)
241 throws ContradictionException {
242 tmpLit.sort(String.CASE_INSENSITIVE_ORDER);
243 String newVar = getProductVariable(tmpLit);
244 if (newVar == null) {
245
246 newVar = "X" + String.valueOf(nbNewSymbols++);
247
248
249
250
251 productStore.put(newVar, tmpLit);
252 IVecInt newLits = new VecInt();
253 for (Iterator<String> iterator = tmpLit.iterator();iterator.hasNext();)
254 negateLiteralInAProduct(iterator.next(), newLits);
255 literalInAProduct(newVar, newLits);
256 solver.addClause(newLits);
257
258
259
260 newLits.clear();
261 IVec<BigInteger> newCoefs = new Vec<BigInteger>();
262 for (Iterator<String> iterator = tmpLit.iterator();iterator.hasNext();) {
263 literalInAProduct(iterator.next(), newLits);
264 newCoefs.push(BigInteger.ONE);
265 }
266 literalInAProduct(newVar, newLits);
267 newCoefs.push(new BigInteger(String.valueOf(-tmpLit.size())));
268 solver.addPseudoBoolean(newLits, newCoefs, true, BigInteger.ZERO);
269 nbConstraintsRead += 2;
270 }
271 return newVar;
272 }
273
274 private Map<String, IVec<String>> productStore = new HashMap<String, IVec<String>>();
275
276 private String getProductVariable(IVec<String> lits) {
277 for (Map.Entry<String, IVec<String>> c : productStore.entrySet())
278 if (c.getValue().equals(lits))
279 return c.getKey();
280 return null;
281 }
282
283 }