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 }