-
Notifications
You must be signed in to change notification settings - Fork 1
/
healernoninv.m
260 lines (208 loc) · 9.05 KB
/
healernoninv.m
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
function [outpattern, details, factor] = healer(pattern, support, bkg, initguess, alg, numrounds, qbarrier, nzpenalty, iters, tols, nowindow)
% Main COACS function.
% pattern, the pattern to phase
% support, the support mask (in autocorrelation space)
% bkg, background signal, support for non-zero values here basically stale at this point
% initguess, start guess for the pattern
% alg, the TFOCS algorithm to use
% numrounds, the number of outermost iterations
% qbarrier, the qbarrier (2 * l) in each round
% nzpenalty, the penalty constant outside of the support
% iters, number of TFOCS iterations within the round
% tols, the tolerance used to determine end of iteration in TFOCS
% Acceleration and continuation adapted to COACS is also used, but hardcoded.
if nargin < 11
nowindow = []
end
if isempty(nowindow)
nowindow = 0;
end
iterfactor = 1.1;
% Handle scalars
nzpenalty = ones(1, numrounds) .* nzpenalty;
qbarrier = ones(1, numrounds) .* qbarrier;
% Everything needs to be square and the same dimension
[dims, side2, fullsize, pshape, cshape] = getdims(pattern);
origpattern = pattern;
pattern = reshape(pattern, fullsize, 1);
opts = tfocs;
opts.alg = alg;
% Note, the tolerance will be dependent on the accuracy of the (double precision) FFT
% which essentially sums side2^dims entries (succession of two side2 sums)
opts.maxmin = 1;
opts.restart = 5e5;
opts.countOps = 1;
opts.printStopCrit = 1;
opts.printEvery = 2500;
% Use "no regress" restart option
opts.restart = -10000000;
% Special hack in our version of TFOCS to accept mode where both
% objective function and gradient are checked when determining no-regress option
% Change to only 'fun' if your version does not support this.
opts.autoRestart = 'fun';
mask = [reshape(support, pshape) 0 * reshape(support, pshape)];
mask = reshape(mask, fullsize * 2,1);
% Purely real, i.e. zero mask in imaginary space
ourlinpflat = jackdawlinop(origpattern,1);
% No windowing used within linop [for now]
ourlinp = ourlinpflat;
global factor
global basepenalty
if isempty(initguess)
initguess = pattern(:);
initguess(initguess < 0) = 0;
end
x = reshape(initguess, fullsize, 1);
xprev = x;
y = x;
jval = 0;
% No actual filter windowing used, window integrated in the scale in diffpoisson instead
filter = ones(fullsize, 1);
rfilter = 1./filter;
for outerround=1:numrounds
if nowindow == 1
factor = ones(65536, 1);
basepenalty = 1 - mask;
else
[factor, basepenalty] = createwindows(origpattern, mask, qbarrier(outerround));
end
y = y .* factor;
x = x .* factor;
penalty = basepenalty * nzpenalty(outerround);
% Acceleration scheme based on assumption of linear steps in response to decreasing qbarrier
if outerround > 1 && (qbarrier(outerround) ~= qbarrier(outerround - 1))
xprev = xprev .* factor;
if (jval > 0)
diffx = x + (x - xprev) .* (qbarrier(outerround) / qbarrier(outerround - 1));
smoothop = diffpoisson(factor, pattern(:), diffx(:), bkg(:), diffx, filter, qbarrier(outerround));
[proxop, diffxt, level, xlevel] = createproxop(diffx, penalty, ourlinp);
newstep = ourlinp(x - xprev, 2);
negstep = -newstep;
negstep(penalty == 0) = 0;
newstep(penalty > 0) = 0;
negstep = ourlinp(negstep, 1);
newstep = ourlinp(newstep, 1);
y = x;
y = y + halfboundedlinesearch((newstep), @(z) (smoothop(z + (y-diffx))));
step = norm(y - x)
y = y + halfboundedlinesearch(negstep, @(z) (smoothop(z + (y-diffx)) + proxop(ourlinp(z + (y-diffx-xlevel), 2))));
step2 = norm(y - x)
y = y + halfboundedlinesearch(-negstep, @(z) (smoothop(z + (y-diffx)) + proxop(ourlinp(z + (y-diffx-xlevel), 2))));
step3 = norm(y - x)
y = y + halfboundedlinesearch((x - xprev), @(z) (smoothop(z + (y-diffx)) + proxop(ourlinp(z + (y-diffx-xlevel), 2))));
step4 = norm(y - x)
y = y + halfboundedlinesearch(negstep, @(z) (smoothop(z + (y-diffx)) + proxop(ourlinp(z + (y-diffx-xlevel), 2))));
step5 = norm(y - x)
y = y + halfboundedlinesearch(-negstep, @(z) (smoothop(z + (y-diffx)) + proxop(ourlinp(z + (y-diffx-xlevel), 2))));
step6 = norm(y - x)
y = y + halfboundedlinesearch((newstep), @(z) (smoothop(z + (y-diffx))));
step7 = norm(y - x)
%smoothop2 = diffpoisson(factor, pattern(:), diffx(:), bkg(:), diffx, filter, qbarrier(outerround));
%y = y + halfboundedlinesearch((x - xprev), @(z) (smoothop2(z + (y-diffx))));
y = y + halfboundedlinesearch((x - xprev), @(z) (smoothop(z + (y-diffx)) + proxop(ourlinp(z + (y-diffx-xlevel), 2))));
step8 = norm(y - x)
end
xprev = x ./ factor;
jval = jval + 1;
end
xprevinner = y;
jvalinner = -1;
opts.maxIts = ceil(iters(outerround) / iterfactor);
while true
% Inner acceleration scheme based on overall difference to previous pre-acceleration start
if jvalinner >= 0
diffx = y;
% TODO: Should bkg(:) be included in diffx???
smoothop = diffpoisson(factor, pattern(:), diffx(:), bkg(:), diffx, filter, qbarrier(outerround));
[proxop, diffxt, level, xlevel] = createproxop(diffx, penalty, ourlinp);
x = y + halfboundedlinesearch((y - xprevinner), @(x) (smoothop(x) + proxop(ourlinp(x - xlevel, 2))));
else
x = y;
end
xprevinner = y;
jvalinner = jvalinner + 1;
opts.maxIts = ceil(opts.maxIts * iterfactor);
opts.tol = tols(outerround);
opts.L0 = 2 ./ qbarrier(outerround);
opts.Lexact = opts.L0 * sqrt(96*96*96);
opts.alpha = 0.1;
opts.beta = 0.1;
diffx = x;
% TODO: Should bkg(:) be included in diffx???
smoothop = diffpoisson(factor, pattern(:), diffx(:), bkg(:), diffx, filter, qbarrier(outerround));
[proxop, diffxt, level, xlevel] = createproxop(diffx, penalty, ourlinp);
qbarrier(outerround)
[x,out] = tfocs({smoothop}, {ourlinp,xlevel}, proxop, -level * 1, opts);
xtupdate = x;
x = ourlinp(x,1);
xrtnorm = norm(xtupdate - ourlinp(x, 2))
xstep = x;
xupdate = x + xlevel;
oldy = y;
prevstep = xprevinner - diffx;
levelprevdiff = norm(prevstep)
y = (xupdate(:)) + diffx(:);
% Acceleration step continuing in the same direction
y = y + halfboundedlinesearch(xupdate, @(x) (smoothop(x + xupdate(:)) + proxop(ourlinp(x + xstep, 2))));
smoothop(y - diffx(:))
pstep = proxop(ourlinp(y - (diffx(:) + xlevel(:)), 2))
smoothop(0 * diffx(:))
proxop(ourlinp(-xlevel(:), 2))
proxop(-level)
olddiffx = diffx;
diffx = y;
normdiff1 = norm(ourlinp(level(:), 1) - xlevel(:))
normdiff2 = norm(level(:) + ourlinp(-xlevel(:), 2))
norm(level(:))
smoothop = diffpoisson(factor, pattern(:), diffx(:), bkg(:), diffx, filter, qbarrier(outerround));
[proxop, diffxt, level, xlevel] = createproxop(diffx, penalty, ourlinp);
levelxdiff = norm(xprevinner - y)
smoothop(olddiffx(:) - diffx(:))
proxop(ourlinp(olddiffx(:) - (diffx(:) + xlevel(:)), 2))
smoothop(0 * diffx(:))
proxop(ourlinp(-xlevel(:), 2))
% Is the distance to the new point from the previous end point, shorter than from the previous end point to the starting point?
% If so, the acceleration step was too large, change to previous starting point and redo.
% Otherwise, divergence is a real risk. This is believed to be a non-issue with the line search scheme now in place.
if levelprevdiff > levelxdiff
% Reset acceleration
%y = xprevinner;
'Do we need to reset acceleration?'
%continue
end
x = y;
global x2;
x2 = x ./ factor;
save x26 x2
% Our step was very small for desired accuracy level, break
%if abs(smoothop(y - diffx) - smoothop(xprevinner(:) - diffx(:)) + proxop(ourlinp(y - (diffx + xlevel), 2)) - proxop(ourlinp(xprevinner(:), 2) - diffxt(:) - level(:))) < 1e-7 / sqrt(qbarrier(outerround))
diffstep = xprevinner - y;
rchange = norm(diffstep(pattern >= 0), 1) / norm(pattern(pattern >= 0) .* factor(pattern >= 0), 1)
if pstep > 0
'Penalty too low, saddle point circus'
break;
end
if jvalinner >= 0 && rchange < 5e-9 * out.niter && ...
abs(smoothop(y - diffx) - smoothop(xprevinner(:) - diffx(:)) + proxop(ourlinp(y - (diffx + xlevel), 2)) - proxop(ourlinp(xprevinner(:), 2) - diffxt(:) - level(:))) < 1e-6 %* sqrt(qbarrier(outerround))
'Next outer iteration'
break
end
if jvalinner > 20
'Going next anyway'
break
end
if out.niter < opts.maxIts
'Reverting maxIts'
% We did a lot of restarts, do not extend maxIts just yet.
opts.maxIts = ceil(opts.maxIts / iterfactor);
end
if outerround < numrounds && qbarrier(outerround) == qbarrier(outerround + 1)
'Not final iter, moving on'
break
end
end
y = y ./ factor;
x = x ./ factor;
end
outpattern = reshape(x, pshape);
details = out;