polyrun.constraints.ConstraintsSystem Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of polyrun Show documentation
Show all versions of polyrun Show documentation
A library containing implementation of uniform sampling from bounded convex polytopes.
// Copyright (c) 2015-2018 Krzysztof Ciomek
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package polyrun.constraints;
import java.util.Collection;
/**
* System of linear constraints represented as matrices A, C and vectors b, d, where
* Ax ≤ b,
* Cx = d.
*/
public class ConstraintsSystem {
private final double[][] A;
private final double[] b;
private final double[][] C;
private final double[] d;
private final int numberOfVariables;
public ConstraintsSystem(Collection constraints) {
if (constraints.size() == 0) {
throw new IllegalArgumentException("Constraints cannot be empty.");
}
Integer numberOfVariables = null;
int numberOfEqualities = 0;
for (Constraint constraint : constraints) {
if (constraint.getDirection().equals("=")) {
numberOfEqualities++;
}
}
this.A = new double[constraints.size() - numberOfEqualities][];
this.b = new double[constraints.size() - numberOfEqualities];
this.C = new double[numberOfEqualities][];
this.d = new double[numberOfEqualities];
int inequalityIndex = 0;
int equalityIndex = 0;
for (Constraint constraint : constraints) {
String dir = constraint.getDirection();
double[] lhs = constraint.getLhs();
double rhs = constraint.getRhs();
if (numberOfVariables == null) {
numberOfVariables = lhs.length;
} else if (lhs.length != numberOfVariables) {
throw new IllegalArgumentException("All rows of A are expected to be of equal length."); // just to be sure
}
double[] a = new double[numberOfVariables];
double b;
if (dir.equals("=") || dir.equals("<=")) {
System.arraycopy(lhs, 0, a, 0, numberOfVariables);
b = rhs;
} else if (dir.equals(">=")) {
// Switch direction to <=
for (int j = 0; j < numberOfVariables; j++) {
a[j] = -lhs[j];
}
b = -rhs;
} else {
throw new IllegalArgumentException("Wrong symbol of direction. Only '<=', '=>' and '=' are acceptable.");
}
if (dir.equals("=")) {
this.C[equalityIndex] = a;
this.d[equalityIndex] = b;
equalityIndex++;
} else {
this.A[inequalityIndex] = a;
this.b[inequalityIndex] = b;
inequalityIndex++;
}
}
this.numberOfVariables = numberOfVariables;
}
public ConstraintsSystem(double[][] lhs, String[] dir, double[] rhs) {
if (lhs.length == 0 || lhs[0].length == 0) {
throw new IllegalArgumentException("Matrix 'lhs' cannot have 0 rows and/or 0 columns.");
}
if (lhs.length != dir.length) {
throw new IllegalArgumentException("Length of vector 'dir' has to be equal to the number of rows of matrix 'lhs'.");
}
if (lhs.length != rhs.length) {
throw new IllegalArgumentException("Length of vector 'rhs' has to be equal to the number of rows of matrix 'lhs'.");
}
this.numberOfVariables = lhs[0].length;
for (int i = 1; i < lhs.length; i++) { // just to be sure
if (lhs[i].length != this.numberOfVariables) {
throw new IllegalArgumentException("All rows of A are expected to be of equal length.");
}
}
int numberOfEqualities = 0;
for (String constraintDirection : dir) {
if (constraintDirection.equals("=")) {
numberOfEqualities++;
}
}
this.A = new double[lhs.length - numberOfEqualities][];
this.b = new double[lhs.length - numberOfEqualities];
this.C = new double[numberOfEqualities][];
this.d = new double[numberOfEqualities];
int inequalityIndex = 0;
int equalityIndex = 0;
for (int i = 0; i < lhs.length; i++) {
double[] a = new double[this.numberOfVariables];
double b;
if (dir[i].equals("=") || dir[i].equals("<=")) {
System.arraycopy(lhs[i], 0, a, 0, this.numberOfVariables);
b = rhs[i];
} else if (dir[i].equals(">=")) {
// Switch direction to <=
for (int j = 0; j < this.numberOfVariables; j++) {
a[j] = -lhs[i][j];
}
b = -rhs[i];
} else {
throw new IllegalArgumentException("Wrong symbol of direction. Only '<=', '=>' and '=' are acceptable.");
}
if (dir[i].equals("=")) {
this.C[equalityIndex] = a;
this.d[equalityIndex] = b;
equalityIndex++;
} else {
this.A[inequalityIndex] = a;
this.b[inequalityIndex] = b;
inequalityIndex++;
}
}
}
public ConstraintsSystem(double[][] A, double[] b, double[][] C, double[] d) {
if (A.length > 0) {
this.numberOfVariables = A[0].length;
} else if (C.length > 0) {
this.numberOfVariables = C[0].length;
} else {
throw new IllegalArgumentException("Matrix A and C are empty.");
}
if (A.length != b.length) {
throw new IllegalArgumentException("Length of vector 'b' has to be equal to the number of rows of matrix 'A'.");
}
if (C.length != d.length) {
throw new IllegalArgumentException("Length of vector 'd' has to be equal to the number of rows of matrix 'C'.");
}
for (double[] row : A) { // just to be sure
if (row.length != this.numberOfVariables) {
throw new IllegalArgumentException("All rows of A and C are expected to be of equal length.");
}
}
for (double[] row : C) { // just to be sure
if (row.length != this.numberOfVariables) {
throw new IllegalArgumentException("All rows of A and C are expected to be of equal length.");
}
}
this.A = A;
this.b = b;
this.C = C;
this.d = d;
}
public ConstraintsSystem(double[][] A, double[] b) {
this(A, b, new double[0][], new double[0]);
}
public double[][] getA() {
return this.A;
}
public double[] getB() {
return this.b;
}
public double[][] getC() {
return this.C;
}
public double[] getD() {
return this.d;
}
public int getNumberOfVariables() {
return numberOfVariables;
}
/**
* Checks if x satisfy system of inequalities: Ax ≤ b.
*
* @param A matrix
* @param x vector
* @param b vector
* @return whether Ax ≤ b is satisfied
*/
public static boolean isSatisfied(double[][] A, double[] x, double[] b) {
for (int i = 0; i < A.length; i++) {
double ax = 0.0;
for (int j = 0; j < A[i].length; j++) {
ax += A[i][j] * x[j];
}
if (ax > b[i]) {
return false;
}
}
return true;
}
}