File: minpack.h

package info (click to toggle)
meshlab 1.3.2%2Bdfsg1-4
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 21,096 kB
  • ctags: 33,630
  • sloc: cpp: 224,813; ansic: 8,170; xml: 119; makefile: 80
file content (226 lines) | stat: -rw-r--r-- 6,715 bytes parent folder | download | duplicates (5)
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
#ifndef LM_DIFF
#define LM_DIFF

/****************************************************************************
* VCGLib                                                            o o     *
* Visual and Computer Graphics Library                            o     o   *
*                                                                _   O  _   *
* Copyright(C) 2004                                                \/)\/    *
* Visual Computing Lab                                            /\/|      *
* ISTI - Italian National Research Council                           |      *
*                                                                    \      *
* All rights reserved.                                                      *
*                                                                           *
* This program is free software; you can redistribute it and/or modify      *   
* it under the terms of the GNU General Public License as published by      *
* the Free Software Foundation; either version 2 of the License, or         *
* (at your option) any later version.                                       *
*                                                                           *
* This program is distributed in the hope that it will be useful,           *
* but WITHOUT ANY WARRANTY; without even the implied warranty of            *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
* for more details.                                                         *
*                                                                           *
****************************************************************************/

#include <cminpack.h>
#include <stdlib.h>
/*
LMDiff is a class that performs non linear minimization:

min Sum_{i=0}^{M} ( F(x0,..,xN)_i ) ^2 )
Where:
F: R^N->R^M is a user defined function

****** basic example use ****

void evaluate (void *data,  int n_par, int m_dat, double* par, double* fvec, int iflag )
{
for(int i = 0 ; i < m_dat;++i)
fvec[i] = i * (par)[0] * (par)[0] + (i/2) * (par)[1] * (par)[1];
}


int main(){
LMDiff nlm;
double par[2]={4.0,-4.0};
nlm.InitControl();
nlm.Run(3,2,par,evaluate,0);
}

*/
/** Class LMDiff.
    This is a class for wrapping  the lmdif part of cminpack (see http://devernay.free.fr/hacks/cminpack.html).
 */
class LMDiff{
public:


// parameters for calling the high-level interface Run
// ( Run.c provides lm_control_default which sets default values ):
typedef struct {
	double ftol; 		// relative error desired in the sum of squares.
	double xtol; 		// relative error between last two approximations.
	double gtol; 		// orthogonality desired between fvec and its derivs.
	double epsilon; 	// step used to calculate the jacobian.
	double stepbound; 	// initial bound to steps in the outer loop.
	double fnorm; 		// norm of the residue vector fvec.
	int maxcall; 		// maximum number of iterations.
	int nfev; 		// actual number of iterations.
	int nprint; 		// desired frequency of print outs.
	int info; 		// status of minimization.
} lm_control_type;


// through the following parameters, lm_lmdif communicates with evaluate:
typedef struct {
	int nfev; 	// actual number of iterations.
	int nprint; 	// desired frequency of print outs.
	int stop; 	// if set to a nonzero value, minimization will stop.
} lm_status_type;


// ***** the following messages are referenced by the variable info.
static char * Message(const int & i){
static char *lm_infmsg[] = {
"improper input parameters",
"the relative error in the sum of squares is at most tol",
"the relative error between x and the solution is at most tol",
"both errors are at most tol",
"fvec is orthogonal to the columns of the jacobian to machine precision",
"number of calls to fcn has reached or exceeded 200*(n+1)",
"tol is too small. no further reduction in the sum of squares is possible",
"tol too small. no further improvement in approximate solution x possible",
"not enough memory"
};
return lm_infmsg[i];
}
lm_control_type control; // control of this object

/// Initialize the control: termination condition, steps size..
void InitControl(){lm_initialize_control();}

/// the subroutine that calculates fvec:
typedef int (lm_evaluate_type) (
	void *user_data, // user data (the same passed to Run
	int m, // the dimension of the co-domain of your F
	int n,
	const double* n_var, // the n parameters to compute your F
	double* fvec, // the values computed by F
	int iflag // status
);

void Run (
	int m, // size of the codomain of F
	int n , // size of the domain of F
	double* par, // starting values of the parameters
	lm_evaluate_type *evaluate, // yuor function F
	void *data, // user data (will be passed to F as they are
	lm_control_type *control // control
);


// compact high-level interface:

void Run( int m_dat,int n_par, double* par, lm_evaluate_type *evaluate,
void *data );

private:
void lm_initialize_control( );
};



/* *********************** high-level interface **************************** */


void LMDiff::lm_initialize_control( )
{
	control.maxcall = 10000;
	control.epsilon = 1.e-14;
	control.stepbound = 100.;
	control.ftol = 1.e-14;
	control.xtol = 1.e-14;
	control.gtol = 1.e-14;
	control.nprint = 0;
}

void LMDiff::Run( int m_dat,int n_par, double* par, lm_evaluate_type *evaluate,
void *data ){Run( m_dat, n_par, par, evaluate, data, &control);}


void LMDiff::Run( int m_dat,int n_par, double* par, lm_evaluate_type *evaluate,
void *data, lm_control_type *control )
{

// *** allocate work space.

double *fvec, *diag, *fjac, *qtf, *wa1, *wa2, *wa3, *wa4;
int *ipvt;

int n = n_par;
int m = m_dat;

if 	(!(fvec = (double*) malloc( m*sizeof(double))) ||
	!(diag = (double*) malloc(n* sizeof(double))) ||
	!(qtf = (double*) malloc(n* sizeof(double))) ||
	!(fjac = (double*) malloc(n*m*sizeof(double))) ||
	!(wa1 = (double*) malloc(n* sizeof(double))) ||
	!(wa2 = (double*) malloc(n* sizeof(double))) ||
	!(wa3 = (double*) malloc(n* sizeof(double))) ||
	!(wa4 = (double*) malloc( m*sizeof(double))) ||
	!(ipvt = (int*) malloc(n* sizeof(int)))) {
	control->info = 9;
	return;
}

// *** perform fit.

control->info = 0;
control->nfev = 0;
// this goes through the modified legacy interface:
control->info = 
lmdif(
evaluate,
data,
m,
n,
par,
fvec,
control->ftol,
control->xtol,
control->gtol,
control->maxcall*(n+1),
control->epsilon,
diag,
1,
control->stepbound,
control->nprint,
&(control->nfev),
fjac,
m,
ipvt,
qtf,
wa1,
wa2,
wa3,
wa4
);

if (control->info >= 8) control->info = 4;

// *** clean up.

free(fvec);
free(diag);
free(qtf);
free(fjac);
free(wa1);
free(wa2);
free(wa3 );
free(wa4);
free(ipvt);
}

#endif