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  
29  package org.sat4j.tools.encoding;
30  
31  import org.sat4j.core.ConstrGroup;
32  import org.sat4j.core.VecInt;
33  import org.sat4j.specs.ContradictionException;
34  import org.sat4j.specs.IConstr;
35  import org.sat4j.specs.ISolver;
36  import org.sat4j.specs.IVecInt;
37  
38  /**
39   * For the cases "at most one" and "exactly one", we can use the ladder encoding
40   * described in: I. P. Gent and P. Nightingale,
41   * "A new encoding for AllDifferent into SAT", in International Workshop on
42   * Modeling and Reformulating Constraint Satisfaction Problems, 2004
43   * 
44   * @author sroussel
45   * @since 2.3.1
46   */
47  public class Ladder extends EncodingStrategyAdapter {
48  
49  	@Override
50  	/**
51  	 * If n is the number of variables in the constraint, 
52  	 * this encoding adds n variables and 4n clauses 
53  	 * (3n+1 size 2 clauses and n-1 size 3 clauses)
54  	 */
55  	public IConstr addAtMostOne(ISolver solver, IVecInt literals)
56  			throws ContradictionException {
57  		ConstrGroup group = new ConstrGroup(false);
58  		final int n = literals.size() + 1;
59  
60  		int xN = solver.nextFreeVarId(true);
61  		int y[] = new int[n - 1];
62  
63  		for (int i = 0; i < n - 1; i++) {
64  			y[i] = solver.nextFreeVarId(true);
65  		}
66  
67  		IVecInt clause = new VecInt();
68  
69  		// Constraint \bigwedge_{i=1}{n-2} (\neg y_{i+1} \vee y_i)
70  		for (int i = 1; i <= n - 2; i++) {
71  			clause.push(-y[i]);
72  			clause.push(y[i - 1]);
73  			group.add(solver.addClause(clause));
74  			clause.clear();
75  		}
76  
77  		// Constraint \bigwedge_{i=2}{n-1} (\neg y_{i-1} \vee y_i \vee x_i)
78  		for (int i = 2; i <= n - 1; i++) {
79  			clause.push(-y[i - 2]);
80  			clause.push(y[i - 1]);
81  			clause.push(literals.get(i - 1));
82  			group.add(solver.addClause(clause));
83  			clause.clear();
84  		}
85  
86  		// Constraint \bigwedge_{i=2}{n-1} (\neg x_i \vee y_{i-1)})
87  		for (int i = 2; i <= n - 1; i++) {
88  			clause.push(-literals.get(i - 1));
89  			clause.push(y[i - 2]);
90  			group.add(solver.addClause(clause));
91  			clause.clear();
92  		}
93  
94  		// Constraint \bigwedge_{i=2}{n-1} (\neg x_i \vee \neg y_i)
95  		for (int i = 2; i <= n - 1; i++) {
96  			clause.push(-literals.get(i - 1));
97  			clause.push(-y[i - 1]);
98  			group.add(solver.addClause(clause));
99  			clause.clear();
100 		}
101 
102 		// Constraint y_1 \vee x_1
103 		clause.push(y[0]);
104 		clause.push(literals.get(0));
105 		group.add(solver.addClause(clause));
106 		clause.clear();
107 
108 		// Constraint \neg y_1 \vee \neg x_1
109 		clause.push(-y[0]);
110 		clause.push(-literals.get(0));
111 		group.add(solver.addClause(clause));
112 		clause.clear();
113 
114 		// Constraint \neg y_{n-1} \vee x_n
115 		clause.push(-y[n - 2]);
116 		clause.push(xN);
117 		group.add(solver.addClause(clause));
118 		clause.clear();
119 
120 		// Constraint y_{n-1} \vee \neg x_n
121 		clause.push(y[n - 2]);
122 		clause.push(-xN);
123 		group.add(solver.addClause(clause));
124 		clause.clear();
125 
126 		return group;
127 	}
128 
129 	@Override
130 	/**
131 	 * If n is the number of variables in the constraint, 
132 	 * this encoding adds n-1 variables and 4(n-1) clauses 
133 	 * (3n-2 size 2 clauses and n-2 size 3 clauses)
134 	 */
135 	public IConstr addExactlyOne(ISolver solver, IVecInt literals)
136 			throws ContradictionException {
137 		ConstrGroup group = new ConstrGroup(false);
138 		final int n = literals.size();
139 
140 		int y[] = new int[n - 1];
141 
142 		for (int i = 0; i < n - 1; i++) {
143 			y[i] = solver.nextFreeVarId(true);
144 		}
145 
146 		IVecInt clause = new VecInt();
147 
148 		// Constraint \bigwedge_{i=1}{n-2} (\neg y_{i+1} \vee y_i)
149 		for (int i = 1; i <= n - 2; i++) {
150 			clause.push(-y[i]);
151 			clause.push(y[i - 1]);
152 			group.add(solver.addClause(clause));
153 			clause.clear();
154 		}
155 
156 		// Constraint \bigwedge_{i=2}{n-1} (\neg y_{i-1} \vee y_i \vee x_i)
157 		for (int i = 2; i <= n - 1; i++) {
158 			clause.push(-y[i - 2]);
159 			clause.push(y[i - 1]);
160 			clause.push(literals.get(i - 1));
161 			group.add(solver.addClause(clause));
162 			clause.clear();
163 		}
164 
165 		// Constraint \bigwedge_{i=2}{n-1} (\neg x_i \vee y_{i-1)})
166 		for (int i = 2; i <= n - 1; i++) {
167 			clause.push(-literals.get(i - 1));
168 			clause.push(y[i - 2]);
169 			group.add(solver.addClause(clause));
170 			clause.clear();
171 		}
172 
173 		// Constraint \bigwedge_{i=2}{n-1} (\neg x_i \vee \neg y_i)
174 		for (int i = 2; i <= n - 1; i++) {
175 			clause.push(-literals.get(i - 1));
176 			clause.push(-y[i - 1]);
177 			group.add(solver.addClause(clause));
178 			clause.clear();
179 		}
180 
181 		// Constraint y_1 \vee x_1
182 		clause.push(y[0]);
183 		clause.push(literals.get(0));
184 		group.add(solver.addClause(clause));
185 		clause.clear();
186 
187 		// Constraint \neg y_1 \vee \neg x_1
188 		clause.push(-y[0]);
189 		clause.push(-literals.get(0));
190 		group.add(solver.addClause(clause));
191 		clause.clear();
192 
193 		// Constraint \neg y_{n-1} \vee x_n
194 		clause.push(-y[n - 2]);
195 		clause.push(literals.get(n - 1));
196 		group.add(solver.addClause(clause));
197 		clause.clear();
198 
199 		// Constraint y_{n-1} \vee \neg x_n
200 		clause.push(y[n - 2]);
201 		clause.push(-literals.get(n - 1));
202 		group.add(solver.addClause(clause));
203 		clause.clear();
204 
205 		return group;
206 	}
207 }