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.*;
|
samer@0
|
15 import samer.tools.*;
|
samer@0
|
16 import samer.core.util.swing.*;
|
samer@0
|
17 import java.awt.*;
|
samer@0
|
18 import java.util.*;
|
samer@0
|
19
|
samer@0
|
20 /**
|
samer@0
|
21 This is a base class for running multidimensional optimisation
|
samer@0
|
22 It requires the following objects to exist in object space
|
samer@0
|
23 (they are used by the State base class default constructor)
|
samer@0
|
24
|
samer@0
|
25 Functionx "functionx": the function to be minimised
|
samer@0
|
26 VVector "vector": the vector to work with
|
samer@0
|
27
|
samer@0
|
28 ConstrainedMinimiser also requires "constraintClass" to
|
samer@0
|
29 exist.
|
samer@0
|
30
|
samer@0
|
31 */
|
samer@0
|
32
|
samer@0
|
33
|
samer@0
|
34 public abstract class MinimiserBase extends State implements SafeTask, Agent
|
samer@0
|
35 {
|
samer@0
|
36 // private Node node;
|
samer@0
|
37
|
samer@0
|
38 protected VVector x1,x2,g1,g2,vh;
|
samer@0
|
39 protected VDouble beta; // initial step length
|
samer@0
|
40 protected CubicLineSearch ls;
|
samer@0
|
41 protected LSCondition lstest; // convergence test for line search
|
samer@0
|
42 protected AbsXFConvergence xfconv; // convergence test for optimisation
|
samer@0
|
43 protected GConvergence gconv;
|
samer@0
|
44 protected double XTOL=1e-4;
|
samer@0
|
45 protected VInteger vmaxiter;
|
samer@0
|
46 protected boolean flange; // signal vector changes every iteration
|
samer@0
|
47
|
samer@0
|
48 protected Meter lsiters, iters;
|
samer@0
|
49 protected Meter steplength;
|
samer@0
|
50 protected LED sig1, sig2, sig3;
|
samer@0
|
51
|
samer@0
|
52 private LinkedList<Viewable> viewables;
|
samer@0
|
53
|
samer@0
|
54 public MinimiserBase(Vec x, Functionx func)
|
samer@0
|
55 {
|
samer@0
|
56 super(x, func);
|
samer@0
|
57
|
samer@0
|
58 // node = new Node("Minimiser");
|
samer@0
|
59 //Shell.push(node);
|
samer@0
|
60
|
samer@0
|
61 boolean oldreg=Shell.setAutoRegister(false);
|
samer@0
|
62 viewables = new LinkedList<Viewable>();
|
samer@0
|
63
|
samer@0
|
64 x1 = new VVector("x1", P1.x); // independent view?
|
samer@0
|
65 x2 = new VVector("x2", P2.x);
|
samer@0
|
66 g1 = new VVector("g1", P1.g);
|
samer@0
|
67 g2 = new VVector("g2", P2.g);
|
samer@0
|
68 vh = new VVector("h", h);
|
samer@0
|
69 beta = new VDouble("beta",1);
|
samer@0
|
70 vmaxiter=new VInteger("maxiter",400);
|
samer@0
|
71 xfconv=new AbsXFConvergence();
|
samer@0
|
72 gconv=new GConvergence();
|
samer@0
|
73 gconv.setGTolerance(0.005);
|
samer@0
|
74 flange=Shell.getBoolean("vprogress",false);
|
samer@0
|
75 ls = new CubicLineSearch(this);
|
samer@0
|
76 ls.setSafeguardFactor(0.125);
|
samer@0
|
77 lstest = new LSCondition();
|
samer@0
|
78
|
samer@0
|
79 steplength = createMeter("step length",2,false,new Color(200,170,0));
|
samer@0
|
80 lsiters = createMeter("line search iterations",20,false,new Color(90,100,255));
|
samer@0
|
81 iters = createMeter("iterations",2*x1.size(), true, new Color(200,50,0));
|
samer@0
|
82 sig1 = new LED(new Color(240,190,20));
|
samer@0
|
83 sig2 = new LED(new Color(90,100,255));
|
samer@0
|
84 sig3 = new LED(new Color(250,60,20));
|
samer@0
|
85 sig1.setToolTipText("Tiny line search step");
|
samer@0
|
86 sig2.setToolTipText("Resetting Hessian, trying steepest descent");
|
samer@0
|
87 sig3.setToolTipText("Maximum iterations reached");
|
samer@0
|
88
|
samer@0
|
89
|
samer@0
|
90 // register some viewables locally
|
samer@0
|
91 // add(x1); add(x2); add(g1); add(g2); add(vh);
|
samer@0
|
92 add(beta);
|
samer@0
|
93 add(vmaxiter);
|
samer@0
|
94
|
samer@0
|
95 add(new VParameter("xtol", new Parameter() {
|
samer@0
|
96 public void setParameter(double t) {
|
samer@0
|
97 xfconv.setXTolerance(t);
|
samer@0
|
98 XTOL=t;
|
samer@0
|
99 }
|
samer@0
|
100 } )
|
samer@0
|
101 );
|
samer@0
|
102
|
samer@0
|
103 add(new VParameter("ftol", new Parameter() {
|
samer@0
|
104 public void setParameter(double t) {
|
samer@0
|
105 xfconv.setFTolerance(t);
|
samer@0
|
106 }
|
samer@0
|
107 } )
|
samer@0
|
108 );
|
samer@0
|
109
|
samer@0
|
110 add(new VParameter("gtol", new Parameter() {
|
samer@0
|
111 public void setParameter(double t) {
|
samer@0
|
112 gconv.setGTolerance(t);
|
samer@0
|
113 }
|
samer@0
|
114 } )
|
samer@0
|
115 );
|
samer@0
|
116
|
samer@0
|
117 add(new VParameter("ZETA", new Parameter() {
|
samer@0
|
118 public void setParameter(double t) {
|
samer@0
|
119 ls.setSafeguardFactor(t);
|
samer@0
|
120 }
|
samer@0
|
121 } )
|
samer@0
|
122 );
|
samer@0
|
123 Shell.setAutoRegister(oldreg);
|
samer@0
|
124 // Shell.pop();
|
samer@0
|
125 }
|
samer@0
|
126
|
samer@0
|
127 public Viewer getViewer() {
|
samer@0
|
128 return new VPanel() {
|
samer@0
|
129 {
|
samer@0
|
130 setLayout( new StackLayout());
|
samer@0
|
131 // add(Shell.createButtonsFor(MinimiserBase.this));
|
samer@0
|
132
|
samer@0
|
133 // set default border for meterbox and signal box?
|
samer@0
|
134 VPanel meterbox = new VPanel();
|
samer@0
|
135 //meterbox.setChildBorder(BorderFactory.createLoweredBevelBorder());
|
samer@0
|
136 meterbox.setLayout( new StackLayout(8));
|
samer@0
|
137 meterbox.add(steplength);
|
samer@0
|
138 meterbox.add(iters);
|
samer@0
|
139 meterbox.add(lsiters);
|
samer@0
|
140
|
samer@0
|
141 VPanel signalbox = new VPanel();
|
samer@0
|
142 //signalbox.setChildBorder(BorderFactory.createLoweredBevelBorder());
|
samer@0
|
143 signalbox.setLayout( new FlowLayout(FlowLayout.LEFT));
|
samer@0
|
144 signalbox.add(sig1);
|
samer@0
|
145 signalbox.add(sig2);
|
samer@0
|
146 signalbox.add(sig3);
|
samer@0
|
147
|
samer@0
|
148 add(meterbox);
|
samer@0
|
149 add(signalbox);
|
samer@0
|
150
|
samer@0
|
151 add(x1); add(x2); add(g1); add(g2); add(vh);
|
samer@0
|
152 for (Iterator<Viewable> it=viewables.iterator(); it.hasNext();) {
|
samer@0
|
153 add(it.next());
|
samer@0
|
154 }
|
samer@0
|
155 // now add all other viewables
|
samer@0
|
156 }
|
samer@0
|
157 };
|
samer@0
|
158 }
|
samer@0
|
159
|
samer@0
|
160 public void dispose() { super.dispose(); }
|
samer@0
|
161
|
samer@0
|
162 public void add(Viewable vbl) { viewables.add(vbl); }
|
samer@0
|
163 public Viewable[] getViewables() { return viewables.toArray(new Viewable[0]); }
|
samer@0
|
164
|
samer@0
|
165 public int getMaxiter() { return vmaxiter.value; }
|
samer@0
|
166 protected void perIteration() { if (flange) x1.changed(); }
|
samer@0
|
167 protected void perOptimisation(int i) {
|
samer@0
|
168 if (P2.f<=P1.f) {
|
samer@0
|
169 move();
|
samer@0
|
170 if (flange) x1.changed();
|
samer@0
|
171 }
|
samer@0
|
172
|
samer@0
|
173 iters.next(i);
|
samer@0
|
174 if (i<vmaxiter.value) sig3.off();
|
samer@0
|
175 else sig3.on();
|
samer@0
|
176 }
|
samer@0
|
177
|
samer@0
|
178 public void starting() {}
|
samer@0
|
179 public void stopping() {}
|
samer@0
|
180
|
samer@0
|
181 public void getCommands(Agent.Registry r) {
|
samer@0
|
182 r.add("eval").add("step").add("move").add("turn").add("info");
|
samer@0
|
183 }
|
samer@0
|
184
|
samer@0
|
185 public void execute(String cmd, Environment env) throws Exception
|
samer@0
|
186 {
|
samer@0
|
187 if (cmd.equals("step")) {
|
samer@0
|
188 step(beta.value);
|
samer@0
|
189 g2.changed();
|
samer@0
|
190 x2.changed();
|
samer@0
|
191 } else if (cmd.equals("info")) Shell.print(toString());
|
samer@0
|
192 else if (cmd.equals("move")) {
|
samer@0
|
193 steplength.next(alpha);
|
samer@0
|
194 move();
|
samer@0
|
195 x1.changed();
|
samer@0
|
196 g1.changed();
|
samer@0
|
197 } else if (cmd.equals("eval")) {
|
samer@0
|
198 evaluate();
|
samer@0
|
199 x1.changed();
|
samer@0
|
200 g1.changed();
|
samer@0
|
201 setSlope();
|
samer@0
|
202 } else if (cmd.equals("turn")) {
|
samer@0
|
203 Mathx.negate(P1.g,h);
|
samer@0
|
204 setSlope();
|
samer@0
|
205 vh.changed();
|
samer@0
|
206 }
|
samer@0
|
207 }
|
samer@0
|
208
|
samer@0
|
209 class LSCondition implements Condition
|
samer@0
|
210 {
|
samer@0
|
211 double MU=1e-4; // ensure function decreases enough
|
samer@0
|
212 double ETA=0.1; // ensure gradient is smaller than last
|
samer@0
|
213 int count;
|
samer@0
|
214 boolean tiny;
|
samer@0
|
215
|
samer@0
|
216 LSCondition()
|
samer@0
|
217 {
|
samer@0
|
218 add(new VParameter("ETA",new DoubleModel() {
|
samer@0
|
219 public double get() { return ETA; }
|
samer@0
|
220 public void set(double t) { ETA=t; }
|
samer@0
|
221 } )
|
samer@0
|
222 );
|
samer@0
|
223 }
|
samer@0
|
224
|
samer@0
|
225 public void init() { tiny=false; count=0; }
|
samer@0
|
226 public boolean test()
|
samer@0
|
227 {
|
samer@0
|
228 if (count++>96) {
|
samer@0
|
229 Shell.trace("\n**** LINE SEARCH OVERRUN ****\n");
|
samer@0
|
230 return true;
|
samer@0
|
231 }
|
samer@0
|
232 if (alpha*normh<XTOL) { tiny=true; return true; }
|
samer@0
|
233 return (P2.f<P1.f+MU*alpha*P1.s) && (Math.abs(P2.s)<-ETA*P1.s);
|
samer@0
|
234 }
|
samer@0
|
235 }
|
samer@0
|
236
|
samer@0
|
237 private static Meter createMeter(String label, double max, boolean reinit, Color color) {
|
samer@0
|
238 Shell.push(label);
|
samer@0
|
239 Meter m=new Meter();
|
samer@0
|
240 m.setForeground(color);
|
samer@0
|
241 m.setBackground(color.darker().darker());
|
samer@0
|
242 m.getMap().setDomain(0,max);
|
samer@0
|
243 m.setToolTipText(label);
|
samer@0
|
244 m.exposeMap(reinit);
|
samer@0
|
245 Shell.pop();
|
samer@0
|
246 return m;
|
samer@0
|
247 }
|
samer@0
|
248 }
|