summaryrefslogtreecommitdiff
path: root/gi/posterior-regularisation/prjava/src/optimization/projections/BoundsProjection.java
blob: 0429d531057e5c60adb6b4ce0c1d8cd83b02a17e (plain)
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;
	}

	
}