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;
29  
30  import java.math.BigInteger;
31  
32  import org.sat4j.core.VecInt;
33  import org.sat4j.specs.ContradictionException;
34  import org.sat4j.specs.IConstr;
35  import org.sat4j.specs.IOptimizationProblem;
36  import org.sat4j.specs.IVecInt;
37  import org.sat4j.specs.TimeoutException;
38  
39  /**
40   * A decorator that computes minimal pseudo boolean models.
41   * 
42   * @author daniel
43   * 
44   */
45  public class PseudoOptDecorator extends PBSolverDecorator implements
46  		IOptimizationProblem {
47  
48  	/**
49       * 
50       */
51  	private static final long serialVersionUID = 1L;
52  
53  	private BigInteger objectiveValue;
54  
55  	private int[] prevmodel;
56  	private int[] prevmodelwithadditionalvars;
57  
58  	private boolean[] prevfullmodel;
59  
60  	private IConstr previousPBConstr;
61  
62  	private boolean isSolutionOptimal;
63  
64  	public PseudoOptDecorator(IPBSolver solver) {
65  		super(solver);
66  	}
67  
68  	@Override
69  	public boolean isSatisfiable() throws TimeoutException {
70  		return isSatisfiable(VecInt.EMPTY);
71  	}
72  
73  	@Override
74  	public boolean isSatisfiable(boolean global) throws TimeoutException {
75  		return isSatisfiable(VecInt.EMPTY, global);
76  	}
77  
78  	@Override
79  	public boolean isSatisfiable(IVecInt assumps, boolean global)
80  			throws TimeoutException {
81  		boolean result = super.isSatisfiable(assumps, true);
82  		if (result) {
83  			prevmodel = super.model();
84  			prevmodelwithadditionalvars = super.modelWithInternalVariables();
85  			prevfullmodel = new boolean[nVars()];
86  			for (int i = 0; i < nVars(); i++) {
87  				prevfullmodel[i] = decorated().model(i + 1);
88  			}
89  		} else {
90  			if (previousPBConstr != null) {
91  				decorated().removeConstr(previousPBConstr);
92  				previousPBConstr = null;
93  			}
94  		}
95  		return result;
96  	}
97  
98  	@Override
99  	public boolean isSatisfiable(IVecInt assumps) throws TimeoutException {
100 		return isSatisfiable(assumps, true);
101 	}
102 
103 	@Override
104 	public void setObjectiveFunction(ObjectiveFunction objf) {
105 		decorated().setObjectiveFunction(objf);
106 	}
107 
108 	public boolean admitABetterSolution() throws TimeoutException {
109 		return admitABetterSolution(VecInt.EMPTY);
110 	}
111 
112 	public boolean admitABetterSolution(IVecInt assumps)
113 			throws TimeoutException {
114 		try {
115 			isSolutionOptimal = false;
116 			boolean result = super.isSatisfiable(assumps, true);
117 			if (result) {
118 				prevmodel = super.model();
119 				prevmodelwithadditionalvars = super
120 						.modelWithInternalVariables();
121 				prevfullmodel = new boolean[nVars()];
122 				for (int i = 0; i < nVars(); i++) {
123 					prevfullmodel[i] = decorated().model(i + 1);
124 				}
125 				if (decorated().getObjectiveFunction() != null) {
126 					calculateObjective();
127 				}
128 			} else {
129 				isSolutionOptimal = true;
130 				if (previousPBConstr != null) {
131 					decorated().removeConstr(previousPBConstr);
132 					previousPBConstr = null;
133 				}
134 			}
135 			return result;
136 		} catch (TimeoutException te) {
137 			if (previousPBConstr != null) {
138 				decorated().removeConstr(previousPBConstr);
139 				previousPBConstr = null;
140 			}
141 			throw te;
142 		}
143 	}
144 
145 	public boolean hasNoObjectiveFunction() {
146 		return decorated().getObjectiveFunction() == null;
147 	}
148 
149 	public boolean nonOptimalMeansSatisfiable() {
150 		return true;
151 	}
152 
153 	public Number calculateObjective() {
154 		if (decorated().getObjectiveFunction() == null) {
155 			throw new UnsupportedOperationException(
156 					"The problem does not contain an objective function");
157 		}
158 		objectiveValue = decorated().getObjectiveFunction().calculateDegree(
159 				decorated());
160 		return getObjectiveValue();
161 	}
162 
163 	public void discardCurrentSolution() throws ContradictionException {
164 		if (previousPBConstr != null) {
165 			super.removeSubsumedConstr(previousPBConstr);
166 		}
167 		if (decorated().getObjectiveFunction() != null
168 				&& objectiveValue != null) {
169 			previousPBConstr = super.addPseudoBoolean(decorated()
170 					.getObjectiveFunction().getVars(), decorated()
171 					.getObjectiveFunction().getCoeffs(), false, objectiveValue
172 					.subtract(BigInteger.ONE));
173 		}
174 	}
175 
176 	@Override
177 	public void reset() {
178 		previousPBConstr = null;
179 		super.reset();
180 	}
181 
182 	@Override
183 	public int[] model() {
184 		// DLB findbugs ok
185 		return prevmodel;
186 	}
187 
188 	@Override
189 	public boolean model(int var) {
190 		return prevfullmodel[var - 1];
191 	}
192 
193 	@Override
194 	public String toString(String prefix) {
195 		return prefix + "Pseudo Boolean Optimization by upper bound\n"
196 				+ super.toString(prefix);
197 	}
198 
199 	public Number getObjectiveValue() {
200 		return objectiveValue.add(decorated().getObjectiveFunction()
201 				.getCorrection());
202 	}
203 
204 	public void discard() throws ContradictionException {
205 		discardCurrentSolution();
206 	}
207 
208 	public void forceObjectiveValueTo(Number forcedValue)
209 			throws ContradictionException {
210 		super.addPseudoBoolean(decorated().getObjectiveFunction().getVars(),
211 				decorated().getObjectiveFunction().getCoeffs(), false,
212 				(BigInteger) forcedValue);
213 	}
214 
215 	public boolean isOptimal() {
216 		return isSolutionOptimal;
217 	}
218 
219 	@Override
220 	public int[] modelWithInternalVariables() {
221 		return prevmodelwithadditionalvars;
222 	}
223 }