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 original MiniSat specification from:
20  * 
21  * An extensible SAT solver. Niklas Een and Niklas Sorensson. Proceedings of the
22  * Sixth International Conference on Theory and Applications of Satisfiability
23  * Testing, LNCS 2919, pp 502-518, 2003.
24  *
25  * See www.minisat.se for the original solver in C++.
26  * 
27  *******************************************************************************/
28  package org.sat4j.minisat.orders;
29  
30  import static org.sat4j.core.LiteralsUtils.neg;
31  import static org.sat4j.core.LiteralsUtils.var;
32  
33  import java.io.PrintWriter;
34  import java.io.Serializable;
35  
36  import org.sat4j.minisat.core.ILits;
37  import org.sat4j.minisat.core.IOrder;
38  import org.sat4j.minisat.core.IPhaseSelectionStrategy;
39  
40  /*
41   * Created on 16 oct. 2003
42   */
43  
44  /**
45   * @author leberre Heuristique du prouveur. Changement par rapport au MiniSAT
46   *         original : la gestion activity est faite ici et non plus dans Solver.
47   */
48  public class VarOrder<L extends ILits> implements Serializable, IOrder<L> {
49  
50      private static final long serialVersionUID = 1L;
51  
52      /**
53       * Comparateur permettant de trier les variables
54       */
55      private static final double VAR_RESCALE_FACTOR = 1e-100;
56  
57      private static final double VAR_RESCALE_BOUND = 1 / VAR_RESCALE_FACTOR;
58  
59      /**
60       * mesure heuristique de l'activite d'une variable.
61       */
62      protected double[] activity = new double[1];
63  
64      /**
65       * Derniere variable choisie
66       */
67      protected int lastVar = 1;
68  
69      /**
70       * Ordre des variables
71       */
72      protected int[] order = new int[1];
73  
74      private double varDecay = 1.0;
75  
76      /**
77       * increment pour l'activite des variables.
78       */
79      private double varInc = 1.0;
80  
81      /**
82       * position des variables
83       */
84      protected int[] varpos = new int[1];
85  
86      protected L lits;
87  
88      private long nullchoice = 0;
89  
90      protected IPhaseSelectionStrategy phaseStrategy;
91      
92      public VarOrder() {
93          this(new PhaseInLastLearnedClauseSelectionStrategy());
94      }
95      
96      public VarOrder(IPhaseSelectionStrategy strategy) {
97          this.phaseStrategy = strategy;
98      }
99      
100     /**
101      * Change the selection strategy.
102      * 
103      * @param strategy
104      */
105     public void setPhaseSelectionStrategy(IPhaseSelectionStrategy strategy) {
106         phaseStrategy = strategy;
107     }
108     
109     public IPhaseSelectionStrategy getPhaseSelectionStrategy() {
110         return phaseStrategy;
111     }
112     
113     /*
114      * (non-Javadoc)
115      * 
116      * @see org.sat4j.minisat.core.IOrder#setLits(org.sat4j.minisat.core.ILits)
117      */
118     public void setLits(L lits) {
119         this.lits = lits;
120     }
121 
122     /*
123      * (non-Javadoc)
124      * 
125      * @see org.sat4j.minisat.core.IOrder#select()
126      */
127     public int select() {
128         assert lastVar > 0;
129         for (int i = lastVar; i < order.length; i++) {
130             assert i > 0;
131             if (lits.isUnassigned(order[i])) {
132                 lastVar = i;
133                 if (activity[i] < 0.0001) {
134                     // if (rand.nextDouble() <= RANDOM_WALK) {
135                     // int randomchoice = rand.nextInt(order.length - i) + i;
136                     // assert randomchoice >= i;
137                     // if ((randomchoice > i)
138                     // && lits.isUnassigned(order[randomchoice])) {
139                     // randchoice++;
140                     // return order[randomchoice];
141                     // }
142                     // }
143                     nullchoice++;
144                 }
145                 return order[i];
146             }
147         }
148         return ILits.UNDEFINED;
149     }
150 
151     /**
152      * Change la valeur de varDecay.
153      * 
154      * @param d
155      *            la nouvelle valeur de varDecay
156      */
157     public void setVarDecay(double d) {
158         varDecay = d;
159     }
160 
161     /*
162      * (non-Javadoc)
163      * 
164      * @see org.sat4j.minisat.core.IOrder#undo(int)
165      */
166     public void undo(int x) {
167         assert x > 0;
168         assert x < order.length;
169         int pos = varpos[x];
170         if (pos < lastVar) {
171             lastVar = pos;
172         }
173         assert lastVar > 0;
174     }
175 
176     /*
177      * (non-Javadoc)
178      * 
179      * @see org.sat4j.minisat.core.IOrder#updateVar(int)
180      */
181     public void updateVar(int p) {
182         assert p > 1;
183         final int var = var(p);
184 
185         updateActivity(var);
186         int i = varpos[var];
187         for (; i > 1 // because there is nothing at i=0
188                 && (activity[var(order[i - 1])] < activity[var]); i--) {
189             assert i > 1;
190             // echange p avec son predecesseur
191             final int orderpm1 = order[i - 1];
192             assert varpos[var(orderpm1)] == i - 1;
193             varpos[var(orderpm1)] = i;
194             order[i] = orderpm1;
195         }
196         assert i >= 1;
197         varpos[var] = i;
198         order[i] = p;
199 
200         if (i < lastVar) {
201             lastVar = i;
202         }
203     }
204 
205     protected void updateActivity(final int var) {
206         if ((activity[var] += varInc) > VAR_RESCALE_BOUND) {
207             varRescaleActivity();
208         }
209     }
210 
211     /**
212      * 
213      */
214     public void varDecayActivity() {
215         varInc *= varDecay;
216     }
217 
218     /**
219      * 
220      */
221     private void varRescaleActivity() {
222         for (int i = 1; i < activity.length; i++) {
223             activity[i] *= VAR_RESCALE_FACTOR;
224         }
225         varInc *= VAR_RESCALE_FACTOR;
226     }
227 
228     public double varActivity(int p) {
229         return activity[var(p)];
230     }
231 
232     /**
233      * 
234      */
235     public int numberOfInterestingVariables() {
236         int cpt = 0;
237         for (int i = 1; i < activity.length; i++) {
238             if (activity[i] > 1.0) {
239                 cpt++;
240             }
241         }
242         return cpt;
243     }
244 
245     /*
246      * (non-Javadoc)
247      * 
248      * @see org.sat4j.minisat.core.IOrder#init()
249      */
250     public void init() {
251         int nlength = lits.nVars() + 1;
252         int reallength = lits.realnVars() + 1;
253         int[] nvarpos = new int[nlength];
254         double[] nactivity = new double[nlength];
255         int[] norder = new int[reallength];
256         nvarpos[0] = -1;
257         nactivity[0] = -1;
258         norder[0] = ILits.UNDEFINED;
259         for (int i = 1, j = 1; i < nlength; i++) {
260             assert i > 0;
261             assert i <= lits.nVars() : "" + lits.nVars() + "/" + i; //$NON-NLS-1$ //$NON-NLS-2$
262             if (lits.belongsToPool(i)) {
263                 norder[j] = neg(lits.getFromPool(i)); // Looks a
264                 // promising
265                 // approach
266                 nvarpos[i] = j++;
267             }
268             nactivity[i] = 0.0;
269         }
270         varpos = nvarpos;
271         activity = nactivity;
272         order = norder;
273         lastVar = 1;
274     }
275 
276     /**
277      * Affiche les litteraux dans l'ordre de l'heuristique, la valeur de
278      * l'activite entre ().
279      * 
280      * @return les litteraux dans l'ordre courant.
281      */
282     @Override
283     public String toString() {
284         return "VSIDS like heuristics from MiniSAT using a sorted array"; //$NON-NLS-1$
285     }
286 
287     public ILits getVocabulary() {
288         return lits;
289     }
290 
291     /*
292      * (non-Javadoc)
293      * 
294      * @see org.sat4j.minisat.core.IOrder#printStat(java.io.PrintStream,
295      *      java.lang.String)
296      */
297     public void printStat(PrintWriter out, String prefix) {
298         out.println(prefix + "non guided choices\t" + nullchoice); //$NON-NLS-1$
299         // out.println(prefix + "random choices\t" + randchoice);
300     }
301 
302     public void assignLiteral(int p) {
303         // do nothing       
304     }
305 
306 }