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 package ffx.xray;
39
40 import ffx.algorithms.Terminatable;
41 import ffx.crystal.ReflectionList;
42 import ffx.numerics.optimization.LBFGS;
43 import ffx.numerics.optimization.LineSearch.LineSearchResult;
44 import ffx.numerics.optimization.OptimizationListener;
45 import ffx.xray.SplineEnergy.SplineType;
46
47 import javax.annotation.Nullable;
48 import java.util.logging.Level;
49 import java.util.logging.Logger;
50
51 import static ffx.utilities.Constants.NS2SEC;
52 import static java.lang.String.format;
53 import static java.lang.System.arraycopy;
54
55
56
57
58
59
60
61 public class SplineMinimize implements OptimizationListener, Terminatable {
62
63 private static final Logger logger = Logger.getLogger(SplineEnergy.class.getName());
64
65 private final SplineEnergy splineEnergy;
66 private final SplineType splineType;
67 private final int n;
68 private final double[] x;
69 private final double[] grad;
70 private final double[] scaling;
71 private boolean done = false;
72 private boolean terminate = false;
73 private long time;
74 private double grms;
75 private int nSteps;
76
77
78
79
80
81
82
83
84
85 public SplineMinimize(ReflectionList reflectionList,
86 DiffractionRefinementData refinementData, double[] x, SplineType type) {
87 this.x = x;
88 this.splineType = type;
89 n = x.length;
90 splineEnergy = new SplineEnergy(reflectionList, refinementData, n, type);
91 grad = new double[n];
92 scaling = new double[n];
93 for (int i = 0; i < n; i++) {
94 if (type == SplineType.FOTOESQ || type == SplineType.FCTOESQ) {
95 x[i] = 0.1;
96 } else {
97 x[i] = 1.0;
98 }
99 scaling[i] = 1.0;
100 }
101 }
102
103
104
105
106
107
108
109 public double[] getCoordinates(@Nullable double[] x) {
110 if (x == null) {
111 x = new double[this.x.length];
112 }
113 arraycopy(this.x, 0, x, 0, this.x.length);
114 return x;
115 }
116
117
118
119
120
121
122 public int getNumberOfVariables() {
123 return x.length;
124 }
125
126
127
128
129
130
131
132 public SplineEnergy minimize(double eps) {
133 return minimize(7, eps);
134 }
135
136
137
138
139
140
141
142
143 public SplineEnergy minimize(int m, double eps) {
144
145 splineEnergy.setScaling(scaling);
146
147 double e = splineEnergy.energyAndGradient(x, grad);
148
149 done = false;
150 time = -System.nanoTime();
151 int status = LBFGS.minimize(n, m, x, e, grad, eps, splineEnergy, this);
152 done = true;
153 switch (status) {
154 case 0:
155 logger.fine(format("\n Optimization achieved convergence criteria: %8.5f\n", grms));
156 break;
157 case 1:
158 logger.fine(format("\n Optimization terminated at step %d.\n", nSteps));
159 break;
160 default:
161 logger.warning("\n Spline Optimization failed.\n");
162 }
163
164 splineEnergy.setScaling(null);
165
166 return splineEnergy;
167 }
168
169
170
171
172 @Override
173 public boolean optimizationUpdate(int iter, int nBFGS, int nfun, double grms, double xrms, double f,
174 double df, double angle, LineSearchResult info) {
175
176 long currentTime = System.nanoTime();
177 Double seconds = (currentTime - time) * NS2SEC;
178 time = currentTime;
179 this.grms = grms;
180 this.nSteps = iter;
181
182 Level level = Level.FINE;
183
184 if (logger.isLoggable(level)) {
185 if (iter == 0) {
186 String name = splineType.toString();
187 if (nBFGS > 0) {
188 logger.log(level, format("\n Limited Memory BFGS Quasi-Newton Optimization of %s", name));
189 } else {
190 logger.log(level, format("\n Steepest Decent Optimization of %s", name));
191 }
192 logger.log(level, format(" Number of Parameters: %d\n", n));
193 logger.log(level," Cycle Energy G RMS Delta E Delta X Angle Evals Time");
194 }
195 if (info == null) {
196 logger.log(level, format("%6d %12.2e %10.2e", iter, f, grms));
197 } else {
198 if (info == LineSearchResult.Success) {
199 logger.log(level, format("%6d %12.2e %10.2e %10.5e %9.5f %8.2f %6d %8.3f",
200 iter, f, grms, df, xrms, angle, nfun, seconds));
201 } else {
202 logger.log(level, format("%6d %12.2e %10.2e %10.5e %9.5f %8.2f %6d %8s",
203 iter, f, grms, df, xrms, angle, nfun, info));
204 }
205 }
206 }
207
208 if (terminate) {
209 logger.info(" The optimization received a termination request.");
210
211 return false;
212 }
213 return true;
214 }
215
216
217
218
219 @Override
220 public void terminate() {
221 terminate = true;
222 while (!done) {
223 synchronized (this) {
224 try {
225 wait(1);
226 } catch (Exception e) {
227 logger.log(Level.WARNING, "Exception terminating minimization.\n", e);
228 }
229 }
230 }
231 }
232
233
234
235
236
237
238 SplineEnergy getSplineEnergy() {
239 return splineEnergy;
240 }
241 }