View Javadoc

1   /*******************************************************************************
2    * SAT4J: a SATisfiability library for Java Copyright (C) 2004, 2012 Artois University and CNRS
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   * Contributors:
28   *   CRIL - initial API and implementation
29   *******************************************************************************/
30  package org.sat4j.minisat.orders;
31  
32  import static org.sat4j.core.LiteralsUtils.var;
33  
34  import java.io.PrintWriter;
35  import java.io.Serializable;
36  
37  import org.sat4j.minisat.core.Heap;
38  import org.sat4j.minisat.core.ILits;
39  import org.sat4j.minisat.core.IOrder;
40  import org.sat4j.minisat.core.IPhaseSelectionStrategy;
41  
42  /*
43   * Created on 16 oct. 2003
44   */
45  
46  /**
47   * @author leberre Heuristique du prouveur. Changement par rapport au MiniSAT
48   *         original : la gestion activity est faite ici et non plus dans Solver.
49   */
50  public class VarOrderHeap implements IOrder, Serializable {
51  
52      private static final long serialVersionUID = 1L;
53  
54      private static final double VAR_RESCALE_FACTOR = 1e-100;
55  
56      private static final double VAR_RESCALE_BOUND = 1 / VAR_RESCALE_FACTOR;
57  
58      /**
59       * mesure heuristique de l'activite d'une variable.
60       */
61      protected double[] activity = new double[1];
62  
63      private double varDecay = 1.0;
64  
65      /**
66       * increment pour l'activite des variables.
67       */
68      private double varInc = 1.0;
69  
70      protected ILits lits;
71  
72      private long nullchoice = 0;
73  
74      protected Heap heap;
75  
76      protected IPhaseSelectionStrategy phaseStrategy;
77  
78      public VarOrderHeap() {
79          this(new PhaseInLastLearnedClauseSelectionStrategy());
80      }
81  
82      public VarOrderHeap(IPhaseSelectionStrategy strategy) {
83          this.phaseStrategy = strategy;
84      }
85  
86      /**
87       * Change the selection strategy.
88       * 
89       * @param strategy
90       */
91      public void setPhaseSelectionStrategy(IPhaseSelectionStrategy strategy) {
92          this.phaseStrategy = strategy;
93      }
94  
95      public IPhaseSelectionStrategy getPhaseSelectionStrategy() {
96          return this.phaseStrategy;
97      }
98  
99      public void setLits(ILits lits) {
100         this.lits = lits;
101     }
102 
103     /**
104      * Selectionne une nouvelle variable, non affectee, ayant l'activite la plus
105      * elevee.
106      * 
107      * @return Lit.UNDEFINED si aucune variable n'est trouvee
108      */
109     public int select() {
110         while (!this.heap.empty()) {
111             int var = this.heap.getmin();
112             int next = this.phaseStrategy.select(var);
113             if (this.lits.isUnassigned(next)) {
114                 if (this.activity[var] < 0.0001) {
115                     this.nullchoice++;
116                 }
117                 return next;
118             }
119         }
120         return ILits.UNDEFINED;
121     }
122 
123     /**
124      * Change la valeur de varDecay.
125      * 
126      * @param d
127      *            la nouvelle valeur de varDecay
128      */
129     public void setVarDecay(double d) {
130         this.varDecay = d;
131     }
132 
133     /**
134      * Methode appelee quand la variable x est desaffectee.
135      * 
136      * @param x
137      */
138     public void undo(int x) {
139         if (!this.heap.inHeap(x)) {
140             this.heap.insert(x);
141         }
142     }
143 
144     /**
145      * Appelee lorsque l'activite de la variable x a change.
146      * 
147      * @param p
148      *            a literal
149      */
150     public void updateVar(int p) {
151         int var = var(p);
152         updateActivity(var);
153         this.phaseStrategy.updateVar(p);
154         if (this.heap.inHeap(var)) {
155             this.heap.increase(var);
156         }
157     }
158 
159     protected void updateActivity(final int var) {
160         if ((this.activity[var] += this.varInc) > VAR_RESCALE_BOUND) {
161             varRescaleActivity();
162         }
163     }
164 
165     /**
166      * 
167      */
168     public void varDecayActivity() {
169         this.varInc *= this.varDecay;
170     }
171 
172     /**
173      * 
174      */
175     private void varRescaleActivity() {
176         for (int i = 1; i < this.activity.length; i++) {
177             this.activity[i] *= VAR_RESCALE_FACTOR;
178         }
179         this.varInc *= VAR_RESCALE_FACTOR;
180     }
181 
182     public double varActivity(int p) {
183         return this.activity[var(p)];
184     }
185 
186     /**
187      * 
188      */
189     public int numberOfInterestingVariables() {
190         int cpt = 0;
191         for (int i = 1; i < this.activity.length; i++) {
192             if (this.activity[i] > 1.0) {
193                 cpt++;
194             }
195         }
196         return cpt;
197     }
198 
199     /**
200      * that method has the responsability to initialize all arrays in the
201      * heuristics. PLEASE CALL super.init() IF YOU OVERRIDE THAT METHOD.
202      */
203     public void init() {
204         int nlength = this.lits.nVars() + 1;
205         if (this.activity == null || this.activity.length < nlength) {
206             this.activity = new double[nlength];
207         }
208         this.phaseStrategy.init(nlength);
209         this.activity[0] = -1;
210         this.heap = new Heap(this.activity);
211         this.heap.setBounds(nlength);
212         for (int i = 1; i < nlength; i++) {
213             assert i > 0;
214             assert i <= this.lits.nVars() : "" + this.lits.nVars() + "/" + i; //$NON-NLS-1$ //$NON-NLS-2$
215             this.activity[i] = 0.0;
216             if (this.lits.belongsToPool(i)) {
217                 this.heap.insert(i);
218             }
219         }
220     }
221 
222     @Override
223     public String toString() {
224         return "VSIDS like heuristics from MiniSAT using a heap " + this.phaseStrategy; //$NON-NLS-1$
225     }
226 
227     public ILits getVocabulary() {
228         return this.lits;
229     }
230 
231     public void printStat(PrintWriter out, String prefix) {
232         out.println(prefix + "non guided choices\t" + this.nullchoice); //$NON-NLS-1$
233     }
234 
235     public void assignLiteral(int p) {
236         this.phaseStrategy.assignLiteral(p);
237     }
238 
239     public void updateVarAtDecisionLevel(int q) {
240         this.phaseStrategy.updateVarAtDecisionLevel(q);
241 
242     }
243 
244     public double[] getVariableHeuristics() {
245         return this.activity;
246     }
247 }