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  package org.sat4j.maxsat;
20  
21  import java.math.BigInteger;
22  
23  import org.sat4j.core.Vec;
24  import org.sat4j.core.VecInt;
25  import org.sat4j.pb.IPBSolver;
26  import org.sat4j.pb.PBSolverDecorator;
27  import org.sat4j.specs.ContradictionException;
28  import org.sat4j.specs.IConstr;
29  import org.sat4j.specs.IOptimizationProblem;
30  import org.sat4j.specs.IVec;
31  import org.sat4j.specs.IVecInt;
32  import org.sat4j.specs.TimeoutException;
33  
34  /**
35   * A decorator that computes minimal cost models. That problem is also known as
36   * binate covering problem.
37   * 
38   * Please make sure that newVar(howmany) is called first to setup the decorator.
39   * 
40   * @author daniel
41   * 
42   */
43  public class MinCostDecorator extends PBSolverDecorator implements
44  		IOptimizationProblem {
45  
46  	/**
47       * 
48       */
49  	private static final long serialVersionUID = 1L;
50  
51  	private int[] costs;
52  
53  	private int[] prevmodel;
54  
55  	private final IVecInt vars = new VecInt();
56  
57  	private final IVec<BigInteger> coeffs = new Vec<BigInteger>();
58  
59  	private int objectivevalue;
60  
61  	private IConstr prevConstr;
62  
63  	public MinCostDecorator(IPBSolver solver) {
64  		super(solver);
65  	}
66  
67  	/*
68  	 * (non-Javadoc)
69  	 * 
70  	 * @see org.sat4j.tools.SolverDecorator#newVar()
71  	 */
72  	@Override
73  	public int newVar() {
74  		throw new UnsupportedOperationException();
75  	}
76  
77  	/**
78  	 * Setup the number of variables to use inside the solver.
79  	 * 
80  	 * It is mandatory to call that method before setting the cost of the
81  	 * variables.
82  	 * 
83  	 * @param howmany
84  	 *            the maximum number of variables in the solver.
85  	 */
86  	@Override
87  	public int newVar(int howmany) {
88  		costs = new int[howmany + 1];
89  		// Arrays.fill(costs, 1);
90  		vars.clear();
91  		coeffs.clear();
92  		for (int i = 1; i <= howmany; i++) {
93  			vars.push(i);
94  			coeffs.push(BigInteger.ZERO);
95  		}
96  		// should the default cost be 1????
97  		// here it is 0
98  		return super.newVar(howmany);
99  	}
100 
101 	/**
102 	 * to know the cost of a given var.
103 	 * 
104 	 * @param var
105 	 *            a variable in dimacs format
106 	 * @return the cost of that variable when assigned to true
107 	 */
108 	public int costOf(int var) {
109 		return costs[var];
110 	}
111 
112 	/**
113 	 * to set the cost of a given var.
114 	 * 
115 	 * @param var
116 	 *            a variable in dimacs format
117 	 * @param cost
118 	 *            the cost of var when assigned to true
119 	 */
120 	public void setCost(int var, int cost) {
121 		costs[var] = cost;
122 		coeffs.set(var - 1, BigInteger.valueOf(cost));
123 	}
124 
125 	public boolean admitABetterSolution() throws TimeoutException {
126 		return admitABetterSolution(VecInt.EMPTY);
127 	}
128 
129 	public boolean admitABetterSolution(IVecInt assumps)
130 			throws TimeoutException {
131 		boolean result = super.isSatisfiable(assumps, true);
132 		if (result) {
133 			prevmodel = super.model();
134 			calculateObjective();
135 		}
136 		return result;
137 	}
138 
139 	public boolean hasNoObjectiveFunction() {
140 		return false;
141 	}
142 
143 	public boolean nonOptimalMeansSatisfiable() {
144 		return true;
145 	}
146 
147 	public Number calculateObjective() {
148 		objectivevalue = calculateDegree(prevmodel);
149 		return new Integer(objectivevalue);
150 	}
151 
152 	private int calculateDegree(int[] prevmodel2) {
153 		int tmpcost = 0;
154 		for (int i = 1; i < costs.length; i++) {
155 			if (prevmodel2[i - 1] > 0) {
156 				tmpcost += costs[i];
157 			}
158 		}
159 		return tmpcost;
160 	}
161 
162 	public void discardCurrentSolution() throws ContradictionException {
163 		if (prevConstr!=null) {
164 			super.removeSubsumedConstr(prevConstr);
165 		}
166 		prevConstr = super.addPseudoBoolean(vars, coeffs, false, BigInteger
167 				.valueOf(objectivevalue - 1));
168 	}
169 
170 	@Override
171 	public void reset() {
172 		prevConstr = null;
173 		super.reset();
174 	}
175 
176 	@Override
177 	public int[] model() {
178 		// DLB findbugs ok
179 		return prevmodel;
180 	}
181 
182 	public Number getObjectiveValue() {
183 		return objectivevalue;
184 	}
185 
186 	public void discard() throws ContradictionException {
187 		discardCurrentSolution();
188 	}
189 
190 	public void forceObjectiveValueTo(Number forcedValue)
191 			throws ContradictionException {
192 		super.addPseudoBoolean(vars, coeffs, false, (BigInteger)
193 				forcedValue);
194 	}
195 }