Skip to content

Commit

Permalink
Made absolute error to accept in floating point comparisons parametri…
Browse files Browse the repository at this point in the history
…sable in all places it is used.
  • Loading branch information
kciomek committed Jun 12, 2021
1 parent e17c07c commit 91f3f9a
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/main/java/polyrun/Boundary.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class Boundary {
* @param b vector
* @param d direction
* @param x current point (vector)
* @param eps absolute error to allow (non-negative), i.e., the greatest value treated as 0;
* @param eps absolute error to accept in floating point comparisons (non-negative, default 1e-10);
* applied also to check Ax ≤ b
* @param indicesOfNonZeroElementsInA array of array of indices of non-zero elements in A (if not provided
* the method will iterate over all elements in each row of A; use only if A is relatively sparse)
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/polyrun/PolytopeRunner.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,11 @@ public PolytopeRunner(ConstraintsSystem constraintsSystem, GLPSolver glpSolver,
* provide for better performance if there may be some redundant constrains
* @param skipZeroElements whether {@code RandomWalk} should iterate over array of indices of non-zero
* elements or directly over entire transformed matrix A (from {@code constraintsSystem})
* @param eps absolute error to accept in floating point comparisons (non-negative, default 1e-10)
*/
public PolytopeRunner(ConstraintsSystem constraintsSystem, GLPSolver glpSolver, boolean skipZeroElements, double eps) {
this.eps = eps;
this.transformation = new Transformation(constraintsSystem.getC(), constraintsSystem.getD(), constraintsSystem.getNumberOfVariables());
this.transformation = new Transformation(constraintsSystem.getC(), constraintsSystem.getD(), constraintsSystem.getNumberOfVariables(), this.eps);
this.numberOfOriginalVariables = constraintsSystem.getA()[0].length;

// Project constraints to space where the polytope will be full-dimensional
Expand Down Expand Up @@ -296,7 +297,7 @@ public void setStartPoint(double[] startPoint) {

double[] transformedPoint = this.transformation.project(new double[][]{startPoint})[0];

if (!ConstraintsSystem.isSatisfied(A, transformedPoint, b, 1e-10)) {
if (!ConstraintsSystem.isSatisfied(A, transformedPoint, b, this.eps)) {
throw new IllegalArgumentException("Interior point is required.");
}

Expand Down
18 changes: 16 additions & 2 deletions src/main/java/polyrun/Transformation.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,20 @@ public class Transformation {
* @param numberOfVariables number of variables
*/
public Transformation(double matrixC[][], double[] vectord, int numberOfVariables) {
this(matrixC, vectord, numberOfVariables, 1e-10);
}

/**
* Builds transformation that is based on system C x = d.
* <p>
* Note: Cx = d is expected to be consistent system of linearly independent equations.
*
* @param matrixC matrix C
* @param vectord vector d
* @param numberOfVariables number of variables
* @param eps absolute error to accept in floating point comparisons (non-negative, default 1e-10)
*/
public Transformation(double matrixC[][], double[] vectord, int numberOfVariables, double eps) {
if (matrixC == null || matrixC.length == 0) {
// Set identity matrix as new basis
this.nullspace = SimpleMatrix.identity(numberOfVariables);
Expand All @@ -62,14 +76,14 @@ public Transformation(double matrixC[][], double[] vectord, int numberOfVariable
for (int i = 0; i < C.getNumCols(); i++) {
for (int j = 0; j < C.getNumRows(); j++) {
if (i == j) {
values[i][j] = W.get(i, i) > 1e-10 ? 1.0 / W.get(i, i) : 0.0;
values[i][j] = W.get(i, i) > eps ? 1.0 / W.get(i, i) : 0.0;
} else {
values[i][j] = 0.0;
}
}
}

// Set null space of Cx = b as new basis
// Set null space of Cx = d as new basis
this.nullspace = svd.nullSpace();

// Set particular solution, which with the null space describes all solutions of Cx=d
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/polyrun/constraints/ConstraintsSystem.java
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ public static boolean isSatisfied(double[][] A, double[] x, double[] b) {
* @param A matrix
* @param x vector
* @param b vector
* @param eps absolute error to allow (non-negative), i.e., the greatest value treated as 0
* @param eps absolute error to accept in floating point comparisons (non-negative, default 1e-10)
* @return whether Ax &le; b is satisfied
*/
public static boolean isSatisfied(double[][] A, double[] x, double[] b, double eps) {
Expand Down
16 changes: 14 additions & 2 deletions src/main/java/polyrun/sampling/BallWalk.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public class BallWalk implements RandomWalk {
private final OutOfBoundsBehaviour outOfBoundsBehaviour;
private final Random random;
private final Boundary boundary;
private final double eps;

/**
* @param radius radius of a ball
Expand All @@ -61,6 +62,16 @@ public BallWalk(double radius, OutOfBoundsBehaviour outOfBoundsBehaviour) {
* @param outOfBoundsBehaviour the behaviour of random walk when it tries to make a step that exceeds bounds of the polytope
*/
public BallWalk(Random random, double radius, OutOfBoundsBehaviour outOfBoundsBehaviour) {
this(random, radius, outOfBoundsBehaviour, 1e-10);
}

/**
* @param random random number generator
* @param radius radius of a ball
* @param outOfBoundsBehaviour the behaviour of random walk when it tries to make a step that exceeds bounds of the polytope
* @param eps absolute error to accept in floating point comparisons (non-negative, default 1e-10)
*/
public BallWalk(Random random, double radius, OutOfBoundsBehaviour outOfBoundsBehaviour, double eps) {
if (radius <= 0.0) {
throw new IllegalArgumentException("Radius have to be positive.");
}
Expand All @@ -69,6 +80,7 @@ public BallWalk(Random random, double radius, OutOfBoundsBehaviour outOfBoundsBe
this.radius = radius;
this.outOfBoundsBehaviour = outOfBoundsBehaviour;
this.random = random;
this.eps = eps;
this.boundary = new Boundary();
}

Expand All @@ -89,14 +101,14 @@ public void next(double[][] A, int[][] indicesOfNonZeroElementsInA,
}

// Set newly generated point as a new if it is inside the polytope and stay otherwise
if (ConstraintsSystem.isSatisfied(A, nextPoint, b, 1e-10)) {
if (ConstraintsSystem.isSatisfied(A, nextPoint, b, this.eps)) {
System.arraycopy(nextPoint, 0, to, 0, from.length);
} else {
System.arraycopy(from, 0, to, 0, from.length);
}
} else if (OutOfBoundsBehaviour.Crop.equals(this.outOfBoundsBehaviour)) {
// Calculate distance from point 'from' to the boundary of the polytope defined by Ax <= b in direction stored in 'buffer'
double distance = boundary.distance(A, b, buffer, from, 1e-10, null)[0];
double distance = boundary.distance(A, b, buffer, from, this.eps, null)[0];

if (distance == Double.POSITIVE_INFINITY) {
throw new RuntimeException("The sampling region is unbounded.");
Expand Down
13 changes: 12 additions & 1 deletion src/main/java/polyrun/sampling/GridWalk.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public class GridWalk implements RandomWalk {

private final Random random;
private final double gridSpacing;
private final double eps;

/**
* @param gridSpacing grid spacing
Expand All @@ -46,12 +47,22 @@ public GridWalk(double gridSpacing) {
* @param gridSpacing grid spacing
*/
public GridWalk(Random random, double gridSpacing) {
this(random, gridSpacing, 1e-10);
}

/**
* @param random random number generator
* @param gridSpacing grid spacing
* @param eps absolute error to accept in floating point comparisons (non-negative, default 1e-10)
*/
public GridWalk(Random random, double gridSpacing, double eps) {
if (gridSpacing <= 0.0) {
throw new IllegalArgumentException("Grid spacing have to be positive.");
}

this.random = random;
this.gridSpacing = gridSpacing;
this.eps = eps;
}

@Override
Expand All @@ -68,7 +79,7 @@ public void next(double[][] A, int[][] indicesOfNonZeroElementsInA,
nextPoint[index / 2] = ((index % 2 == 0) ? 1.0 : -1.0) * this.gridSpacing;

// Set newly generated point as a new if it is inside the polytope and stay otherwise
if (ConstraintsSystem.isSatisfied(A, nextPoint, b, 1e-10)) {
if (ConstraintsSystem.isSatisfied(A, nextPoint, b, this.eps)) {
System.arraycopy(nextPoint, 0, to, 0, from.length);
} else {
System.arraycopy(from, 0, to, 0, from.length);
Expand Down
17 changes: 16 additions & 1 deletion src/main/java/polyrun/sampling/HitAndRun.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,28 @@ public class HitAndRun implements RandomWalk {
private final Random random;
private final UnitNSphere unitNSphere;
private final Boundary boundary;
private final double eps;

public HitAndRun() {
this(new RandomAdaptor(new MersenneTwister()));
}

/**
*
* @param random random number generator
*/
public HitAndRun(Random random) {
this(random, 1e-10);
}

/**
*
* @param random random number generator
* @param eps absolute error to accept in floating point comparisons (non-negative, default 1e-10)
*/
public HitAndRun(Random random, double eps) {
this.random = random;
this.eps = eps;
this.unitNSphere = new UnitNSphere(random);
this.boundary = new Boundary();
}
Expand All @@ -55,7 +70,7 @@ public void next(double[][] A, int[][] indicesOfNonZeroElementsInA,
this.unitNSphere.fillVectorWithRandomPoint(buffer);

// Calculate begin and end of the segment along the generated direction (distance to boundary in both directions)
double[] dist = boundary.distance(A, b, buffer, from, 1e-10, indicesOfNonZeroElementsInA);
double[] dist = boundary.distance(A, b, buffer, from, eps, indicesOfNonZeroElementsInA);

if (dist[0] == Double.POSITIVE_INFINITY || dist[1] == Double.NEGATIVE_INFINITY) {
throw new RuntimeException("Cannot find begin or end of a segment for given direction. The sampling region is unbounded.");
Expand Down
12 changes: 11 additions & 1 deletion src/main/java/polyrun/sampling/SphereWalk.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,17 @@ public SphereWalk(double radius, OutOfBoundsBehaviour outOfBoundsBehaviour) {
* @param outOfBoundsBehaviour the behaviour of random walk when it tries to make a step that exceeds bounds of the polytope
*/
public SphereWalk(Random random, double radius, OutOfBoundsBehaviour outOfBoundsBehaviour) {
super(random, radius, outOfBoundsBehaviour);
super(random, radius, outOfBoundsBehaviour, 1e-10);
}

/**
* @param random random number generator
* @param radius radius of a sphere
* @param outOfBoundsBehaviour the behaviour of random walk when it tries to make a step that exceeds bounds of the polytope
* @param eps absolute error to accept in floating point comparisons (non-negative, default 1e-10)
*/
public SphereWalk(Random random, double radius, OutOfBoundsBehaviour outOfBoundsBehaviour, double eps) {
super(random, radius, outOfBoundsBehaviour, eps);
}

@Override
Expand Down

0 comments on commit 91f3f9a

Please sign in to comment.