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.pb.reader;
31  
32  import java.math.BigInteger;
33  import java.util.regex.Matcher;
34  import java.util.regex.Pattern;
35  
36  import org.sat4j.core.Vec;
37  import org.sat4j.core.VecInt;
38  import org.sat4j.pb.IPBSolver;
39  import org.sat4j.pb.ObjectiveFunction;
40  import org.sat4j.reader.JSONReader;
41  import org.sat4j.reader.ParseFormatException;
42  import org.sat4j.specs.ContradictionException;
43  import org.sat4j.specs.IVec;
44  import org.sat4j.specs.IVecInt;
45  
46  /**
47   * Simple JSON reader for boolean optimization problems.
48   * 
49   * The objective function is represented by an array of weighted literals.
50   * Pseudo boolean constraints are represented by an array of weighted literals
51   * of the left hand side, a comparator (a string) and an integer.
52   * <code>[['min',[[1,1],[20,2],[80,3]]],[-1,-2,-3],[[1,-2,3],'>',2],[4,-3,6],[[[1,1],[2,2],[4,3],[8,4]],'<=',6]</code>
53   * represents an optimization problem with an objective function, min: x1 + 20
54   * x2, four constraints with two clauses, a cardinality constraint and the
55   * pseudo boolean constraint 1 x1 + 2 x2 + 4 x3 + 8 x4 <= 6.
56   * 
57   * @author leberre
58   * @since 2.3.3
59   */
60  public class JSONPBReader extends JSONReader<IPBSolver> {
61  	public static final String WLITERAL = "\\[(-?\\d+),(-?\\d+)\\]";
62  	public static final String WCLAUSE = "(\\[(" + WLITERAL + "(," + WLITERAL
63  			+ ")*)?\\])";
64  	public static final String PB = "(\\[" + WCLAUSE + ",'[=<>]=?',-?\\d+\\])";
65  
66  	public static final String OBJECTIVE_FUNCTION = "(\\[('min'|'max'),"
67  			+ WCLAUSE + "\\])";
68  
69  	public static final Pattern PSEUDO_PATTERN = Pattern.compile(PB);
70  	public static final Pattern WCLAUSE_PATTERN = Pattern.compile(WCLAUSE);
71  	public static final Pattern WLITERAL_PATTERN = Pattern.compile(WLITERAL);
72  	public static final Pattern OBJECTIVE_FUNCTION_PATTERN = Pattern
73  			.compile(OBJECTIVE_FUNCTION);
74  
75  	public JSONPBReader(IPBSolver solver) {
76  		super(solver);
77  	}
78  
79  	@Override
80  	protected void handleNotHandled(String constraint)
81  			throws ParseFormatException, ContradictionException {
82  		if (PSEUDO_PATTERN.matcher(constraint).matches()) {
83  			handlePB(constraint);
84  		} else if (OBJECTIVE_FUNCTION_PATTERN.matcher(constraint).matches()) {
85  			handleObj(constraint);
86  		} else {
87  			throw new UnsupportedOperationException("Wrong formula "
88  					+ constraint);
89  		}
90  	}
91  
92  	private void handleObj(String constraint) {
93  		Matcher matcher = WCLAUSE_PATTERN.matcher(constraint);
94  		if (matcher.find()) {
95  			String weightedLiterals = matcher.group();
96  			constraint = matcher.replaceFirst("");
97  			matcher = WLITERAL_PATTERN.matcher(weightedLiterals);
98  			IVecInt literals = new VecInt();
99  			String[] pieces = constraint.split(",");
100 			boolean negate = pieces[0].contains("max");
101 			IVec<BigInteger> coefs = new Vec<BigInteger>();
102 			BigInteger coef;
103 			while (matcher.find()) {
104 				literals.push(Integer.valueOf(matcher.group(2)));
105 				coef = new BigInteger(matcher.group(1));
106 				coefs.push(negate ? coef.negate() : coef);
107 			}
108 			solver.setObjectiveFunction(new ObjectiveFunction(literals, coefs));
109 		}
110 
111 	}
112 
113 	private void handlePB(String constraint) throws ContradictionException {
114 		Matcher matcher = WCLAUSE_PATTERN.matcher(constraint);
115 		if (matcher.find()) {
116 			String weightedLiterals = matcher.group();
117 			constraint = matcher.replaceFirst("");
118 			matcher = WLITERAL_PATTERN.matcher(weightedLiterals);
119 			IVecInt literals = new VecInt();
120 			IVecInt coefs = new VecInt();
121 			while (matcher.find()) {
122 				literals.push(Integer.valueOf(matcher.group(2)));
123 				coefs.push(Integer.valueOf(matcher.group(1)));
124 			}
125 			String[] pieces = constraint.split(",");
126 			String comp = pieces[1].substring(1, pieces[1].length() - 1);
127 			int degree = Integer.valueOf(pieces[2].substring(0,
128 					pieces[2].length() - 1));
129 			if ("=".equals(comp) || "==".equals(comp)) {
130 				solver.addExactly(literals, coefs, degree);
131 			} else if ("<=".equals(comp)) {
132 				solver.addAtMost(literals, coefs, degree);
133 			} else if ("<".equals(comp)) {
134 				solver.addAtMost(literals, coefs, degree - 1);
135 			} else if (">=".equals(comp)) {
136 				solver.addAtLeast(literals, coefs, degree);
137 			} else {
138 				assert ">".equals(comp);
139 				solver.addAtLeast(literals, coefs, degree + 1);
140 			}
141 		}
142 
143 	}
144 
145 	@Override
146 	protected String constraintRegexp() {
147 		return "(" + CLAUSE + "|" + CARD + "|" + PB + "|" + OBJECTIVE_FUNCTION
148 				+ ")";
149 	}
150 }