11
11
// Therefore we don't have to negate the answer to get theta.
12
12
// Update one coordinate
13
13
14
- double update_one_coord (double * Sigma , /* A covariance matrix: X^TX/n */
15
- int nrow , /* How many rows in Sigma */
16
- double bound , /* feasibility parameter */
17
- double * theta , /* current value */
18
- int row , /* which row: 0-based */
19
- int coord ) /* which coordinate to update: 0-based */
14
+ double objective (double * Sigma , /* A covariance matrix: X^TX/n */
15
+ int nrow , /* how many rows in Sigma */
16
+ int row , /* which row: 0-based */
17
+ double bound , /* Lagrange multipler for \ell_1 */
18
+ double * theta ) /* current value */
20
19
{
20
+ int irow , icol ;
21
+ double value = 0 ;
22
+ double * Sigma_ptr = Sigma ;
23
+ double * theta_row_ptr , * theta_col_ptr ;
21
24
25
+ theta_row_ptr = theta ;
26
+ theta_col_ptr = theta ;
27
+
28
+ for (irow = 0 ; irow < nrow ; irow ++ ) {
29
+ double * theta_col_ptr = theta ;
30
+ for (icol = 0 ; icol < nrow ; icol ++ ) {
31
+ value += 0.5 * (* Sigma_ptr ) * (* theta_row_ptr ) * (* theta_col_ptr );
32
+ Sigma_ptr ++ ;
33
+ theta_col_ptr ++ ;
34
+ }
35
+ if (irow == row ) {
36
+ value -= (* theta_row_ptr ); // the elementary basis vector term
37
+ }
38
+
39
+ value = value + bound * fabs ((* theta_row_ptr )); // the \ell_1 term
40
+ theta_row_ptr ++ ;
41
+ }
42
+
43
+ return (value );
44
+ }
45
+
46
+
47
+ double update_one_coord (double * Sigma , /* A covariance matrix: X^TX/n */
48
+ double * Sigma_diag , /* Diagonal entries of Sigma */
49
+ double * Sigma_theta , /* Sigma times theta */
50
+ int nrow , /* How many rows in Sigma */
51
+ double bound , /* feasibility parameter */
52
+ double * theta , /* current value */
53
+ int row , /* which row: 0-based */
54
+ int coord ) /* which coordinate to update: 0-based */
55
+ {
56
+
57
+ double delta ;
22
58
double linear_term = 0 ;
23
- double quadratic_term = 0 ;
24
59
double value = 0 ;
60
+ double old_value ;
25
61
double * Sigma_ptr ;
26
- double * theta_ptr = theta ;
62
+ double * Sigma_theta_ptr ;
63
+ double * theta_ptr ;
27
64
int icol = 0 ;
28
65
29
- Sigma_ptr = ((double * ) Sigma + nrow * coord );
66
+ double * quadratic_ptr = ((double * ) Sigma_diag + coord );
67
+ double quadratic_term = * quadratic_ptr ;
68
+
69
+ Sigma_theta_ptr = ((double * ) Sigma_theta + coord );
70
+ linear_term = * Sigma_theta_ptr ;
71
+
72
+ theta_ptr = ((double * ) theta + coord );
73
+ old_value = * theta_ptr ;
74
+
75
+ // The coord entry of Sigma_theta term has a diagonal term in it:
76
+ // Sigma[coord, coord] * theta[coord]
77
+ // This removes it.
78
+ linear_term -= quadratic_term * old_value ;
30
79
31
- for (icol = 0 ; icol < nrow ; icol ++ ) {
32
- if (icol != coord ) {
33
- linear_term += (* Sigma_ptr ) * (* theta_ptr );
34
- }
35
- else {
36
- quadratic_term = (* Sigma_ptr );
37
- }
38
- Sigma_ptr += 1 ;
39
- theta_ptr += 1 ;
40
- }
41
-
42
80
if (row == coord ) {
43
81
linear_term -= 1 ;
44
82
}
@@ -58,60 +96,72 @@ double update_one_coord(double *Sigma, /* A covariance matrix: X^TX/n */
58
96
value = - (linear_term - bound ) / quadratic_term ;
59
97
}
60
98
99
+ if (fabs (old_value - value ) > 1.e-6 * (fabs (value ) + fabs (old_value ))) { // Update the linear term
100
+
101
+ delta = value - old_value ;
102
+ Sigma_ptr = ((double * ) Sigma + coord * nrow );
103
+ Sigma_theta_ptr = ((double * ) Sigma_theta );
104
+
105
+ for (icol = 0 ; icol < nrow ; icol ++ ) {
106
+ * Sigma_theta_ptr = * Sigma_theta_ptr + delta * (* Sigma_ptr );
107
+ Sigma_theta_ptr += 1 ;
108
+ Sigma_ptr += 1 ;
109
+ }
110
+
111
+ double before = objective (Sigma ,
112
+ nrow ,
113
+ row ,
114
+ bound ,
115
+ theta );
116
+ fprintf (stderr , "before %f\n" , before );
117
+
61
118
theta_ptr = ((double * ) theta + coord );
62
119
* theta_ptr = value ;
63
- return (value );
64
120
65
- }
121
+ double after = objective (Sigma ,
122
+ nrow ,
123
+ row ,
124
+ bound ,
125
+ theta );
66
126
67
- double objective (double * Sigma , /* A covariance matrix: X^TX/n */
68
- int nrow , /* how many rows in Sigma */
69
- int row , /* which row: 0-based */
70
- double bound , /* Lagrange multipler for \ell_1 */
71
- double * theta ) /* current value */
72
- {
73
- int irow , icol ;
74
- double value = 0 ;
75
- double * Sigma_ptr = Sigma ;
76
- double * theta_row_ptr , * theta_col_ptr ;
127
+ fprintf (stderr , "after %f\n" , after );
128
+ if (after > before ) {
129
+ fprintf (stderr , "not a descent step!!!!!!!!!!!!!!!!!!!!!\n" );
130
+ }
77
131
78
- theta_row_ptr = theta ;
79
- theta_col_ptr = theta ;
80
132
81
- for (irow = 0 ; irow < nrow ; irow ++ ) {
82
- double * theta_col_ptr = theta ;
133
+ }
134
+
135
+ Sigma_ptr = ((double * ) Sigma + coord * nrow );
136
+ Sigma_theta_ptr = ((double * ) Sigma_theta );
83
137
for (icol = 0 ; icol < nrow ; icol ++ ) {
84
- value += (* Sigma_ptr ) * (* theta_row_ptr ) * (* theta_col_ptr );
85
- Sigma_ptr ++ ;
86
- theta_col_ptr ++ ;
87
- }
88
- if (irow == row ) {
89
- value += (* theta_row_ptr ); // the elementary basis vector term
138
+
139
+ Sigma_theta_ptr += 1 ;
140
+ Sigma_ptr += 1 ;
90
141
}
91
142
92
- value = value + bound * fabs ((* theta_row_ptr )); // the \ell_1 term
93
- theta_row_ptr ++ ;
94
- }
95
143
96
144
return (value );
145
+
97
146
}
98
147
99
148
void find_one_row (double * Sigma , /* A covariance matrix: X^TX/n */
149
+ double * Sigma_diag , /* Diagonal entry of covariance matrix */
150
+ double * Sigma_theta , /* Sigma times theta */
100
151
int * nrow_ptr , /* How many rows in Sigma */
101
152
double * bound_ptr , /* feasibility parameter */
102
153
double * theta , /* current value */
103
154
int * maxiter_ptr , /* how many iterations */
104
- int * row_ptr , /* which row: 0-based */
105
- int * coord_ptr ) /* which coordinate to update: 0-based */
155
+ int * row_ptr ) /* which coordinate to update: 0-based */
106
156
{
107
157
108
158
int maxiter = * maxiter_ptr ;
109
159
int iter = 0 ;
110
160
int icoord = 0 ;
111
- int coord = * coord_ptr ;
112
161
int row = * row_ptr ;
113
162
double bound = * bound_ptr ;
114
163
int nrow = * nrow_ptr ;
164
+
115
165
double old_value = objective (Sigma ,
116
166
nrow ,
117
167
row ,
@@ -125,6 +175,8 @@ void find_one_row(double *Sigma, /* A covariance matrix: X^TX/n */
125
175
// Update the diagonal first
126
176
127
177
update_one_coord (Sigma ,
178
+ Sigma_diag ,
179
+ Sigma_theta ,
128
180
nrow ,
129
181
bound ,
130
182
theta ,
@@ -134,6 +186,8 @@ void find_one_row(double *Sigma, /* A covariance matrix: X^TX/n */
134
186
for (icoord = 0 ; icoord < nrow ; icoord ++ ) {
135
187
136
188
update_one_coord (Sigma ,
189
+ Sigma_diag ,
190
+ Sigma_theta ,
137
191
nrow ,
138
192
bound ,
139
193
theta ,
@@ -147,9 +201,11 @@ void find_one_row(double *Sigma, /* A covariance matrix: X^TX/n */
147
201
bound ,
148
202
theta );
149
203
150
- if (((old_value - new_value ) < tol * fabs (new_value )) && (iter > 3 )) {
204
+ if (((old_value - new_value ) < tol * fabs (new_value )) && (iter > 5 )) {
151
205
break ;
152
206
}
207
+
208
+ fprintf (stderr , "%f %f value\n" , old_value , new_value );
153
209
old_value = new_value ;
154
210
}
155
211
0 commit comments