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 package org.sat4j.pb;
31
32 import java.io.IOException;
33 import java.io.InputStream;
34 import java.io.InputStreamReader;
35 import java.io.LineNumberReader;
36 import java.io.PrintWriter;
37 import java.io.Serializable;
38 import java.math.BigInteger;
39 import java.util.HashMap;
40 import java.util.Map;
41 import java.util.Scanner;
42
43 import org.sat4j.core.Vec;
44 import org.sat4j.core.VecInt;
45 import org.sat4j.reader.ParseFormatException;
46 import org.sat4j.reader.Reader;
47 import org.sat4j.specs.ContradictionException;
48 import org.sat4j.specs.IProblem;
49 import org.sat4j.specs.IVec;
50 import org.sat4j.specs.IVecInt;
51
52
53
54
55
56
57
58
59
60 public class GoodOPBReader extends Reader implements Serializable {
61
62
63
64
65 private static final long serialVersionUID = 1L;
66
67 private static final String COMMENT_SYMBOL = "*";
68
69 private final IPBSolver solver;
70
71 private final Map<String, Integer> map = new HashMap<String, Integer>();
72
73 private final IVec<String> decode = new Vec<String>();
74
75
76
77
78 public GoodOPBReader(IPBSolver solver) {
79 this.solver = solver;
80 }
81
82 @Override
83 public final IProblem parseInstance(final java.io.Reader in)
84 throws ParseFormatException, ContradictionException, IOException {
85 return parseInstance(new LineNumberReader(in));
86 }
87
88 private IProblem parseInstance(LineNumberReader in)
89 throws ContradictionException, IOException {
90 this.solver.reset();
91 String line;
92 while ((line = in.readLine()) != null) {
93
94 line = line.trim();
95 if (line.endsWith(";")) {
96 line = line.substring(0, line.length() - 1);
97 }
98 parseLine(line);
99 }
100 return this.solver;
101 }
102
103 void parseLine(String line) throws ContradictionException {
104
105 if (line.startsWith(COMMENT_SYMBOL)) {
106 return;
107 }
108 if (line.startsWith("p")) {
109 return;
110 }
111 if (line.startsWith("min:") || line.startsWith("min :")) {
112 return;
113 }
114 if (line.startsWith("max:") || line.startsWith("max :")) {
115 return;
116 }
117
118
119 int index = line.indexOf(":");
120 if (index != -1) {
121 line = line.substring(index + 1);
122 }
123
124 IVecInt lits = new VecInt();
125 IVec<BigInteger> coeffs = new Vec<BigInteger>();
126 Scanner stk = new Scanner(line)
127 .useDelimiter("\\s*\\*\\s*|\\s*\\+\\s*|\\s+");
128 while (stk.hasNext()) {
129 String token = stk.next();
130 if (">=".equals(token) || "<=".equals(token) || "=".equals(token)) {
131 assert stk.hasNext();
132 String tok = stk.next();
133
134 if (tok.startsWith("+")) {
135 tok = tok.substring(1);
136 }
137 BigInteger d = new BigInteger(tok);
138
139 try {
140 if (">=".equals(token) || "=".equals(token)) {
141 this.solver.addPseudoBoolean(lits, coeffs, true, d);
142 }
143 if ("<=".equals(token) || "=".equals(token)) {
144 this.solver.addPseudoBoolean(lits, coeffs, false, d);
145 }
146 } catch (ContradictionException ce) {
147 throw ce;
148 }
149 } else {
150
151
152 if ("+".equals(token)) {
153 assert stk.hasNext();
154 token = stk.next();
155 } else if ("-".equals(token)) {
156 assert stk.hasNext();
157 token = token + stk.next();
158 }
159 BigInteger coef;
160
161 try {
162
163 if (token.startsWith("+")) {
164 token = token.substring(1);
165 }
166 coef = new BigInteger(token);
167 assert stk.hasNext();
168 token = stk.next();
169 } catch (NumberFormatException nfe) {
170
171 coef = BigInteger.ONE;
172 }
173 if ("-".equals(token) || "~".equals(token)) {
174 assert stk.hasNext();
175 token = token + stk.next();
176 }
177 boolean negative = false;
178 if (token.startsWith("+")) {
179 token = token.substring(1);
180 } else if (token.startsWith("-")) {
181 token = token.substring(1);
182 assert coef.equals(BigInteger.ONE);
183 coef = BigInteger.ONE.negate();
184 } else if (token.startsWith("~")) {
185 token = token.substring(1);
186 negative = true;
187 }
188 Integer id = this.map.get(token);
189 if (id == null) {
190 id = this.decode.size() + 1;
191 this.map.put(token, id);
192 this.decode.push(token);
193 }
194 coeffs.push(coef);
195 int lid = (negative ? -1 : 1) * id.intValue();
196 lits.push(lid);
197 assert coeffs.size() == lits.size();
198 }
199 }
200 }
201
202 @Override
203 public String decode(int[] model) {
204 StringBuffer stb = new StringBuffer();
205 for (int i = 0; i < model.length; i++) {
206 if (model[i] < 0) {
207 stb.append("-");
208 stb.append(this.decode.get(-model[i] - 1));
209 } else {
210 stb.append(this.decode.get(model[i] - 1));
211 }
212 stb.append(" ");
213 }
214 return stb.toString();
215 }
216
217 @Override
218 public void decode(int[] model, PrintWriter out) {
219 for (int i = 0; i < model.length; i++) {
220 if (model[i] < 0) {
221 out.print("-");
222 out.print(this.decode.get(-model[i] - 1));
223 } else {
224 out.print(this.decode.get(model[i] - 1));
225 }
226 out.print(" ");
227 }
228 }
229
230 @Override
231 public IProblem parseInstance(final InputStream in)
232 throws ParseFormatException, ContradictionException, IOException {
233 return parseInstance(new InputStreamReader(in));
234 }
235 }