Added Symbolics class

Some tests now passing!
This commit is contained in:
Alex Birkett 2015-02-01 20:45:20 +01:00
parent ae31e0faf9
commit 76014e1903
5 changed files with 472 additions and 46 deletions

View File

@ -22,8 +22,8 @@ public class Constraint {
this.strength = Strength.clip(strength);
}
public Constraint(Constraint other, RelationalOperator op) {
this(other.expression, other.op, other.strength);
public Constraint(Constraint other, double strength) {
this(other.expression, other.op, strength);
}
public Expression getExpression() {
@ -38,8 +38,9 @@ public class Constraint {
return strength;
}
public void setStrength(double strength) {
public Constraint setStrength(double strength) {
this.strength = strength;
return this;
}
public RelationalOperator getOp() {

View File

@ -36,6 +36,10 @@ public class Expression {
this.constant = constant;
}
public Expression(List<Term> terms) {
this(terms, 0);
}
public double getConstant() {
return constant;
}

View File

@ -0,0 +1,410 @@
package no.birkett.kiwi;
import java.util.ArrayList;
import java.util.List;
/**
* Created by alex on 31/01/15.
*/
public class Symbolics {
private Symbolics() {
}
// Variable multiply, divide, and unary invert
public static Term multiply(Variable variable, double coefficient) {
return new Term(variable, coefficient);
}
public static Term divide(Variable variable, double denominator) {
return multiply(variable, (1.0 / denominator));
}
public static Term negate(Variable variable) {
return multiply(variable, -1.0);
}
// Term multiply, divide, and unary invert
public static Term multiply(Term term, double coefficient) {
return new Term(term.getVariable(), term.getCoefficient() * coefficient);
}
public static Term divide(Term term, double denominator) {
return multiply(term, (1.0 / denominator));
}
public static Term negate(Term term) {
return multiply(term, -1.0);
}
// Expression multiply, divide, and unary invert
public static Expression multiply(Expression expression, double coefficient) {
List<Term> terms = new ArrayList<Term>();
for (Term term : expression.getTerms()) {
terms.add(multiply(term, coefficient));
}
// TODO Do we need to make a copy of the term objects in the array?
return new Expression(terms, expression.getConstant() * coefficient);
}
public static Expression divide(Expression expression, double denominator) {
return multiply(expression, (1.0 / denominator));
}
public static Expression negate(Expression expression) {
return multiply(expression, -1.0);
}
// Double multiply
public static Expression multiply(double coefficient, Expression expression) {
return multiply(expression, coefficient);
}
public static Term multiply(double coefficient, Term term) {
return multiply(term, coefficient);
}
public static Term multiply(double coefficient, Variable variable) {
return multiply(variable, coefficient);
}
// Expression add and subtract
public static Expression add(Expression first, Expression second) {
//TODO do we need to copy term objects?
List<Term> terms = new ArrayList<Term>(first.getTerms().size() + second.getTerms().size());
terms.addAll(first.getTerms());
terms.addAll(second.getTerms());
return new Expression(terms, first.getConstant() + second.getConstant());
}
public static Expression add(Expression first, Term second) {
//TODO do we need to copy term objects?
List<Term> terms = new ArrayList<Term>(first.getTerms().size() + 1);
terms.addAll(first.getTerms());
terms.add(second);
return new Expression(terms, first.getConstant());
}
public static Expression add(Expression expression, Variable variable) {
return add(expression, new Term(variable));
}
public static Expression add(Expression expression, double constant) {
return new Expression(expression.getTerms(), expression.getConstant() + constant);
}
public static Expression subtract(Expression first, Expression second) {
return add(first, negate(second));
}
public static Expression subtract(Expression expression, Term term) {
return add(expression, negate(term));
}
public static Expression subtract(Expression expression, Variable variable) {
return add(expression, negate(variable));
}
public static Expression subtract(Expression expression, double constant) {
return add(expression, -constant);
}
// Term add and subtract
public static Expression add(Term term, Expression expression) {
return add(expression, term);
}
public static Expression add(Term first, Term second) {
List<Term> terms = new ArrayList<Term>(2);
terms.add(first);
terms.add(second);
return new Expression(terms);
}
public static Expression add(Term term, Variable variable) {
return add(term, new Term(variable));
}
public static Expression add(Term term, double constant) {
return new Expression(term, constant);
}
public static Expression subtract(Term term, Expression expression) {
return add(negate(expression), term);
}
public static Expression subtract(Term first, Term second) {
return add(first, negate(second));
}
public static Expression subtract(Term term, Variable variable) {
return add(term, negate(variable));
}
public static Expression subtract(Term term, double constant) {
return add(term, -constant);
}
// Variable add and subtract
public static Expression add(Variable variable, Expression expression) {
return add(expression, variable);
}
public static Expression add(Variable variable, Term term) {
return add(term, variable);
}
public static Expression add(Variable first, Variable second) {
return add(new Term(first), second);
}
public static Expression add(Variable variable, double constant) {
return add(new Term(variable), constant);
}
public static Expression subtract(Variable variable, Expression expression) {
return add(variable, negate(expression));
}
public static Expression subtract(Variable variable, Term term) {
return add(variable, negate(term));
}
public static Expression subtract(Variable first, Variable second) {
return add(first, negate(second));
}
public static Expression subtract(Variable variable, double constant) {
return add(variable, -constant);
}
// Double add and subtract
public static Expression add(double constant, Expression expression) {
return add(expression, constant);
}
public static Expression add(double constant, Term term) {
return add(term, constant);
}
public static Expression add(double constant, Variable variable) {
return add(variable, constant);
}
public static Expression subtract(double constant, Expression expression) {
return add(negate(expression), constant);
}
public static Expression subtract(double constant, Term term) {
return add(negate(term), constant);
}
public static Expression subtract(double constant, Variable variable) {
return add(negate(variable), constant);
}
// Expression relations
public static Constraint equals(Expression first, Expression second) {
return new Constraint(subtract(first, second), RelationalOperator.OP_EQ);
}
public static Constraint equals(Expression expression, Term term) {
return equals(expression, new Expression(term));
}
public static Constraint equals(Expression expression, Variable variable) {
return equals(expression, new Term(variable));
}
public static Constraint equals(Expression expression, double constant) {
return equals(expression, new Expression(constant));
}
public static Constraint lessThanOrEqualTo(Expression first, Expression second) {
return new Constraint(subtract(first, second), RelationalOperator.OP_LE);
}
public static Constraint lessThanOrEqualTo(Expression expression, Term term) {
return lessThanOrEqualTo(expression, new Expression(term));
}
public static Constraint lessThanOrEqualTo(Expression expression, Variable variable) {
return lessThanOrEqualTo(expression, new Term(variable));
}
public static Constraint lessThanOrEqualTo(Expression expression, double constant) {
return lessThanOrEqualTo(expression, new Expression(constant));
}
public static Constraint greaterThanOrEqualTo(Expression first, Expression second) {
return new Constraint(subtract(first, second), RelationalOperator.OP_GE);
}
public static Constraint greaterThanOrEqualTo(Expression expression, Term term) {
return greaterThanOrEqualTo(expression, new Expression(term));
}
public static Constraint greaterThanOrEqualTo(Expression expression, Variable variable) {
return greaterThanOrEqualTo(expression, new Term(variable));
}
public static Constraint greaterThanOrEqualTo(Expression expression, double constant) {
return greaterThanOrEqualTo(expression, new Expression(constant));
}
// Term relations
public static Constraint equals(Term term, Expression expression) {
return equals(expression, term);
}
public static Constraint equals(Term first, Term second) {
return equals(new Expression(first), second);
}
public static Constraint equals(Term term, Variable variable) {
return equals(new Expression(term), variable);
}
public static Constraint equals(Term term, double constant) {
return equals(new Expression(term), constant);
}
public static Constraint lessThanOrEqualTo(Term term, Expression expression) {
return lessThanOrEqualTo(expression, term);
}
public static Constraint lessThanOrEqualTo(Term first, Term second) {
return lessThanOrEqualTo(new Expression(first), second);
}
public static Constraint lessThanOrEqualTo(Term term, Variable variable) {
return lessThanOrEqualTo(new Expression(term), variable);
}
public static Constraint lessThanOrEqualTo(Term term, double constant) {
return lessThanOrEqualTo(new Expression(term), constant);
}
public static Constraint greaterThanOrEqualTo(Term term, Expression expression) {
return greaterThanOrEqualTo(expression, term);
}
public static Constraint greaterThanOrEqualTo(Term first, Term second) {
return greaterThanOrEqualTo(new Expression(first), second);
}
public static Constraint greaterThanOrEqualTo(Term term, Variable variable) {
return greaterThanOrEqualTo(new Expression(term), variable);
}
public static Constraint greaterThanOrEqualTo(Term term, double constant) {
return greaterThanOrEqualTo(new Expression(term), constant);
}
// Variable relations
public static Constraint equals(Variable variable, Expression expression) {
return equals(expression, variable);
}
public static Constraint equals(Variable variable, Term term) {
return equals(term, variable);
}
public static Constraint equals(Variable first, Variable second) {
return equals(new Term(first), second);
}
public static Constraint equals(Variable variable, double constant) {
return equals(new Term(variable), constant);
}
public static Constraint lessThanOrEqualTo(Variable variable, Expression expression) {
return lessThanOrEqualTo(expression, variable);
}
public static Constraint lessThanOrEqualTo(Variable variable, Term term) {
return lessThanOrEqualTo(term, variable);
}
public static Constraint lessThanOrEqualTo(Variable first, Variable second) {
return lessThanOrEqualTo(new Term(first), second);
}
public static Constraint lessThanOrEqualTo(Variable variable, double constant) {
return lessThanOrEqualTo(new Term(variable), constant);
}
public static Constraint greaterThanOrEqualTo(Variable variable, Expression expression) {
return greaterThanOrEqualTo(expression, variable);
}
public static Constraint greaterThanOrEqualTo(Variable variable, Term term) {
return greaterThanOrEqualTo(term, variable);
}
public static Constraint greaterThanOrEqualTo(Variable first, Variable second) {
return greaterThanOrEqualTo(new Term(first), second);
}
public static Constraint greaterThanOrEqualTo(Variable variable, double constant) {
return greaterThanOrEqualTo(new Term(variable), constant);
}
// Double relations
public static Constraint equals(double constant, Expression expression) {
return equals(expression, constant);
}
public static Constraint equals(double constant, Term term) {
return equals(term, constant);
}
public static Constraint equals(double constant, Variable variable) {
return equals(variable, constant);
}
public static Constraint lessThanOrEqualTo(double constant, Expression expression) {
return lessThanOrEqualTo(expression, constant);
}
public static Constraint lessThanOrEqualTo(double constant, Term term) {
return lessThanOrEqualTo(term, constant);
}
public static Constraint lessThanOrEqualTo(double constant, Variable variable) {
return lessThanOrEqualTo(variable, constant);
}
public static Constraint greaterThanOrEqualTo(double constant, Expression expression) {
return greaterThanOrEqualTo(expression, constant);
}
public static Constraint greaterThanOrEqualTo(double constant, Term term) {
return greaterThanOrEqualTo(term, constant);
}
public static Constraint greaterThanOrEqualTo(double constant, Variable variable) {
return greaterThanOrEqualTo(variable, constant);
}
// Constraint strength modifier
public static Constraint modifyStrength(Constraint constraint, double strength) {
return new Constraint(constraint, strength);
}
public static Constraint modifyStrength(double strength, Constraint constraint) {
return modifyStrength(strength, constraint);
}
}

View File

@ -14,9 +14,8 @@ public class Variable {
}
public Variable(double value) {
}
public double getValue() {
return value;
}
@ -25,11 +24,4 @@ public class Variable {
this.value = value;
}
public Expression times(double value) {
return null;
}
public Expression plus(double value) {
return null;
}
}

View File

@ -10,36 +10,73 @@ public class Tests {
private static double EPSILON = 1.0e-8;
@Test
public void testKiwi() throws UnsatisfiableConstraintException, DuplicateConstraintException {
public void simpleNew() throws UnsatisfiableConstraintException, DuplicateConstraintException {
Solver solver = new Solver();
Variable x = new Variable("x");
solver.addConstraint(Symbolics.equals(Symbolics.add(x,2), 20));
solver.updateVariables();
assertEquals(x.getValue(), 18, EPSILON);
}
@Test
public void simple0() throws UnsatisfiableConstraintException, DuplicateConstraintException {
Solver solver = new Solver();
Variable x = new Variable("x");
Variable y = new Variable("y");
// x = 20
solver.addConstraint(Symbolics.equals(x, 20));
Term term = new Term(x);
// x + 2 == y + 10
//
solver.addConstraint(Symbolics.equals(Symbolics.add(x,2), Symbolics.add(y, 10)));
Expression expression = new Expression(term);
Constraint constraint = new Constraint(expression, RelationalOperator.OP_EQ);
solver.addConstraint(constraint);
solver.updateVariables();
System.out.println("x " + x.getValue() + " y " + y.getValue());
assertEquals(y.getValue(), 12, EPSILON);
assertEquals(x.getValue(), 20, EPSILON);
}
/*@Test
public void simple1() {
Variable x = new Variable(167);
Variable y = new Variable(2);
@Test
public void simple1() throws DuplicateConstraintException, UnsatisfiableConstraintException {
Variable x = new Variable("x");
Variable y = new Variable("y");
Solver solver = new Solver();
solver.addConstraint(Symbolics.equals(x, y));
solver.updateVariables();
assertEquals(x.getValue(), y.getValue(), EPSILON);
}
@Test
public void casso1() throws DuplicateConstraintException, UnsatisfiableConstraintException {
Variable x = new Variable("x");
Variable y = new Variable("y");
Solver solver = new Solver();
Constraint eq = new Constraint(x, Constraint.Operator.EQ, new Expression(y));
//ClLinearEquation eq = new ClLinearEquation(x, new ClLinearExpression(y));
solver.addConstraint(eq);
assertEquals(x.value(), y.value(), EPSILON);
solver.addConstraint(Symbolics.lessThanOrEqualTo(x, y));
solver.addConstraint(Symbolics.equals(y, Symbolics.add(x, 3.0)));
solver.addConstraint(Symbolics.equals(x, 10.0).setStrength(Strength.WEAK));
solver.addConstraint(Symbolics.equals(y, 10.0).setStrength(Strength.WEAK));
solver.updateVariables();
if (Math.abs(x.getValue() - 10.0) < EPSILON) {
assertEquals(10, x.getValue(), EPSILON);
assertEquals(13, y.getValue(), EPSILON);
} else {
assertEquals(7, x.getValue(), EPSILON);
assertEquals(10, y.getValue(), EPSILON);
}
}
@Test
/*@Test
public void addDelete1() {
Variable x = new Variable("x");
Solver solver = new Solver();
@ -112,25 +149,7 @@ public class Tests {
assertEquals(120, y.value(), EPSILON);
}
@Test
public void casso1() {
Variable x = new Variable("x");
Variable y = new Variable("y");
Solver solver = new Solver();
solver.addConstraint(new Constraint(x, Constraint.Operator.LEQ, y));
solver.addConstraint(new Constraint(y, Constraint.Operator.EQ, x.plus(3.0)));
solver.addConstraint(new Constraint(x, Constraint.Operator.EQ, 10.0, Strength.WEAK));
solver.addConstraint(new Constraint(y, Constraint.Operator.EQ, 10.0, Strength.WEAK));
if (Math.abs(x.getValue() - 10.0) < EPSILON) {
assertEquals(10, x.value(), EPSILON);
assertEquals(13, y.value(), EPSILON);
} else {
assertEquals(7, x.value(), EPSILON);
assertEquals(10, y.value(), EPSILON);
}
}
@Test(expected = RequiredFailure.class)
public void inconsistent1() throws InternalError {