/* * Copyright 2011 JBoss Inc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.drools.semantics.lang.dl; import choco.cp.model.CPModel; import choco.kernel.model.constraints.Constraint; import choco.kernel.model.variables.AbstractVariable; import choco.kernel.model.variables.integer.IntegerVariable; import choco.kernel.model.variables.real.RealExpressionVariable; import choco.kernel.model.variables.real.RealVariable; import java.util.ArrayList; import java.util.List; import static choco.Choco.*; public class ConstraintFactory { private enum Operator { EQ, LE, GE, LEQ, GEQ, NEQ }; private static List<Pair<CPModel,Integer>> varCounter = new ArrayList<Pair<CPModel,Integer>>(); public static RealVariable newUnitIntervalVariable(Object var, MinimizationProblem p) { return newUnitIntervalVariable(var, 0.0, 1.0, p); } public static RealVariable newUnitIntervalVariable(Object var, double low, double upp, MinimizationProblem p) { String varName = format(var,p); AbstractVariable v1 = p.getVariable( varName ); if ( v1 instanceof IntegerVariable ) { System.err.println("What went wrong"); } RealVariable v = (RealVariable) v1; if ( v == null ) { v = makeRealVar( varName, low, upp ); p.registerVar( varName, v ); } v.setLowB( Math.max( v.getLowB(), low ) ); v.setUppB( Math.min( v.getUppB(), upp ) ); return v; } public static IntegerVariable newBooleanVariable(Object var, MinimizationProblem p) { String varName = format(var,p); IntegerVariable v = (IntegerVariable) p.getVariable( varName ); if ( v == null ) { v = makeBooleanVar( varName ); p.registerVar( varName, v ); } return v; } public static RealVariable newBooleanRealVariable(Object var, MinimizationProblem p) { IntegerVariable x = newBooleanVariable(var, p); RealVariable Y = castIntToRealVariable(x, p); return Y; } private static RealVariable castIntToRealVariable(IntegerVariable y, MinimizationProblem p) { RealVariable Y = newUnitIntervalVariable( "S"+y, p ); p.addConstraint( eq( y, Y ) ); return Y; } private static String format(Object var, MinimizationProblem p) { // return "x"+(var.toString().hashCode() % 10000); return "x_"+var; } // public static void addAndConstraint(Object[] vars, Object y, Object l, Problem prob) { // // addUnique(ConstraintFactory.buildConstraint(" 1.0*"+l+" +1.0*"+y,Operator.LE, 1.0)); // String terms = ""; // for (int j = 0; j < vars.length; j++) { // // xj <= 1 - y // addUnique(ConstraintFactory.buildConstraint(" 1.0*"+vars[j]+" +1.0*"+y,Operator.LE, 1.0)); // terms += " 1.0*" + vars[j]; // } // addUnique(ConstraintFactory.buildConstraint(terms+" -1.0*"+l+" +1.0*"+y,Operator.EQ, vars.length -1)); // } public static void addAndConstraint(RealVariable[] vars, IntegerVariable y, RealVariable l, MinimizationProblem prob) { // addUnique(ConstraintFactory.buildConstraint(" 1.0*"+l+" -1.0*"+y,Operator.LE, 0.0), prob); RealVariable Y = castIntToRealVariable(y, prob); prob.addConstraint( leq(l, Y) ); RealExpressionVariable terms = vars[0]; for (int j = 1; j < vars.length; j++) { terms = plus(terms, vars[j]); } // addUnique(ConstraintFactory.buildConstraint(terms+" -1.0*"+l,Operator.LE, vars.length -1), prob); prob.addConstraint( leq( terms, plus( l, vars.length - 1.0 ) ) ); // addUnique(ConstraintFactory.buildConstraint(terms+" -1.0*"+l+" -1.0*"+y,Operator.GE, vars.length -2), prob); prob.addConstraint( geq( terms, plus( plus( l, Y ), vars.length - 2.0 ) ) ); } // public static void addOrConstraint(Object[] vars, Object y, Object l, Problem prob) { // String terms = ""; // for (int j = 0; j < vars.length; j++) { // terms += " 1.0*" + vars[j]; // } // // addUnique(ConstraintFactory.buildConstraint(terms+" -1.0*"+l,Operator.EQ, 0), prob); // // } public static void addOrConstraint(RealVariable[] vars, IntegerVariable y, RealVariable l, MinimizationProblem prob) { // addUnique(ConstraintFactory.buildConstraint(" 1.0*"+l+" -1.0*"+y,Operator.GE, 0.0), prob); RealVariable Y = castIntToRealVariable(y, prob); prob.addConstraint( geq(l, Y) ); RealExpressionVariable terms = vars[0]; for (int j = 1; j < vars.length; j++) { terms = plus( terms, vars[j] ); } // addUnique(ConstraintFactory.buildConstraint(terms+" -1.0*"+l,Operator.GE, 0), prob); prob.addConstraint( geq(terms, l) ); // addUnique(ConstraintFactory.buildConstraint(terms+" -1.0*"+l+" -1.0*"+y,Operator.LE, 0), prob); prob.addConstraint( leq(terms, plus(l, Y)) ); } //// public static void addComplementConstraint(RealVariable v1, RealVariable v2, MinimizationProblem prob) { // addUnique(ConstraintFactory.buildConstraint(" 1.0*"+v1+" +1.0*"+v2, Operator.EQ, 1.0), prob); prob.addConstraint( eq( v1, minus( 1.0, v2 ) ) ); } public static void addEqualityConstraint(RealVariable v1, RealVariable v2, MinimizationProblem prob) { // addUnique(ConstraintFactory.buildConstraint(" 1.0*"+v1+" -1.0*"+v2,Operator.EQ, 0.0), prob); prob.addConstraint( eq( v1, v2 ) ); } public static void addImplicationConstraint(RealVariable xA, RealVariable xB, RealVariable l, MinimizationProblem prob) { // addUnique(ConstraintFactory.buildConstraint(" 1.0*"+l+" -1.0*"+xA+" 1.0*"+xB,Operator.LE,0.0), prob); prob.addConstraint( leq( plus( l, xB ), xA ) ); } public static void addLBConstraint(RealVariable x, RealVariable l, MinimizationProblem prob) { // addUnique(ConstraintFactory.buildConstraint(" 1.0*"+x+" -1.0*"+l,Operator.GE,0), prob); prob.addConstraint( geq( x, l ) ); } public static void addNumericLBConstraint(RealVariable x, Number tau, MinimizationProblem prob) { // addUnique(ConstraintFactory.buildConstraint(" 1.0*"+x,Operator.GE,tau), prob); prob.addConstraint( geq( x, tau.doubleValue() ) ); } public static void addUBConstraint(RealVariable x, RealVariable l, MinimizationProblem prob) { // addUnique(ConstraintFactory.buildConstraint(" 1.0*"+x+" +1.0*"+l,Operator.LE,1.0), prob); prob.addConstraint( leq( x, minus(1.0, l) ) ); } public static void addNumericUBConstraint(RealVariable x, Number phi, MinimizationProblem prob) { // addUnique(ConstraintFactory.buildConstraint(" 1.0*"+x,Operator.LE,phi), prob); prob.addConstraint( leq( x, phi.doubleValue() ) ); } // ( prop && klass ) <= father public static void addExistConstraint(RealVariable prop, RealVariable klass, RealVariable father, MinimizationProblem prob) { // addUnique(ConstraintFactory.buildConstraint(" 1.0*"+prop+" +1.0*"+klass+" -1.0*"+father,Operator.LE, 1), prob); prob.addConstraint( leq( plus( prop, klass ), plus( father, 1.0 ) ) ); } // ( prop => klass ) >= father public static void addForallConstraint(RealVariable prop, RealVariable klass, IntegerVariable y, RealVariable father, MinimizationProblem prob) { RealVariable Y = newUnitIntervalVariable( "S"+y, prob ); // addUnique(ConstraintFactory.buildConstraint(" -1.0*"+father+" -1.0*"+prop+" +1.0*"+klass,Operator.GE,-1), prob); prob.addConstraint( geq( klass, minus( plus( father, prop ), 1.0 ) ) ); } private static void addUnique( Constraint c, MinimizationProblem prob ) { // Constraint does not redefine equals :( //if (! prob.getConstraints().contains(c)) // prob.add(c); // for (Constraint con : prob.getConstraints()) { // if (con.toString().equals(c.toString())) // return; // } prob.addConstraint( c ); } private static class Pair<T, K> { private T key; private K value; private Pair(T key, K value) { this.key = key; this.value = value; } public T getKey() { return key; } public void setKey(T key) { this.key = key; } @Override public String toString() { return "Pair{" + "key=" + key + ", value=" + value + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Pair pair = (Pair) o; if (key != null ? !key.equals(pair.key) : pair.key != null) return false; if (value != null ? !value.equals(pair.value) : pair.value != null) return false; return true; } @Override public int hashCode() { int result = key != null ? key.hashCode() : 0; result = 31 * result + (value != null ? value.hashCode() : 0); return result; } public K getValue() { return value; } public void setValue(K value) { this.value = value; } } }