1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
package optimization.projections;
import java.util.Random;
import optimization.util.MathUtils;
import optimization.util.MatrixOutput;
/**
* Implements a projection into a box set defined by a and b.
* If either a or b are infinity then that bound is ignored.
* @author javg
*
*/
public class BoundsProjection extends Projection{
double a,b;
boolean ignoreA = false;
boolean ignoreB = false;
public BoundsProjection(double lowerBound, double upperBound) {
if(Double.isInfinite(lowerBound)){
this.ignoreA = true;
}else{
this.a =lowerBound;
}
if(Double.isInfinite(upperBound)){
this.ignoreB = true;
}else{
this.b =upperBound;
}
}
/**
* Projects into the bounds
* a <= x_i <=b
*/
public void project(double[] original){
for (int i = 0; i < original.length; i++) {
if(!ignoreA && original[i] < a){
original[i] = a;
}else if(!ignoreB && original[i]>b){
original[i]=b;
}
}
}
/**
* Generates a random number between a and b.
*/
Random r = new Random();
public double[] samplePoint(int numParams) {
double[] point = new double[numParams];
for (int i = 0; i < point.length; i++) {
double rand = r.nextDouble();
if(ignoreA && ignoreB){
//Use const to avoid number near overflow
point[i] = rand*(1.E100+1.E100)-1.E100;
}else if(ignoreA){
point[i] = rand*(b-1.E100)-1.E100;
}else if(ignoreB){
point[i] = rand*(1.E100-a)-a;
}else{
point[i] = rand*(b-a)-a;
}
}
return point;
}
public static void main(String[] args) {
BoundsProjection sp = new BoundsProjection(0,Double.POSITIVE_INFINITY);
MatrixOutput.printDoubleArray(sp.samplePoint(3), "random 1");
MatrixOutput.printDoubleArray(sp.samplePoint(3), "random 2");
MatrixOutput.printDoubleArray(sp.samplePoint(3), "random 3");
double[] d = {-1.1,1.2,1.4};
double[] original = d.clone();
MatrixOutput.printDoubleArray(d, "before");
sp.project(d);
MatrixOutput.printDoubleArray(d, "after");
System.out.println("Test projection: " + sp.testProjection(original, d));
}
double epsilon = 1.E-10;
public double[] perturbePoint(double[] point, int parameter){
double[] newPoint = point.clone();
if(!ignoreA && MathUtils.almost(point[parameter], a)){
newPoint[parameter]+=epsilon;
}else if(!ignoreB && MathUtils.almost(point[parameter], b)){
newPoint[parameter]-=epsilon;
}else{
newPoint[parameter]-=epsilon;
}
return newPoint;
}
}
|