Ansel
0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
ashift_nmsimplex.c
Go to the documentation of this file.
1
/*
2
This file is part of darktable,
3
Copyright (C) 2016 Tobias Ellinghaus.
4
Copyright (C) 2016 Ulrich Pegelow.
5
Copyright (C) 2017 luzpaz.
6
Copyright (C) 2020 Hubert Kowalski.
7
Copyright (C) 2020 Pascal Obry.
8
Copyright (C) 2022 Martin Bařinka.
9
Copyright (C) 2023, 2025 Aurélien PIERRE.
10
11
darktable is free software: you can redistribute it and/or modify
12
it under the terms of the GNU General Public License as published by
13
the Free Software Foundation, either version 3 of the License, or
14
(at your option) any later version.
15
16
darktable is distributed in the hope that it will be useful,
17
but WITHOUT ANY WARRANTY; without even the implied warranty of
18
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
GNU General Public License for more details.
20
21
You should have received a copy of the GNU General Public License
22
along with darktable. If not, see <http://www.gnu.org/licenses/>.
23
*/
24
25
/* For parameter optimization we are using the Nelder-Mead simplex method
26
* implemented by Michael F. Hutt.
27
* Changes versus the original code:
28
* do not include "nmsimplex.h" (not needed)
29
* renamed configuration variables to NMS_*
30
* add additional argument to objfun for arbitrary parameters
31
* simplex() returns number of used iterations instead of min value
32
* maximum number of iterations as function parameter
33
* make interface function simplex() static * initialize i and j to avoid compiler warnings
34
* comment out printing of status inormation
35
* reformat according to darktable's clang standards
36
*/
37
38
/*==================================================================================
39
* begin nmsimplex code downloaded from http://www.mikehutt.com/neldermead.html
40
* on February 6, 2016
41
*==================================================================================*/
42
/*
43
* Program: nmsimplex.c
44
* Author : Michael F. Hutt
45
* http://www.mikehutt.com
46
* 11/3/97
47
*
48
* An implementation of the Nelder-Mead simplex method.
49
*
50
* Copyright (c) 1997-2011 <Michael F. Hutt>
51
*
52
* Permission is hereby granted, free of charge, to any person obtaining
53
* a copy of this software and associated documentation files (the
54
* "Software"), to deal in the Software without restriction, including
55
* without limitation the rights to use, copy, modify, merge, publish,
56
* distribute, sublicense, and/or sell copies of the Software, and to
57
* permit persons to whom the Software is furnished to do so, subject to
58
* the following conditions:
59
*
60
* The above copyright notice and this permission notice shall be
61
* included in all copies or substantial portions of the Software.
62
*
63
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
64
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
65
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
66
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
67
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
68
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
69
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
70
*
71
*
72
* Jan. 6, 1999
73
* Modified to conform to the algorithm presented
74
* in Margaret H. Wright's paper on Direct Search Methods.
75
*
76
* Jul. 23, 2007
77
* Fixed memory leak.
78
*
79
* Mar. 1, 2011
80
* Added constraints.
81
*/
82
83
//#include "nmsimplex.h"
84
85
static
int
simplex
(
double
(*objfunc)(
double
[],
void
*params),
double
start[],
int
n
,
double
EPSILON
,
double
scale,
86
int
maxiter,
void
(*constrain)(
double
[],
int
n
),
void
*params)
87
{
88
89
int
vs;
/* vertex with smallest value */
90
int
vh;
/* vertex with next smallest value */
91
int
vg;
/* vertex with largest value */
92
93
int
i
= 0, j = 0,
m
,
row
;
94
int
itr;
/* track the number of iterations */
95
96
double
**
v
;
/* holds vertices of simplex */
97
double
pn, qn;
/* values used to create initial simplex */
98
double
*
f
;
/* value of function at each vertex */
99
double
fr;
/* value of function at reflection point */
100
double
fe;
/* value of function at expansion point */
101
double
fc
;
/* value of function at contraction point */
102
double
*vr;
/* reflection - coordinates */
103
double
*ve;
/* expansion - coordinates */
104
double
*vc;
/* contraction - coordinates */
105
double
*vm;
/* centroid - coordinates */
106
//double min;
107
108
double
fsum, favg, s, cent;
109
110
/* dynamically allocate arrays */
111
112
/* allocate the rows of the arrays */
113
v
= (
double
**)malloc(
sizeof
(
double
*) * (
n
+ 1));
114
f
= (
double
*)malloc(
sizeof
(
double
) * (
n
+ 1));
115
vr = (
double
*)malloc(
sizeof
(
double
) *
n
);
116
ve = (
double
*)malloc(
sizeof
(
double
) *
n
);
117
vc = (
double
*)malloc(
sizeof
(
double
) *
n
);
118
vm = (
double
*)malloc(
sizeof
(
double
) *
n
);
119
120
/* allocate the columns of the arrays */
121
for
(
i
= 0;
i
<=
n
;
i
++)
122
{
123
v
[
i
] = (
double
*)malloc(
sizeof
(
double
) *
n
);
124
}
125
126
/* create the initial simplex */
127
/* assume one of the vertices is 0,0 */
128
129
pn = scale * (sqrt(
n
+ 1) - 1 +
n
) / (
n
* sqrt(2));
130
qn = scale * (sqrt(
n
+ 1) - 1) / (
n
* sqrt(2));
131
132
for
(
i
= 0;
i
<
n
;
i
++)
133
{
134
v
[0][
i
] = start[
i
];
135
}
136
137
for
(
i
= 1;
i
<=
n
;
i
++)
138
{
139
for
(j = 0; j <
n
; j++)
140
{
141
if
(
i
- 1 == j)
142
{
143
v
[
i
][j] = pn + start[j];
144
}
145
else
146
{
147
v
[
i
][j] = qn + start[j];
148
}
149
}
150
}
151
152
if
(!
IS_NULL_PTR
(constrain))
153
{
154
constrain(
v
[j],
n
);
155
}
156
/* find the initial function values */
157
for
(j = 0; j <=
n
; j++)
158
{
159
f
[j] = objfunc(
v
[j], params);
160
}
161
162
#if 0
163
/* print out the initial values */
164
printf(
"Initial Values\n"
);
165
for
(j = 0; j <=
n
; j++)
166
{
167
for
(
i
= 0;
i
<
n
;
i
++)
168
{
169
printf(
"%f %f\n"
,
v
[j][
i
],
f
[j]);
170
}
171
}
172
#endif
173
174
/* begin the main loop of the minimization */
175
for
(itr = 1; itr <= maxiter; itr++)
176
{
177
/* find the index of the largest value */
178
vg = 0;
179
for
(j = 0; j <=
n
; j++)
180
{
181
if
(
f
[j] >
f
[vg])
182
{
183
vg = j;
184
}
185
}
186
187
/* find the index of the smallest value */
188
vs = 0;
189
for
(j = 0; j <=
n
; j++)
190
{
191
if
(
f
[j] <
f
[vs])
192
{
193
vs = j;
194
}
195
}
196
197
/* find the index of the second largest value */
198
vh = vs;
199
for
(j = 0; j <=
n
; j++)
200
{
201
if
(
f
[j] >
f
[vh] &&
f
[j] <
f
[vg])
202
{
203
vh = j;
204
}
205
}
206
207
/* calculate the centroid */
208
for
(j = 0; j <=
n
- 1; j++)
209
{
210
cent = 0.0;
211
for
(
m
= 0;
m
<=
n
;
m
++)
212
{
213
if
(
m
!= vg)
214
{
215
cent +=
v
[
m
][j];
216
}
217
}
218
vm[j] = cent /
n
;
219
}
220
221
/* reflect vg to new vertex vr */
222
for
(j = 0; j <=
n
- 1; j++)
223
{
224
/*vr[j] = (1+NMS_ALPHA)*vm[j] - NMS_ALPHA*v[vg][j];*/
225
vr[j] = vm[j] +
NMS_ALPHA
* (vm[j] -
v
[vg][j]);
226
}
227
if
(!
IS_NULL_PTR
(constrain))
228
{
229
constrain(vr,
n
);
230
}
231
fr = objfunc(vr, params);
232
233
if
(fr <
f
[vh] && fr >=
f
[vs])
234
{
235
for
(j = 0; j <=
n
- 1; j++)
236
{
237
v
[vg][j] = vr[j];
238
}
239
f
[vg] = fr;
240
}
241
242
/* investigate a step further in this direction */
243
if
(fr <
f
[vs])
244
{
245
for
(j = 0; j <=
n
- 1; j++)
246
{
247
/*ve[j] = NMS_GAMMA*vr[j] + (1-NMS_GAMMA)*vm[j];*/
248
ve[j] = vm[j] +
NMS_GAMMA
* (vr[j] - vm[j]);
249
}
250
if
(!
IS_NULL_PTR
(constrain))
251
{
252
constrain(ve,
n
);
253
}
254
fe = objfunc(ve, params);
255
256
/* by making fe < fr as opposed to fe < f[vs],
257
Rosenbrocks function takes 63 iterations as opposed
258
to 64 when using double variables. */
259
260
if
(fe < fr)
261
{
262
for
(j = 0; j <=
n
- 1; j++)
263
{
264
v
[vg][j] = ve[j];
265
}
266
f
[vg] = fe;
267
}
268
else
269
{
270
for
(j = 0; j <=
n
- 1; j++)
271
{
272
v
[vg][j] = vr[j];
273
}
274
f
[vg] = fr;
275
}
276
}
277
278
/* check to see if a contraction is necessary */
279
if
(fr >=
f
[vh])
280
{
281
if
(fr <
f
[vg] && fr >=
f
[vh])
282
{
283
/* perform outside contraction */
284
for
(j = 0; j <=
n
- 1; j++)
285
{
286
/*vc[j] = NMS_BETA*v[vg][j] + (1-NMS_BETA)*vm[j];*/
287
vc[j] = vm[j] +
NMS_BETA
* (vr[j] - vm[j]);
288
}
289
if
(!
IS_NULL_PTR
(constrain))
290
{
291
constrain(vc,
n
);
292
}
293
fc
= objfunc(vc, params);
294
}
295
else
296
{
297
/* perform inside contraction */
298
for
(j = 0; j <=
n
- 1; j++)
299
{
300
/*vc[j] = NMS_BETA*v[vg][j] + (1-NMS_BETA)*vm[j];*/
301
vc[j] = vm[j] -
NMS_BETA
* (vm[j] -
v
[vg][j]);
302
}
303
if
(!
IS_NULL_PTR
(constrain))
304
{
305
constrain(vc,
n
);
306
}
307
fc
= objfunc(vc, params);
308
}
309
310
311
if
(
fc
<
f
[vg])
312
{
313
for
(j = 0; j <=
n
- 1; j++)
314
{
315
v
[vg][j] = vc[j];
316
}
317
f
[vg] =
fc
;
318
}
319
/* at this point the contraction is not successful,
320
we must halve the distance from vs to all the
321
vertices of the simplex and then continue.
322
10/31/97 - modified to account for ALL vertices.
323
*/
324
else
325
{
326
for
(
row
= 0;
row
<=
n
;
row
++)
327
{
328
if
(
row
!= vs)
329
{
330
for
(j = 0; j <=
n
- 1; j++)
331
{
332
v
[
row
][j] =
v
[vs][j] + (
v
[
row
][j] -
v
[vs][j]) / 2.0;
333
}
334
}
335
}
336
if
(!
IS_NULL_PTR
(constrain))
337
{
338
constrain(
v
[vg],
n
);
339
}
340
f
[vg] = objfunc(
v
[vg], params);
341
if
(!
IS_NULL_PTR
(constrain))
342
{
343
constrain(
v
[vh],
n
);
344
}
345
f
[vh] = objfunc(
v
[vh], params);
346
}
347
}
348
#if 0
349
/* print out the value at each iteration */
350
printf(
"Iteration %d\n"
, itr);
351
for
(j = 0; j <=
n
; j++)
352
{
353
for
(
i
= 0;
i
<
n
;
i
++)
354
{
355
printf(
"%f %f\n"
,
v
[j][
i
],
f
[j]);
356
}
357
}
358
#endif
359
/* test for convergence */
360
fsum = 0.0;
361
for
(j = 0; j <=
n
; j++)
362
{
363
fsum +=
f
[j];
364
}
365
favg = fsum / (
n
+ 1);
366
s = 0.0;
367
for
(j = 0; j <=
n
; j++)
368
{
369
s += pow((
f
[j] - favg), 2.0) / (
n
);
370
}
371
s = sqrt(s);
372
if
(s <
EPSILON
)
break
;
373
}
374
/* end main loop of the minimization */
375
376
/* find the index of the smallest value */
377
vs = 0;
378
for
(j = 0; j <=
n
; j++)
379
{
380
if
(
f
[j] <
f
[vs])
381
{
382
vs = j;
383
}
384
}
385
#if 0
386
printf(
"The minimum was found at\n"
);
387
for
(j = 0; j <
n
; j++)
388
{
389
printf(
"%e\n"
,
v
[vs][j]);
390
start[j] =
v
[vs][j];
391
}
392
double
min
= objfunc(
v
[vs], params);
393
printf(
"The minimum value is %f\n"
,
min
);
394
printf(
"%d Iterations through program\n"
, itr);
395
#else
396
for
(j = 0; j <
n
; j++)
397
{
398
start[j] =
v
[vs][j];
399
}
400
#endif
401
dt_free
(
f
);
402
dt_free
(vr);
403
dt_free
(ve);
404
dt_free
(vc);
405
dt_free
(vm);
406
for
(
i
= 0;
i
<=
n
;
i
++)
407
{
408
dt_free
(
v
[
i
]);
409
}
410
dt_free
(
v
);
411
return
itr;
412
}
413
414
/*==================================================================================
415
* end of nmsimplex code
416
*==================================================================================*/
417
418
// clang-format off
419
// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
420
// vim: shiftwidth=2 expandtab tabstop=2 cindent
421
// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
422
// clang-format on
NMS_GAMMA
#define NMS_GAMMA
Definition
ashift.c:122
NMS_BETA
#define NMS_BETA
Definition
ashift.c:121
NMS_ALPHA
#define NMS_ALPHA
Definition
ashift.c:120
simplex
static int simplex(double(*objfunc)(double[], void *params), double start[], int n, double EPSILON, double scale, int maxiter, void(*constrain)(double[], int n), void *params)
Definition
ashift_nmsimplex.c:85
m
#define m
Definition
basecurve.c:278
i
const float i
Definition
colorspaces_inline_conversions.h:440
f
const dt_aligned_pixel_t f
Definition
colorspaces_inline_conversions.h:102
min
static const float const float const float min
Definition
colorspaces_inline_conversions.h:438
n
const float n
Definition
colorspaces_inline_conversions.h:678
row
static const int row
Definition
colorspaces_inline_conversions.h:35
fc
const float fc
Definition
colorspaces_inline_conversions.h:442
EPSILON
#define EPSILON
Definition
curve_tools.c:41
dt_free
#define dt_free(ptr)
Definition
darktable.h:456
IS_NULL_PTR
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition
darktable.h:281
v
const float v
Definition
iop_profile.h:221
src
iop
ashift_nmsimplex.c
Generated by
1.9.8