1
2
3
4 package org.sat4j.reader;
5
6 import java.io.IOException;
7 import java.math.BigInteger;
8 import java.util.HashMap;
9 import java.util.Map;
10
11 import org.sat4j.core.Vec;
12 import org.sat4j.core.VecInt;
13 import org.sat4j.specs.ContradictionException;
14 import org.sat4j.specs.ISolver;
15 import org.sat4j.specs.IVec;
16 import org.sat4j.specs.IVecInt;
17
18
19
20
21
22 public class OPBReader2007 extends OPBReader2006 {
23
24
25
26
27 private static final long serialVersionUID = 1L;
28
29 private int nbProducts;
30
31
32
33
34
35
36 public OPBReader2007(ISolver solver) {
37 super(solver);
38
39 }
40
41 @Override
42 protected boolean isGoodFirstCharacter(char c) {
43 return Character.isLetter(c) || c == '_' || c == '~';
44 }
45
46 @Override
47 protected void checkId(StringBuffer s) throws ParseFormatException {
48
49 int cpt = 1;
50 if (s.charAt(0) == '~')
51 cpt = 2;
52 int varID = Integer.parseInt(s.substring(cpt));
53 if (varID > nbVars) {
54 throw new ParseFormatException(
55 "Variable identifier larger than #variables in metadata.");
56 }
57 }
58
59
60
61
62 private int nbNewSymbols;
63
64 @Override
65 protected void readTerm(StringBuffer coeff, StringBuffer var)
66 throws IOException, ParseFormatException, ContradictionException {
67 readInteger(coeff);
68
69 skipSpaces();
70
71 var.setLength(0);
72 IVec<String> tmpLit = new Vec<String>();
73 StringBuffer tmpVar = new StringBuffer();
74 while (readIdentifier(tmpVar)) {
75 tmpLit = tmpLit.push(tmpVar.toString());
76 skipSpaces();
77 }
78 if (tmpLit.size() == 0)
79 throw new ParseFormatException("identifier expected");
80 if (tmpLit.size() == 1) {
81
82 var.append(tmpLit.last());
83 tmpLit.pop();
84 } else {
85
86 var.append(linearizeProduct(tmpLit));
87 }
88 }
89
90
91
92
93
94
95
96
97
98
99 protected void literalInAProduct(String var, IVecInt lits) {
100 int beginning = ((var.charAt(0) == '~') ? 2 : 1);
101 int id = Integer.parseInt(var.substring(beginning));
102 int lid = ((var.charAt(0) == '~') ? -1 : 1) * id;
103 lits.push(lid);
104 }
105
106
107
108
109
110
111
112
113
114
115 protected void negateLiteralInAProduct(String var, IVecInt lits) {
116 int beginning = ((var.charAt(0) == '~') ? 2 : 1);
117 int id = Integer.parseInt(var.substring(beginning));
118 int lid = ((var.charAt(0) == '~') ? 1 : -1) * id;
119 lits.push(lid);
120 }
121
122
123
124
125
126
127
128
129 @Override
130 protected void readMetaData() throws IOException, ParseFormatException {
131 char c;
132 String s;
133
134
135 c = get();
136 if (c != '*')
137 throw new ParseFormatException(
138 "First line of input file should be a comment");
139
140 s = readWord();
141 if (eof() || !"#variable=".equals(s))
142 throw new ParseFormatException(
143 "First line should contain #variable= as first keyword");
144
145 nbVars = Integer.parseInt(readWord());
146 nbNewSymbols = nbVars + 1;
147
148 s = readWord();
149 if (eof() || !"#constraint=".equals(s))
150 throw new ParseFormatException(
151 "First line should contain #constraint= as second keyword");
152
153 nbConstr = Integer.parseInt(readWord());
154
155 s = readWord();
156
157
158
159 if (s.equals("#product=")) {
160 nbProducts = Integer.parseInt(readWord());
161 nbVars += nbProducts;
162 nbConstr += 2 * nbProducts;
163 }
164
165 s = readWord();
166
167
168
169
170 if (s.equals("sizeproduct="))
171 readWord();
172
173
174 in.readLine();
175
176
177 metaData(nbVars, nbConstr);
178 }
179
180 @Override
181 protected int translateVarToId(String var) {
182 int beginning = ((var.charAt(0) == '~') ? 2 : 1);
183 int id = Integer.parseInt(var.substring(beginning));
184 return ((var.charAt(0) == '~') ? -1 : 1) * id;
185 }
186
187 private String linearizeProduct(IVec<String> tmpLit)
188 throws ContradictionException {
189 tmpLit.sort(String.CASE_INSENSITIVE_ORDER);
190 String newVar = getProductVariable(tmpLit);
191 if (newVar == null) {
192
193 newVar = "X" + String.valueOf(nbNewSymbols++);
194
195
196
197
198 productStore.put(newVar, tmpLit);
199 IVecInt newLits = new VecInt();
200 for (String lit : tmpLit)
201 negateLiteralInAProduct(lit, newLits);
202 literalInAProduct(newVar, newLits);
203 solver.addClause(newLits);
204
205
206
207 newLits.clear();
208 IVec<BigInteger> newCoefs = new Vec<BigInteger>();
209 for (String lit : tmpLit) {
210 literalInAProduct(lit, newLits);
211 newCoefs.push(BigInteger.ONE);
212 }
213 literalInAProduct(newVar, newLits);
214 newCoefs.push(new BigInteger(String.valueOf(-tmpLit.size())));
215 solver.addPseudoBoolean(newLits, newCoefs, true, BigInteger.ZERO);
216 nbConstraintsRead += 2;
217 }
218 return newVar;
219 }
220
221 private Map<String, IVec<String>> productStore = new HashMap<String, IVec<String>>();
222
223 private String getProductVariable(IVec<String> lits) {
224 for (Map.Entry<String, IVec<String>> c : productStore.entrySet())
225 if (c.getValue().equals(lits))
226 return c.getKey();
227 return null;
228 }
229
230 }