-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathconjugate_grad.c
114 lines (94 loc) · 2.15 KB
/
conjugate_grad.c
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
#include <volume_io/internal_volume_io.h>
#include <bicpl.h>
#include <conjugate_grad.h>
struct conjugate_grad_struct
{
BOOLEAN first_call;
int n_parameters;
Real *g;
Real *h;
};
public void reinitialize_conjugate_gradient(
conjugate_grad con )
{
con->first_call = TRUE;
}
public conjugate_grad initialize_conjugate_gradient(
int n_parameters )
{
conjugate_grad con;
ALLOC( con, 1 );
con->n_parameters = n_parameters;
con->first_call = TRUE;
if( n_parameters > 0 )
{
ALLOC( con->g, n_parameters );
ALLOC( con->h, n_parameters );
}
return( con );
}
public void delete_conjugate_gradient(
conjugate_grad con )
{
if( con->n_parameters >= 0 )
{
FREE( con->g );
FREE( con->h );
}
FREE( con );
}
public BOOLEAN get_conjugate_unit_direction(
conjugate_grad con,
Real derivative[],
Real unit_dir[] )
{
int p;
Real len, gg, dgg, gam;
BOOLEAN found;
found = TRUE;
if( con->first_call )
{
con->first_call = FALSE;
for_less( p, 0, con->n_parameters )
{
con->g[p] = -derivative[p];
con->h[p] = -derivative[p];
unit_dir[p] = -derivative[p];
}
}
else
{
gg = 0.0;
dgg = 0.0;
for_less( p, 0, con->n_parameters )
{
gg += con->g[p] * con->g[p];
dgg += (derivative[p] + con->g[p]) * derivative[p];
/*
dgg += derivative[p] * derivative[p];
*/
}
if( gg != 0.0 )
gam = dgg / gg;
else
{
gam = 0.0;
found = FALSE;
}
for_less( p, 0, con->n_parameters )
{
con->g[p] = -derivative[p];
con->h[p] = con->g[p] + gam * con->h[p];
unit_dir[p] = con->h[p];
}
}
len = 0.0;
for_less( p, 0, con->n_parameters )
len += unit_dir[p] * unit_dir[p];
if( len == 0.0 )
return( FALSE );
len = sqrt( len );
for_less( p, 0, con->n_parameters )
unit_dir[p] /= len;
return( found );
}