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