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