12
12
// Update one coordinate
13
13
14
14
double objective (double * Sigma , /* A covariance matrix: X^TX/n */
15
+ int * ever_active , /* Ever active set */
16
+ int * nactive_ptr , /* Size of ever active set */
15
17
int nrow , /* how many rows in Sigma */
16
18
int row , /* which row: 0-based */
17
19
double bound , /* Lagrange multipler for \ell_1 */
@@ -21,33 +23,106 @@ double objective(double *Sigma, /* A covariance matrix: X^TX/n */
21
23
double value = 0 ;
22
24
double * Sigma_ptr = Sigma ;
23
25
double * theta_row_ptr , * theta_col_ptr ;
26
+ int * active_row_ptr , * active_col_ptr ;
27
+ int active_row , active_col ;
28
+ int nactive = * nactive_ptr ;
24
29
25
30
theta_row_ptr = theta ;
26
31
theta_col_ptr = theta ;
27
32
33
+ for (irow = 0 ; irow < nactive ; irow ++ ) {
34
+
35
+ active_row_ptr = ((int * ) ever_active + irow );
36
+ active_row = * active_row_ptr ;
37
+ theta_row_ptr = ((double * ) theta + active_row );
38
+
39
+ for (icol = 0 ; icol < nactive ; icol ++ ) {
40
+
41
+ active_col_ptr = ((int * ) ever_active + icol );
42
+ active_col = * active_col_ptr ;
43
+ theta_col_ptr = ((double * ) theta + active_col );
44
+
45
+ fprintf (stderr , "%d %d \n" , active_row , active_col );
46
+
47
+ Sigma_ptr = ((double * ) Sigma + nrow * active_row + active_col );
48
+
49
+ value += 0.5 * (* Sigma_ptr ) * (* theta_row_ptr ) * (* theta_col_ptr );
50
+ }
51
+ value = value + bound * fabs ((* theta_row_ptr )); // the \ell_1 term
52
+ }
53
+
54
+ theta_row_ptr = ((double * ) theta + row );
55
+ value -= (* theta_row_ptr ); // the elementary basis vector term
56
+
57
+ return (value );
58
+ }
59
+
60
+ int is_active (int coord ,
61
+ int * nactive_ptr ,
62
+ int * ever_active ) {
63
+ int iactive ;
64
+ int active_var ;
65
+ int nactive = * nactive_ptr ;
66
+ int * ever_active_ptr = ever_active ;
67
+
68
+ for (iactive = 0 ; iactive < nactive ; iactive ++ ) {
69
+ active_var = (* ever_active_ptr );
70
+ if (active_var == coord ) {
71
+ return (1 );
72
+ }
73
+ }
74
+ return (0 );
75
+ }
76
+
77
+ int check_KKT (double * theta , /* current theta */
78
+ double * Sigma_theta , /* Sigma times theta */
79
+ int nrow , /* how many rows in Sigma */
80
+ int row , /* which row: 0-based */
81
+ double bound ) /* Lagrange multipler for \ell_1 */
82
+ {
83
+ // First check inactive
84
+
85
+ int irow ;
86
+ int fail = 0 ;
87
+ double tol = 1.e-4 ;
88
+ double * theta_ptr , * Sigma_theta_ptr ;
89
+ double gradient ;
90
+
28
91
for (irow = 0 ; irow < nrow ; irow ++ ) {
29
- double * theta_col_ptr = theta ;
30
- if (* theta_row_ptr != 0 ) {
31
- for (icol = 0 ; icol < nrow ; icol ++ ) {
32
- value += 0.5 * (* Sigma_ptr ) * (* theta_row_ptr ) * (* theta_col_ptr );
33
- Sigma_ptr ++ ;
34
- theta_col_ptr ++ ;
92
+ theta_ptr = ((double * ) theta + irow );
93
+ Sigma_theta_ptr = ((double * ) Sigma_theta + irow );
94
+
95
+ // Compute this coordinate of the gradient
96
+
97
+ gradient = * Sigma_theta_ptr ;
98
+ if (row == irow ) {
99
+ gradient -= 1 ;
100
+ }
101
+
102
+ if (* theta_ptr != 0 ) { // these coordinates of gradients should be equal to -bound
103
+ if ((* theta_ptr > 0 ) && (fabs (gradient + bound ) > (1. + tol ) * bound )) {
104
+ fail += 1 ;
105
+ }
106
+ else if ((* theta_ptr < 0 ) && (fabs (gradient - bound ) > (1. + tol ) * bound )) {
107
+ fail += 1 ;
35
108
}
36
109
}
37
- if (irow == row ) {
38
- value -= (* theta_row_ptr ); // the elementary basis vector term
110
+ else {
111
+ if (fabs (gradient ) > (1. + tol ) * bound ) {
112
+ fail += 1 ;
113
+ }
39
114
}
40
- value = value + bound * fabs ((* theta_row_ptr )); // the \ell_1 term
41
- theta_row_ptr ++ ;
42
115
}
43
116
44
- return (value );
117
+ return (fail == 0 );
45
118
}
46
119
47
120
48
121
double update_one_coord (double * Sigma , /* A covariance matrix: X^TX/n */
49
122
double * Sigma_diag , /* Diagonal entries of Sigma */
50
123
double * Sigma_theta , /* Sigma times theta */
124
+ int * ever_active , /* Ever active set */
125
+ int * nactive_ptr , /* Size of ever active set */
51
126
int nrow , /* How many rows in Sigma */
52
127
double bound , /* feasibility parameter */
53
128
double * theta , /* current value */
@@ -67,6 +142,8 @@ double update_one_coord(double *Sigma, /* A covariance matrix: X^TX/n
67
142
double * quadratic_ptr = ((double * ) Sigma_diag + coord );
68
143
double quadratic_term = * quadratic_ptr ;
69
144
145
+ int * ever_active_ptr ;
146
+
70
147
Sigma_theta_ptr = ((double * ) Sigma_theta + coord );
71
148
linear_term = * Sigma_theta_ptr ;
72
149
@@ -97,7 +174,17 @@ double update_one_coord(double *Sigma, /* A covariance matrix: X^TX/n
97
174
value = - (linear_term - bound ) / quadratic_term ;
98
175
}
99
176
100
- if (fabs (old_value - value ) > 1.e-6 * (fabs (value ) + fabs (old_value ))) { // Update the linear term
177
+ // Add to active set if necessary
178
+
179
+ if ((value != 0 ) && (is_active (coord , ever_active , nactive_ptr ) == 0 )) {
180
+ ever_active_ptr = ((int * ) ever_active + * nactive_ptr );
181
+ * ever_active_ptr = coord ;
182
+ * nactive_ptr += 1 ;
183
+ }
184
+
185
+ // Update the linear term
186
+
187
+ if (fabs (old_value - value ) > 1.e-6 * (fabs (value ) + fabs (old_value ))) {
101
188
102
189
delta = value - old_value ;
103
190
Sigma_ptr = ((double * ) Sigma + coord * nrow );
@@ -121,6 +208,8 @@ double update_one_coord(double *Sigma, /* A covariance matrix: X^TX/n
121
208
void find_one_row (double * Sigma , /* A covariance matrix: X^TX/n */
122
209
double * Sigma_diag , /* Diagonal entry of covariance matrix */
123
210
double * Sigma_theta , /* Sigma times theta */
211
+ int * ever_active , /* Ever active set */
212
+ int * nactive_ptr , /* Size of ever active set */
124
213
int * nrow_ptr , /* How many rows in Sigma */
125
214
double * bound_ptr , /* feasibility parameter */
126
215
double * theta , /* current value */
@@ -135,13 +224,17 @@ void find_one_row(double *Sigma, /* A covariance matrix: X^TX/n */
135
224
double bound = * bound_ptr ;
136
225
int nrow = * nrow_ptr ;
137
226
227
+ fprintf (stderr , "starting now\n" );
228
+
138
229
double old_value = objective (Sigma ,
230
+ ever_active ,
231
+ nactive_ptr ,
139
232
nrow ,
140
233
row ,
141
234
bound ,
142
235
theta );
143
236
double new_value ;
144
- double tol = 1.e-6 ;
237
+ double tol = 1.e-5 ;
145
238
146
239
for (iter = 0 ; iter < maxiter ; iter ++ ) {
147
240
@@ -150,31 +243,56 @@ void find_one_row(double *Sigma, /* A covariance matrix: X^TX/n */
150
243
update_one_coord (Sigma ,
151
244
Sigma_diag ,
152
245
Sigma_theta ,
246
+ ever_active ,
247
+ nactive_ptr ,
153
248
nrow ,
154
249
bound ,
155
250
theta ,
156
251
row ,
157
252
row );
158
253
254
+ if (check_KKT (theta ,
255
+ Sigma_theta ,
256
+ nrow ,
257
+ row ,
258
+ bound ) == 1 ) {
259
+ fprintf (stderr , "ending in first KKT check\n" );
260
+ break ;
261
+ }
262
+
159
263
for (icoord = 0 ; icoord < nrow ; icoord ++ ) {
160
264
161
265
update_one_coord (Sigma ,
162
266
Sigma_diag ,
163
267
Sigma_theta ,
268
+ ever_active ,
269
+ nactive_ptr ,
164
270
nrow ,
165
271
bound ,
166
272
theta ,
167
273
row ,
168
274
icoord );
169
275
}
170
276
277
+ if (check_KKT (theta ,
278
+ Sigma_theta ,
279
+ nrow ,
280
+ row ,
281
+ bound ) == 1 ) {
282
+ fprintf (stderr , "ending in second KKT check\n" );
283
+ break ;
284
+ }
285
+
171
286
new_value = objective (Sigma ,
287
+ ever_active ,
288
+ nactive_ptr ,
172
289
nrow ,
173
290
row ,
174
291
bound ,
175
292
theta );
176
293
177
294
if (((old_value - new_value ) < tol * fabs (new_value )) && (iter > 0 )) {
295
+ fprintf (stderr , "ending in objective value check\n" );
178
296
break ;
179
297
}
180
298
0 commit comments