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 import samer.core.util.heavy.*;
|
samer@0
|
15
|
samer@0
|
16 /**
|
samer@0
|
17 Constrained minimiser.
|
samer@0
|
18
|
samer@0
|
19 - ConjugateGradient
|
samer@0
|
20 - OR Quasi-newton (using GillMurray uydates)
|
samer@0
|
21 - Safeguarded cubic interpolation line search using gradients
|
samer@0
|
22
|
samer@0
|
23 We expect a Class object to be in object Space
|
samer@0
|
24 to tell us what kind of constraints to create
|
samer@0
|
25 */
|
samer@0
|
26
|
samer@0
|
27
|
samer@0
|
28 public class ConstrainedMinimiser extends MinimiserBase implements Agent
|
samer@0
|
29 {
|
samer@0
|
30 ConstrainedGillMurray dir;
|
samer@0
|
31 // ConstrainedConjGrad dir;
|
samer@0
|
32 Constraints cons; // handles line search
|
samer@0
|
33 VDouble percentage;
|
samer@0
|
34 boolean toggle=false;
|
samer@0
|
35
|
samer@0
|
36 /** expected stack top: Vec, Functionx, Class */
|
samer@0
|
37 public ConstrainedMinimiser(Vec v, Functionx f, Constraints.Factory constraintFactory)
|
samer@0
|
38 {
|
samer@0
|
39 super(v,f);
|
samer@0
|
40 cons = constraintFactory.build(this);
|
samer@0
|
41 init();
|
samer@0
|
42 }
|
samer@0
|
43
|
samer@0
|
44 public ConstrainedMinimiser(Vec v, Functionx f, Class conscl)
|
samer@0
|
45 {
|
samer@0
|
46 super(v,f);
|
samer@0
|
47
|
samer@0
|
48 if (conscl==ZeroCrossingSparsity.class) {
|
samer@0
|
49 cons = new ZeroCrossingSparsity(this);
|
samer@0
|
50 } else if (conscl==Positivity.class) {
|
samer@0
|
51 cons = new Positivity(this);
|
samer@0
|
52 } else {
|
samer@0
|
53 throw new Error("Unrecognised constrain class: "+conscl);
|
samer@0
|
54 }
|
samer@0
|
55 init();
|
samer@0
|
56 }
|
samer@0
|
57
|
samer@0
|
58 private void init() {
|
samer@0
|
59 dir = new ConstrainedGillMurray(this,cons);
|
samer@0
|
60 // dir = new ConstrainedConjGrad(this,cons);
|
samer@0
|
61 percentage=new VDouble("releaseFactor",0.01);
|
samer@0
|
62
|
samer@0
|
63 // add( dir.hessin.viewable());
|
samer@0
|
64 add( percentage);
|
samer@0
|
65 cons.activateAll();
|
samer@0
|
66 }
|
samer@0
|
67
|
samer@0
|
68 public void setHessian(Jama.Matrix H) { dir.setInitialHessian(H); }
|
samer@0
|
69
|
samer@0
|
70 public void getCommands(Agent.Registry r) {
|
samer@0
|
71 super.getCommands(r);
|
samer@0
|
72 r.add("all").add("run");
|
samer@0
|
73 r.add("report").add("release").add("resetHess");
|
samer@0
|
74 }
|
samer@0
|
75
|
samer@0
|
76 public void execute(String cmd, Environment env) throws Exception
|
samer@0
|
77 {
|
samer@0
|
78 if (cmd.equals("run")) run();
|
samer@0
|
79 else if (cmd.equals("report")) cons.report();
|
samer@0
|
80 else if (cmd.equals("release")) releaseDimensions(P1);
|
samer@0
|
81 else if (cmd.equals("all")) {
|
samer@0
|
82 toggle = X._bool(env.datum(),!toggle);
|
samer@0
|
83 if (toggle) cons.activateAll();
|
samer@0
|
84 else cons.deactivateAll();
|
samer@0
|
85 } else if (cmd.equals("resetHess")) {
|
samer@0
|
86 dir.resetHessian();
|
samer@0
|
87 } else super.execute(cmd,env);
|
samer@0
|
88 }
|
samer@0
|
89
|
samer@0
|
90 private boolean releaseDimensions(Datum P)
|
samer@0
|
91 {
|
samer@0
|
92 if (cons.release(P)) {
|
samer@0
|
93 dir.resetDimension(cons.getReleasedDimension());
|
samer@0
|
94
|
samer@0
|
95 int p=cons.getReleasableDimensions()-1;
|
samer@0
|
96
|
samer@0
|
97 // going to release a percentage of releasable dims?
|
samer@0
|
98 // or absolute number?
|
samer@0
|
99 p=(int)(percentage.value*p);
|
samer@0
|
100 // if (p>1) p=1;
|
samer@0
|
101 for (; p>0; p--) {
|
samer@0
|
102 cons.release(P);
|
samer@0
|
103 dir.resetDimension(cons.getReleasedDimension());
|
samer@0
|
104 }
|
samer@0
|
105
|
samer@0
|
106 return true;
|
samer@0
|
107 }
|
samer@0
|
108 return false;
|
samer@0
|
109 }
|
samer@0
|
110
|
samer@0
|
111 public void run()
|
samer@0
|
112 {
|
samer@0
|
113 double beta;
|
samer@0
|
114 int i, maxiter=getMaxiter();
|
samer@0
|
115 boolean triedSteepest=false;
|
samer@0
|
116
|
samer@0
|
117 // we start from the current state instead.
|
samer@0
|
118 // cons.initialise should set up the constraints
|
samer@0
|
119 // to reflect the current state.
|
samer@0
|
120 cons.initialise();
|
samer@0
|
121
|
samer@0
|
122 evaluate();
|
samer@0
|
123 releaseDimensions(P1);
|
samer@0
|
124
|
samer@0
|
125 if (cons.activeCount()==0) {
|
samer@0
|
126 iters.next(0);
|
samer@0
|
127 sig3.off();
|
samer@0
|
128 return;
|
samer@0
|
129 }
|
samer@0
|
130
|
samer@0
|
131
|
samer@0
|
132 sig1.off();
|
samer@0
|
133
|
samer@0
|
134 // must reset hessian for active dimensions
|
samer@0
|
135 cons.zeroInactive(P2.x);
|
samer@0
|
136 dir.resetHessian();
|
samer@0
|
137 dir.hessin.changed();
|
samer@0
|
138 dir.init();
|
samer@0
|
139 setSlope();
|
samer@0
|
140 beta = initialStep();
|
samer@0
|
141 // beta = beta.value; ??
|
samer@0
|
142
|
samer@0
|
143 for (i=0; i<maxiter; i++) {
|
samer@0
|
144
|
samer@0
|
145 // constrained line search with initial step beta0
|
samer@0
|
146 lstest.init();
|
samer@0
|
147 cons.lineSearch(lstest,ls,beta);
|
samer@0
|
148 lsiters.next(lstest.count);
|
samer@0
|
149 steplength.next(alpha);
|
samer@0
|
150
|
samer@0
|
151 if (lstest.tiny && (P2.f>=P1.f)) {
|
samer@0
|
152 // tiny step was no good
|
samer@0
|
153 sig1.on();
|
samer@0
|
154 sig2.off();
|
samer@0
|
155 if (gconv.isSatisfied(P1.g,cons)) break;
|
samer@0
|
156 if (triedSteepest) break;
|
samer@0
|
157 sig2.on();
|
samer@0
|
158
|
samer@0
|
159 beta = this.beta.value;
|
samer@0
|
160 dir.update(); // ??
|
samer@0
|
161 if (dir.uvc) dir.init();
|
samer@0
|
162 else dir.steepest();
|
samer@0
|
163 setSlope();
|
samer@0
|
164 triedSteepest=true;
|
samer@0
|
165 continue;
|
samer@0
|
166 }
|
samer@0
|
167
|
samer@0
|
168
|
samer@0
|
169 // check gradients at P2
|
samer@0
|
170 if (!releaseDimensions(P2)) {
|
samer@0
|
171 // don't quit if any dimensions released
|
samer@0
|
172 if (cons.activeCount()==0) break;
|
samer@0
|
173 if (xfconv.isSatisfied(this)) {
|
samer@0
|
174 if (gconv.isSatisfied(P2.g,cons)) break;
|
samer@0
|
175 }
|
samer@0
|
176 }
|
samer@0
|
177
|
samer@0
|
178 // beta = beta.value;
|
samer@0
|
179 beta = nextStep();
|
samer@0
|
180 dir.update();
|
samer@0
|
181 move();
|
samer@0
|
182 perIteration();
|
samer@0
|
183 }
|
samer@0
|
184
|
samer@0
|
185 perOptimisation(i);
|
samer@0
|
186 dir.hessin.changed();
|
samer@0
|
187 }
|
samer@0
|
188 }
|
samer@0
|
189
|
samer@0
|
190
|
samer@0
|
191
|
samer@0
|
192
|