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.algorithms.optimize.anneal;
39
40
41
42
43
44
45
46
47
48 public class FlatEndAnnealSchedule implements AnnealingSchedule {
49
50 private final AnnealingSchedule middle;
51 private final double tLow;
52 private final double tHigh;
53 private final double lenBefore;
54 private final double lenAfter;
55 private final int totWindows;
56 private final boolean useBefore;
57 private final boolean useAfter;
58 private final String description;
59
60
61
62
63
64
65
66
67
68
69
70
71
72 public FlatEndAnnealSchedule(AnnealingSchedule middle, double tLow, double tHigh,
73 double lengthBefore, double lengthAfter) {
74 assert tLow < tHigh;
75 assert tLow >= 0;
76 assert Double.isFinite(tHigh);
77 assert lengthBefore >= 0;
78 assert lengthAfter >= 0;
79
80 this.middle = middle;
81 this.tLow = tLow;
82 this.tHigh = tHigh;
83 this.lenBefore = lengthBefore;
84 this.lenAfter = lengthAfter;
85
86 int nWin = middle.getNumWindows();
87 useBefore = lengthBefore > 0;
88 if (useBefore) {
89 ++nWin;
90 }
91 useAfter = lengthAfter > 0;
92 if (useAfter) {
93 ++nWin;
94 }
95 totWindows = nWin;
96
97 StringBuilder sb = new StringBuilder(
98 String.format("Flat-ended annealing schedule: starts at %10.4g K, ends at %10.4g K.", tHigh,
99 tLow));
100 if (useBefore) {
101 sb.append(
102 String.format("\nMain annealing is preceded by a %9.3f-long window at %10.4g K", lenBefore,
103 tHigh));
104 }
105 if (useAfter) {
106 sb.append(
107 String.format("\nMain annealing is followed by a %9.3f-long window at %10.4g K", lenAfter,
108 tLow));
109 }
110 sb.append("\nMain annealing schedule: ").append(middle);
111 this.description = sb.toString();
112 }
113
114 @Override
115 public double getHighTemp() {
116 return tHigh;
117 }
118
119 @Override
120 public double getLowTemp() {
121 return tLow;
122 }
123
124 @Override
125 public int getNumWindows() {
126 return totWindows;
127 }
128
129 @Override
130 public double getTemperature(int i) {
131 assert i >= 0 && i < totWindows;
132 if (i == 0 && useBefore) {
133 return tHigh;
134 } else if (i == (totWindows - 1) && useAfter) {
135 return tLow;
136 } else {
137 i = useBefore ? i - 1 : i;
138 return middle.getTemperature(i);
139 }
140 }
141
142 @Override
143 public double[] getTemperatures() {
144 double[] temps = new double[totWindows];
145 for (int i = 0; i < totWindows; i++) {
146 temps[i] = getTemperature(i);
147 }
148 return temps;
149 }
150
151 @Override
152 public double maxWindowLength() {
153 return Math.max(Math.max(lenBefore, lenAfter), middle.maxWindowLength());
154 }
155
156 @Override
157 public double minWindowLength() {
158 double len = middle.minWindowLength();
159 if (useAfter) {
160 len = Math.min(len, lenAfter);
161 }
162 if (useBefore) {
163 len = Math.min(len, lenBefore);
164 }
165 return len;
166 }
167
168 @Override
169 public String toString() {
170 return description;
171 }
172
173 @Override
174 public double totalWindowLength() {
175 return lenBefore + lenAfter + middle.totalWindowLength();
176 }
177
178 @Override
179 public double windowLength(int window) {
180 assert window >= 0 && window < totWindows;
181
182 if (useBefore && window == 0) {
183 return lenBefore;
184 } else if (useAfter && window == (totWindows - 1)) {
185 return lenAfter;
186 } else {
187 window = useBefore ? window - 1 : window;
188 return middle.windowLength(window);
189 }
190 }
191 }