samer@0
|
1 /*
|
samer@0
|
2 * Copyright (c) 2000, Samer Abdallah, King's College London.
|
samer@0
|
3 * All rights reserved.
|
samer@0
|
4 *
|
samer@0
|
5 * This software is provided AS iS and WITHOUT ANY WARRANTY;
|
samer@0
|
6 * without even the implied warranty of MERCHANTABILITY or
|
samer@0
|
7 * FITNESS FOR A PARTICULAR PURPOSE.
|
samer@0
|
8 */
|
samer@0
|
9
|
samer@0
|
10 package samer.maths.opt;
|
samer@0
|
11 import samer.maths.*;
|
samer@0
|
12 import samer.core.*;
|
samer@0
|
13 import samer.core.types.*;
|
samer@0
|
14
|
samer@0
|
15 /**
|
samer@0
|
16 Cubic line search with positivity constraints
|
samer@0
|
17 dimensions become inactive when they go to
|
samer@0
|
18 zero and the gradient > GEPS
|
samer@0
|
19 */
|
samer@0
|
20
|
samer@0
|
21 public class Positivity extends Constraints
|
samer@0
|
22 {
|
samer@0
|
23 double XEPS=1e-6;
|
samer@0
|
24 double GEPS=1e-4;
|
samer@0
|
25 int [] zerod;
|
samer@0
|
26 int released;
|
samer@0
|
27
|
samer@0
|
28 public Positivity(MinimiserBase minimiser)
|
samer@0
|
29 {
|
samer@0
|
30 super(minimiser);
|
samer@0
|
31 zerod=new int[n];
|
samer@0
|
32
|
samer@0
|
33 minimiser.add(new VParameter("XEPS", new DoubleModel() {
|
samer@0
|
34 public void set(double t) { XEPS=t; }
|
samer@0
|
35 public double get() { return XEPS; }
|
samer@0
|
36 } )
|
samer@0
|
37 );
|
samer@0
|
38
|
samer@0
|
39 minimiser.add(new VParameter("GEPS", new DoubleModel() {
|
samer@0
|
40 public void set(double t) { GEPS=t; }
|
samer@0
|
41 public double get() { return GEPS; }
|
samer@0
|
42 } )
|
samer@0
|
43 );
|
samer@0
|
44 }
|
samer@0
|
45
|
samer@0
|
46 /** constrain all dimensions which are currently set
|
samer@0
|
47 to zero.
|
samer@0
|
48 */
|
samer@0
|
49
|
samer@0
|
50 public void initialise()
|
samer@0
|
51 {
|
samer@0
|
52 int p=0, q=0;
|
samer@0
|
53
|
samer@0
|
54 for (int i=0; i<n; i++) {
|
samer@0
|
55 if (S.P1.x[i]<=0) { inactive[p++]=i; S.P1.x[i]=0; }
|
samer@0
|
56 else active[q++]=i;
|
samer@0
|
57 }
|
samer@0
|
58 m=q;
|
samer@0
|
59 }
|
samer@0
|
60
|
samer@0
|
61 /**
|
samer@0
|
62 This finds the constrained dimension with the
|
samer@0
|
63 largest positive gradient, and if of
|
samer@0
|
64 that gradient is bigger than 1, then releases
|
samer@0
|
65 that dimension so that it can take part in the
|
samer@0
|
66 optimization
|
samer@0
|
67 */
|
samer@0
|
68
|
samer@0
|
69 public boolean release(Datum P)
|
samer@0
|
70 {
|
samer@0
|
71 if (m==n) return false;
|
samer@0
|
72
|
samer@0
|
73 int imax=-1;
|
samer@0
|
74 double grad=-GEPS; // tolerance
|
samer@0
|
75
|
samer@0
|
76 for (int k=0; k<(n-m); k++) {
|
samer@0
|
77 int j=inactive[k];
|
samer@0
|
78 if (P.g[j]<grad) {
|
samer@0
|
79 grad=P.g[j];
|
samer@0
|
80 imax=j;
|
samer@0
|
81 }
|
samer@0
|
82 }
|
samer@0
|
83
|
samer@0
|
84 if (imax!=-1) { activate(imax); released=imax; return true; }
|
samer@0
|
85 else return false;
|
samer@0
|
86 }
|
samer@0
|
87
|
samer@0
|
88 public int getReleasedDimension() { return released; }
|
samer@0
|
89
|
samer@0
|
90 /**
|
samer@0
|
91 Take a step but make sure none of the coordinates
|
samer@0
|
92 becomes negative. This function returns true if
|
samer@0
|
93 any dimensions were inactivated - implying that
|
samer@0
|
94 we should finish the line search. The alternative
|
samer@0
|
95 is that even the clipped step was too long and
|
samer@0
|
96 we need to interpolate some more.
|
samer@0
|
97 */
|
samer@0
|
98
|
samer@0
|
99 public boolean clipStep(double beta)
|
samer@0
|
100 {
|
samer@0
|
101
|
samer@0
|
102 step(beta);
|
samer@0
|
103
|
samer@0
|
104
|
samer@0
|
105 // got to find sign swappers
|
samer@0
|
106 int imin=-1;
|
samer@0
|
107 double alphamin=beta; // ??
|
samer@0
|
108
|
samer@0
|
109 for (int k=0; k<m; k++) {
|
samer@0
|
110 int i=active[k];
|
samer@0
|
111 if (S.P2.x[i]<=XEPS) {
|
samer@0
|
112 double alpha=-S.P1.x[i]/S.h[i];
|
samer@0
|
113 if (imin==-1 || alpha<alphamin) {
|
samer@0
|
114 imin=i;
|
samer@0
|
115 alphamin=alpha;
|
samer@0
|
116 }
|
samer@0
|
117 }
|
samer@0
|
118 }
|
samer@0
|
119
|
samer@0
|
120 // if no negative values, evaluate and return
|
samer@0
|
121 if (imin==-1) { S.eval2(); return false; }
|
samer@0
|
122
|
samer@0
|
123 // atlease one dimension has become
|
samer@0
|
124 // zero or negative. imin was the first
|
samer@0
|
125 // what if alphamin=0?
|
samer@0
|
126 step(alphamin);
|
samer@0
|
127
|
samer@0
|
128 // now we should check for ANY unconstrained
|
samer@0
|
129 // x[i] being less than XEPS, and set it to
|
samer@0
|
130 // exactly zero, including, obviously x[j]
|
samer@0
|
131 int numzerod=0;
|
samer@0
|
132 for (int k=0; k<m; k++) {
|
samer@0
|
133 int j=active[k];
|
samer@0
|
134 if (S.P2.x[j]<=XEPS) {
|
samer@0
|
135 S.P2.x[j]=0;
|
samer@0
|
136 zerod[numzerod++]=j;
|
samer@0
|
137 }
|
samer@0
|
138 }
|
samer@0
|
139
|
samer@0
|
140 eval2();
|
samer@0
|
141
|
samer@0
|
142 // next, check zeroed dimensions
|
samer@0
|
143 // for constraint eligibilty
|
samer@0
|
144 boolean flag=false;
|
samer@0
|
145
|
samer@0
|
146 for (int k=0; k<numzerod; k++) {
|
samer@0
|
147 int j=zerod[k];
|
samer@0
|
148 if (S.P2.g[j]>=-GEPS) {
|
samer@0
|
149 inactivate(j);
|
samer@0
|
150 flag=true;
|
samer@0
|
151 }
|
samer@0
|
152 }
|
samer@0
|
153
|
samer@0
|
154 return flag;
|
samer@0
|
155 }
|
samer@0
|
156
|
samer@0
|
157
|
samer@0
|
158 public void lineSearch(Condition convergence, CubicLineSearch ls, double beta0)
|
samer@0
|
159 {
|
samer@0
|
160 if (clipStep(beta0)) return;
|
samer@0
|
161
|
samer@0
|
162 while (!convergence.test()) {
|
samer@0
|
163 // formulate any other direction change conditions
|
samer@0
|
164
|
samer@0
|
165 if (S.P2.f<S.P1.f && S.P2.s<0) {
|
samer@0
|
166 double beta=ls.extrapolate();
|
samer@0
|
167 S.move();
|
samer@0
|
168 if (clipStep(beta)) break;
|
samer@0
|
169 } else {
|
samer@0
|
170 // since both P1 and P2 must satisfy positivity
|
samer@0
|
171 // constraints, all points between them do alse,
|
samer@0
|
172 // so no worries about interpolation
|
samer@0
|
173 step(ls.interpolate());
|
samer@0
|
174 eval2();
|
samer@0
|
175 }
|
samer@0
|
176 }
|
samer@0
|
177 }
|
samer@0
|
178 }
|
samer@0
|
179
|