1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  package org.sat4j.sat;
20  
21  import java.io.FileNotFoundException;
22  import java.io.IOException;
23  import java.lang.reflect.Method;
24  import java.util.Properties;
25  import java.util.StringTokenizer;
26  
27  import org.apache.commons.beanutils.BeanUtils;
28  import org.apache.commons.cli.CommandLine;
29  import org.apache.commons.cli.HelpFormatter;
30  import org.apache.commons.cli.Option;
31  import org.apache.commons.cli.Options;
32  import org.apache.commons.cli.ParseException;
33  import org.apache.commons.cli.PosixParser;
34  import org.sat4j.AbstractLauncher;
35  import org.sat4j.Messages;
36  import org.sat4j.core.ASolverFactory;
37  import org.sat4j.core.VecInt;
38  import org.sat4j.minisat.constraints.MixedDataStructureDanielWL;
39  import org.sat4j.minisat.core.DataStructureFactory;
40  import org.sat4j.minisat.core.DotSearchListener;
41  import org.sat4j.minisat.core.IOrder;
42  import org.sat4j.minisat.core.LearningStrategy;
43  import org.sat4j.minisat.core.RestartStrategy;
44  import org.sat4j.minisat.core.SearchParams;
45  import org.sat4j.minisat.core.Solver;
46  import org.sat4j.minisat.learning.PercentLengthLearning;
47  import org.sat4j.minisat.orders.VarOrderHeap;
48  import org.sat4j.minisat.restarts.MiniSATRestarts;
49  import org.sat4j.minisat.uip.FirstUIP;
50  import org.sat4j.reader.InstanceReader;
51  import org.sat4j.reader.ParseFormatException;
52  import org.sat4j.reader.Reader;
53  import org.sat4j.specs.ContradictionException;
54  import org.sat4j.specs.IProblem;
55  import org.sat4j.specs.ISolver;
56  import org.sat4j.specs.IVecInt;
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  public class Lanceur extends AbstractLauncher {
73  
74  	
75  
76  
77  	private static final long serialVersionUID = 1L;
78  
79  	
80  
81  
82  
83  
84  
85  
86  	public static void main(final String[] args) {
87  		AbstractLauncher lanceur = new Lanceur();
88  		lanceur.run(args);
89  		System.exit(lanceur.getExitCode().value());
90  	}
91  
92  	protected ASolverFactory<ISolver> factory;
93  
94  	private String filename;
95  
96  	private int k = -1;
97  
98  	@SuppressWarnings("nls")
99  	private Options createCLIOptions() {
100 		Options options = new Options();
101 
102 		options.addOption("l", "library", true,
103 				"specifies the name of the library used (minisat by default)");
104 		options.addOption("s", "solver", true,
105 				"specifies the name of a prebuilt solver from the library");
106 		options.addOption("S", "Solver", true,
107 				"setup a solver using a solver config string");
108 		options.addOption("t", "timeout", true,
109 				"specifies the timeout (in seconds)");
110 		options.addOption("T", "timeoutms", true,
111 				"specifies the timeout (in milliseconds)");
112 		options.addOption("C", "conflictbased", false,
113 				"conflict based timeout (for deterministic behavior)");
114 		options
115 				.addOption("d", "dot", true,
116 						"create a sat4j.dot file in current directory representing the search");
117 		options
118 				.addOption("f", "filename", true,
119 						"specifies the file to use (in conjunction with -d for instance)");
120 		options.addOption("m", "mute", false, "Set launcher in silent mode");
121 		options
122 				.addOption("k", "kleast", true,
123 						"limit the search to models having at least k variables set to false");
124 		Option op = options.getOption("l");
125 		op.setArgName("libname");
126 		op = options.getOption("s");
127 		op.setArgName("solvername");
128 		op = options.getOption("S");
129 		op.setArgName("solverStringDefinition");
130 		op = options.getOption("t");
131 		op.setArgName("number");
132 		op = options.getOption("T");
133 		op.setArgName("number");
134 		op = options.getOption("C");
135 		op.setArgName("number");
136 		op = options.getOption("k");
137 		op.setArgName("number");
138 		op = options.getOption("d");
139 		op.setArgName("filename");
140 		op = options.getOption("f");
141 		op.setArgName("filename");
142 		return options;
143 	}
144 
145 	
146 
147 
148 
149 
150 
151 
152 	@SuppressWarnings( { "nls", "unchecked" })
153 	@Override
154 	protected ISolver configureSolver(String[] args) {
155 		Options options = createCLIOptions();
156 		if (args.length == 0) {
157 			HelpFormatter helpf = new HelpFormatter();
158 			helpf.printHelp("java -jar sat4j.jar", options, true);
159 			return null;
160 		}
161 		try {
162 			CommandLine cmd = new PosixParser().parse(options, args);
163 
164 			String framework = cmd.getOptionValue("l"); 
165 			if (framework == null) { 
166 				framework = "minisat";
167 			}
168 
169 			try {
170 				Class<?> clazz = Class
171 						.forName("org.sat4j." + framework + ".SolverFactory"); 
172 				Class<?>[] params = {};
173 				Method m = clazz.getMethod("instance", params); 
174 				factory = (ASolverFactory) m.invoke(null, (Object[]) null);
175 			} catch (Exception e) { 
176 				System.err.println(Messages
177 						.getString("Lanceur.wrong.framework")); 
178 				e.printStackTrace();
179 			}
180 
181 			ISolver asolver;
182 			if (cmd.hasOption("S")) {
183 				asolver = configureFromString(cmd.getOptionValue("S"));
184 			} else {
185 				String solvername = cmd.getOptionValue("s");
186 				if (solvername == null) {
187 					asolver = factory.defaultSolver();
188 				} else {
189 					asolver = factory.createSolverByName(solvername);
190 				}
191 			}
192 			String timeout = cmd.getOptionValue("t");
193 			if (timeout == null) {
194 				timeout = cmd.getOptionValue("T");
195 				if (timeout != null) {
196 					asolver.setTimeoutMs(Long.parseLong(timeout));
197 				}
198 			} else {
199 				if (cmd.hasOption("C")) {
200 					asolver.setTimeoutOnConflicts(Integer.parseInt(timeout));
201 				} else {
202 					asolver.setTimeout(Integer.parseInt(timeout));
203 				}
204 			}
205 			filename = cmd.getOptionValue("f");
206 
207 			if (cmd.hasOption("d")) {
208 				String dotfilename = null;
209 				if (filename != null) {
210 					dotfilename = cmd.getOptionValue("d");
211 				}
212 				if (dotfilename == null) {
213 					dotfilename = "sat4j.dot";
214 				}
215 				((Solver<DataStructureFactory>) asolver)
216 						.setSearchListener(new DotSearchListener(dotfilename,null));
217 			}
218 
219 			if (cmd.hasOption("m")) {
220 				setSilent(true);
221 			}
222 
223 			if (cmd.hasOption("k")) {
224 				Integer myk = Integer.valueOf(cmd.getOptionValue("k"));
225 				if (myk != null) {
226 					k = myk.intValue();
227 				}
228 			}
229 			int others = 0;
230 			String[] rargs = cmd.getArgs();
231 			if (filename == null) {
232 				filename = rargs[others++];
233 			}
234 
235 			
236 			while (others < rargs.length) {
237 				String[] param = rargs[others].split("="); 
238 				assert param.length == 2;
239 				log("setting " + param[0] + " to " + param[1]); 
240 				try {
241 					BeanUtils.setProperty(asolver, param[0], param[1]);
242 				} catch (Exception e) {
243 					log("Cannot set parameter : " 
244 							+ args[others]);
245 				}
246 				others++;
247 			}
248 
249 			log(asolver.toString(COMMENT_PREFIX)); 
250 			return asolver;
251 		} catch (ParseException e1) {
252 			HelpFormatter helpf = new HelpFormatter();
253 			helpf.printHelp("java -jar sat4j.jar", options, true);
254 			usage();
255 		}
256 		return null;
257 	}
258 
259 	@Override
260 	protected Reader createReader(ISolver theSolver, String problemname) {
261 		return new InstanceReader(theSolver);
262 	}
263 
264 	@Override
265 	public void displayLicense() {
266 		super.displayLicense();
267 		log("This software uses some libraries from the Jakarta Commons project. See jakarta.apache.org for details."); 
268 	}
269 
270 	@Override
271 	public void usage() {
272 		showAvailableSolvers(factory);
273 	}
274 
275 	@Override
276 	protected String getInstanceName(String[] args) {
277 		return filename;
278 	}
279 
280 	@SuppressWarnings("unchecked")
281 	private final ISolver configureFromString(String solverconfig) {
282 		
283 		
284 		StringTokenizer stk = new StringTokenizer(solverconfig, ",");
285 		Properties pf = new Properties();
286 		String token;
287 		String[] couple;
288 		while (stk.hasMoreElements()) {
289 			token = stk.nextToken();
290 			couple = token.split("=");
291 			pf.setProperty(couple[0], couple[1]);
292 		}
293 		DataStructureFactory dsf = setupObject("DSF", pf,
294 				new MixedDataStructureDanielWL());
295 		LearningStrategy learning = setupObject("LEARNING", pf,
296 				new PercentLengthLearning());
297 		IOrder order = setupObject("ORDER", pf, new VarOrderHeap());
298 		RestartStrategy restarter = setupObject("RESTARTS", pf,
299 				new MiniSATRestarts());
300 		Solver theSolver = new Solver(new FirstUIP(), learning, dsf, order,
301 				restarter);
302 		learning.setSolver(theSolver);
303 		theSolver.setSimplifier(pf.getProperty("SIMP", "NO_SIMPLIFICATION"));
304 		SearchParams params = setupObject("PARAMS", pf, new SearchParams());
305 		theSolver.setSearchParams(params);
306 		return theSolver;
307 	}
308 
309 	@SuppressWarnings("unchecked")
310 	private final <T> T setupObject(String component, Properties pf,
311 			T defaultcomp) {
312 		try {
313 			String configline = pf.getProperty(component);
314 			if (configline == null) {
315 				log("using default component " + defaultcomp + " for "
316 						+ component);
317 				return defaultcomp;
318 			}
319 			log("configuring " + component);
320 			String[] config = configline.split("/");
321 			T comp = (T) Class.forName(config[0]).newInstance();
322 			for (int i = 1; i < config.length; i++) {
323 				String[] param = config[i].split(":"); 
324 				assert param.length == 2;
325 				try {
326 					
327 					BeanUtils.getProperty(comp, param[0]);
328 					BeanUtils.setProperty(comp, param[0], param[1]);
329 				} catch (Exception e) {
330 					log("Problem with component " + config[0] + " " + e);
331 				}
332 			}
333 			return comp;
334 		} catch (InstantiationException e) {
335 			log("Problem with component " + component + " " + e);
336 		} catch (IllegalAccessException e) {
337 			log("Problem with component " + component + " " + e);
338 		} catch (ClassNotFoundException e) {
339 			log("Problem with component " + component + " " + e);
340 		}
341 		log("using default component " + defaultcomp + " for " + component);
342 		return defaultcomp;
343 	}
344 
345 	@Override
346 	protected IProblem readProblem(String problemname)
347 			throws FileNotFoundException, ParseFormatException, IOException,
348 			ContradictionException {
349 		ISolver theSolver = (ISolver) super.readProblem(problemname);
350 		if (k > 0) {			
351 			IVecInt literals = new VecInt();
352 			for (int i = 1; i <= theSolver.nVars(); i++) {
353 				literals.push(-i);
354 			}
355 			theSolver.addAtLeast(literals, k);
356 			log("Limiting solutions to those having at least "+k+" variables assigned to false");
357 		}
358 		return theSolver;
359 	}
360 }