View Javadoc

1   /*******************************************************************************
2   * SAT4J: a SATisfiability library for Java Copyright (C) 2004-2008 Daniel Le Berre
3   *
4   * All rights reserved. This program and the accompanying materials
5   * are made available under the terms of the Eclipse Public License v1.0
6   * which accompanies this distribution, and is available at
7   * http://www.eclipse.org/legal/epl-v10.html
8   *
9   * Alternatively, the contents of this file may be used under the terms of
10  * either the GNU Lesser General Public License Version 2.1 or later (the
11  * "LGPL"), in which case the provisions of the LGPL are applicable instead
12  * of those above. If you wish to allow use of your version of this file only
13  * under the terms of the LGPL, and not to allow others to use your version of
14  * this file under the terms of the EPL, indicate your decision by deleting
15  * the provisions above and replace them with the notice and other provisions
16  * required by the LGPL. If you do not delete the provisions above, a recipient
17  * may use your version of this file under the terms of the EPL or the LGPL.
18  * 
19  * Based on the pseudo boolean algorithms described in:
20  * A fast pseudo-Boolean constraint solver Chai, D.; Kuehlmann, A.
21  * Computer-Aided Design of Integrated Circuits and Systems, IEEE Transactions on
22  * Volume 24, Issue 3, March 2005 Page(s): 305 - 317
23  * 
24  * and 
25  * Heidi E. Dixon, 2004. Automating Pseudo-Boolean Inference within a DPLL 
26  * Framework. Ph.D. Dissertation, University of Oregon.
27  *******************************************************************************/
28  package org.sat4j.pb.constraints.pb;
29  
30  import java.math.BigInteger;
31  
32  import org.sat4j.minisat.constraints.cnf.Lits;
33  import org.sat4j.minisat.core.VarActivityListener;
34  import org.sat4j.specs.IVec;
35  import org.sat4j.specs.IVecInt;
36  
37  /**
38   * @author parrain 
39   * 
40   */
41  public class MapPb implements IDataStructurePB {
42  
43      /*
44       * During the process of cutting planes, pseudo-boolean constraints are
45       * coded with a HashMap <literal, coefficient> and a BigInteger for the
46       * degree.
47       */
48      protected InternalMapPBStructure weightedLits;
49  
50      protected BigInteger degree;
51  
52      MapPb(PBConstr cpb) {
53          weightedLits = new InternalMapPBStructure(cpb);
54          degree = cpb.getDegree();
55      }
56  
57      MapPb(int size) {
58          weightedLits = new InternalMapPBStructure(size);
59          degree = BigInteger.ZERO;
60      }
61  
62      public boolean isCardinality(){
63          for (int i = 0; i < size(); i++)
64              if (!(weightedLits.getCoef(i).equals(BigInteger.ONE)))
65              	return false;
66          return true;
67      }
68      
69      public BigInteger saturation() {
70          assert degree.signum() > 0;
71          BigInteger minimum = degree;
72          for (int ind = 0; ind < size(); ind++) {
73              assert weightedLits.getCoef(ind).signum() > 0;
74              if (degree.compareTo(weightedLits.getCoef(ind)) < 0)
75                  changeCoef(ind, degree);
76              assert weightedLits.getCoef(ind).signum() > 0;
77              minimum = minimum.min(weightedLits.getCoef(ind));
78          }
79          // a clause has been learned
80          if (minimum.equals(degree) && minimum.compareTo(BigInteger.ONE) > 0) {
81              degree = BigInteger.ONE;
82              for (int ind = 0; ind < size(); ind++)
83                  changeCoef(ind, BigInteger.ONE);
84          }
85  
86          return degree;
87      }
88  
89      public BigInteger cuttingPlane(PBConstr cpb, BigInteger deg,
90              BigInteger[] reducedCoefs, VarActivityListener val) {
91          return cuttingPlane(cpb, deg, reducedCoefs, BigInteger.ONE, val);
92      }
93  
94      public BigInteger cuttingPlane(PBConstr cpb, BigInteger degreeCons,
95              BigInteger[] reducedCoefs, BigInteger coefMult,
96              VarActivityListener val) {
97          degree = degree.add(degreeCons);
98          assert degree.signum() > 0;
99  
100         if (reducedCoefs == null)
101             for (int i = 0; i < cpb.size(); i++) {
102                 val.varBumpActivity(cpb.get(i));
103                 cuttingPlaneStep(cpb.get(i), multiplyCoefficient(
104                         cpb.getCoef(i), coefMult));
105             }
106         else
107             for (int i = 0; i < cpb.size(); i++) {
108                 val.varBumpActivity(cpb.get(i));
109                 cuttingPlaneStep(cpb.get(i), multiplyCoefficient(
110                         reducedCoefs[i], coefMult));
111             }
112 
113         return degree;
114     }
115 
116     public BigInteger cuttingPlane(int[] lits, BigInteger[] reducedCoefs,
117             BigInteger deg) {
118         return cuttingPlane(lits, reducedCoefs, deg, BigInteger.ONE);
119     }
120 
121     public BigInteger cuttingPlane(int lits[], BigInteger[] reducedCoefs,
122             BigInteger degreeCons, BigInteger coefMult) {
123         degree = degree.add(degreeCons);
124         assert degree.signum() > 0;
125 
126         for (int i = 0; i < lits.length; i++)
127             cuttingPlaneStep(lits[i], reducedCoefs[i].multiply(coefMult));
128 
129         return degree;
130     }
131 
132     private void cuttingPlaneStep(final int lit, final BigInteger coef) {
133         assert coef.signum() >= 0;
134         int nlit = lit ^ 1;
135         if (coef.signum() > 0) {
136             if (weightedLits.containsKey(nlit)) {
137                 assert !weightedLits.containsKey(lit);
138                 assert weightedLits.get(nlit) != null;
139                 if (weightedLits.get(nlit).compareTo(coef) < 0) {
140                     BigInteger tmp = weightedLits.get(nlit);
141                     setCoef(lit, coef.subtract(tmp));
142                     assert weightedLits.get(lit).signum() > 0;
143                     degree = degree.subtract(tmp);
144                     removeCoef(nlit);
145                 } else {
146                     if (weightedLits.get(nlit).equals(coef)) {
147                         degree = degree.subtract(coef);
148                         removeCoef(nlit);
149                     } else {
150                         decreaseCoef(nlit, coef);
151                         assert weightedLits.get(nlit).signum() > 0;
152                         degree = degree.subtract(coef);
153                     }
154                 }
155             } else {
156                 assert (!weightedLits.containsKey(lit))
157                         || (weightedLits.get(lit).signum() > 0);
158                 if (weightedLits.containsKey(lit))
159                     increaseCoef(lit, coef);
160                 else 
161                     setCoef(lit, coef);
162                 assert weightedLits.get(lit).signum() > 0;
163             }
164         }
165         assert (!weightedLits.containsKey(nlit)) || (!weightedLits.containsKey(lit));
166     }
167 
168     public void buildConstraintFromConflict(IVecInt resLits,
169             IVec<BigInteger> resCoefs) {
170         resLits.clear();
171         resCoefs.clear();
172         weightedLits.copyCoefs(resCoefs);
173         weightedLits.copyLits(resLits);
174     };
175 
176     public void buildConstraintFromMapPb(int[] resLits, BigInteger[] resCoefs) {
177         // On recherche tous les litt?raux concern?s
178         assert resLits.length == resCoefs.length;
179         assert resLits.length == size();
180         weightedLits.copyCoefs(resCoefs);
181         weightedLits.copyLits(resLits);
182     };
183 
184     public BigInteger getDegree() {
185         return degree;
186     }
187 
188     public int size() {
189         return weightedLits.size();
190     }
191 
192     /*
193      * (non-Javadoc)
194      * 
195      * @see java.lang.Object#toString()
196      */
197     @Override
198     public String toString() {
199         StringBuffer stb = new StringBuffer();
200         for (int ind = 0; ind < size(); ind++) {
201             stb.append(weightedLits.getCoef(ind));
202             stb.append(".");
203             stb.append(Lits.toString(weightedLits.getLit(ind)));
204             stb.append(" ");
205         }
206         return stb.toString() + " >= " + degree; //$NON-NLS-1$
207     }
208 
209     private BigInteger multiplyCoefficient(BigInteger coef, BigInteger mult) {
210         if (coef.equals(BigInteger.ONE))
211             return mult;
212         return coef.multiply(mult);
213     }
214 
215     void increaseCoef(int lit, BigInteger incCoef) {
216         weightedLits.put(lit, weightedLits.get(lit).add(incCoef));
217     }
218 
219     void decreaseCoef(int lit, BigInteger decCoef) {
220         weightedLits.put(lit, weightedLits.get(lit).subtract(decCoef));
221     }
222 
223     void setCoef(int lit, BigInteger newValue) {
224         weightedLits.put(lit, newValue);
225     }
226 
227     void changeCoef(int indLit, BigInteger newValue) {
228         weightedLits.changeCoef(indLit, newValue);
229     }
230 
231     void removeCoef(int lit) {
232         weightedLits.remove(lit);
233     }
234 
235 }