@@ -163,11 +163,11 @@ int check_KKT_wide(double *theta_ptr, /* current theta */
163
163
double * gradient_ptr , /* X^TX/ncase times theta + linear_func*/
164
164
double * X_theta_ptr , /* Current fitted values */
165
165
double * X_ptr , /* Sqrt of non-neg def matrix -- X^TX/ncase = nndef */
166
- double * linear_func_ptr , /* Linear term in objective */
166
+ double * linear_func_ptr , /* Linear term in objective */
167
167
int * need_update_ptr , /* Which coordinates need to be updated? */
168
168
int nfeature , /* how many columns in X */
169
169
int ncase , /* how many rows in X */
170
- double bound , /* Lagrange multipler for \ell_1 */
170
+ double bound , /* Lagrange multipler for \ell_1 */
171
171
double tol ) /* precision for checking KKT conditions */
172
172
{
173
173
// First check inactive
@@ -204,6 +204,59 @@ int check_KKT_wide(double *theta_ptr, /* current theta */
204
204
return (1 );
205
205
}
206
206
207
+ int check_KKT_wide_active (int * ever_active_ptr , /* Ever active set: 0-based */
208
+ int * nactive_ptr , /* Size of ever active set */
209
+ double * theta_ptr , /* current theta */
210
+ double * gradient_ptr , /* X^TX/ncase times theta + linear_func*/
211
+ double * X_theta_ptr , /* Current fitted values */
212
+ double * X_ptr , /* Sqrt of non-neg def matrix -- X^TX/ncase = nndef */
213
+ double * linear_func_ptr , /* Linear term in objective */
214
+ int * need_update_ptr , /* Which coordinates need to be updated? */
215
+ int nfeature , /* how many columns in X */
216
+ int ncase , /* how many rows in X */
217
+ double bound , /* Lagrange multipler for \ell_1 */
218
+ double tol ) /* precision for checking KKT conditions */
219
+ {
220
+ // First check inactive
221
+
222
+ int iactive ;
223
+ double * theta_ptr_tmp ;
224
+ double gradient ;
225
+ int ever_active_ptr_tmp ;
226
+ int nactive = * nactive_ptr ;
227
+ int active_feature ;
228
+ int * active_feature_ptr ;
229
+
230
+ for (iactive = 0 ; iactive < nactive ; iactive ++ ) {
231
+
232
+ active_feature_ptr = ((int * ) ever_active_ptr + iactive );
233
+ active_feature = * active_feature_ptr - 1 ; // Ever-active is 1-based
234
+ theta_ptr_tmp = ((double * ) theta_ptr + active_feature );
235
+
236
+ // Compute this coordinate of the gradient
237
+
238
+ gradient = compute_gradient_coord (gradient_ptr , X_theta_ptr , X_ptr , linear_func_ptr , need_update_ptr , active_feature , ncase );
239
+
240
+ if (* theta_ptr_tmp != 0 ) { // these coordinates of gradients should be equal to -bound
241
+
242
+ if ((* theta_ptr_tmp > 0 ) && (fabs (gradient + bound ) > tol * bound )) {
243
+ return (0 );
244
+ }
245
+ else if ((* theta_ptr_tmp < 0 ) && (fabs (gradient - bound ) > tol * bound )) {
246
+ return (0 );
247
+ }
248
+
249
+ }
250
+ else {
251
+ if (fabs (gradient ) > (1. + tol ) * bound ) {
252
+ return (0 );
253
+ }
254
+ }
255
+ }
256
+
257
+ return (1 );
258
+ }
259
+
207
260
double update_one_coord_wide (double * X_ptr , /* A design matrix*/
208
261
double * linear_func_ptr , /* Linear term in objective */
209
262
double * nndef_diag_ptr , /* Diagonal entries of Sigma */
@@ -323,10 +376,10 @@ int solve_wide(double *X_ptr, /* Sqrt of non-neg def matrix -- X^TX
323
376
int ifeature = 0 ;
324
377
int iactive = 0 ;
325
378
int * active_ptr ;
326
-
327
379
int check_objective = 1 ;
328
-
329
380
double old_value , new_value ;
381
+ int niter_active = 5 ;
382
+ int iter_active ;
330
383
331
384
if (check_objective ) {
332
385
@@ -343,26 +396,47 @@ int solve_wide(double *X_ptr, /* Sqrt of non-neg def matrix -- X^TX
343
396
344
397
for (iter = 0 ; iter < maxiter ; iter ++ ) {
345
398
346
- // Update the active variables first
399
+ // Update the active variables first -- do this niter_active times
400
+
401
+ for (iter_active = 0 ; iter_active < niter_active ; iter_active ++ ) {
402
+
403
+ active_ptr = (int * ) ever_active_ptr ;
404
+ for (iactive = 0 ; iactive < * nactive_ptr ; iactive ++ ) {
405
+
406
+ update_one_coord_wide (X_ptr ,
407
+ linear_func_ptr ,
408
+ nndef_diag_ptr ,
409
+ gradient_ptr ,
410
+ ever_active_ptr ,
411
+ nactive_ptr ,
412
+ X_theta_ptr ,
413
+ need_update_ptr ,
414
+ ncase ,
415
+ nfeature ,
416
+ bound ,
417
+ theta_ptr ,
418
+ * active_ptr - 1 , // Ever-active is 1-based
419
+ 1 );
420
+ active_ptr ++ ;
421
+ }
422
+
423
+ // Check KKT of active subproblem
424
+
425
+ if (check_KKT_wide_active (ever_active_ptr ,
426
+ nactive_ptr ,
427
+ theta_ptr ,
428
+ gradient_ptr ,
429
+ X_theta_ptr ,
430
+ X_ptr ,
431
+ linear_func_ptr ,
432
+ need_update_ptr ,
433
+ nfeature ,
434
+ ncase ,
435
+ bound ,
436
+ kkt_tol ) == 1 ) {
437
+ break ;
438
+ }
347
439
348
- active_ptr = (int * ) ever_active_ptr ;
349
- for (iactive = 0 ; iactive < * nactive_ptr ; iactive ++ ) {
350
-
351
- update_one_coord_wide (X_ptr ,
352
- linear_func_ptr ,
353
- nndef_diag_ptr ,
354
- gradient_ptr ,
355
- ever_active_ptr ,
356
- nactive_ptr ,
357
- X_theta_ptr ,
358
- need_update_ptr ,
359
- ncase ,
360
- nfeature ,
361
- bound ,
362
- theta_ptr ,
363
- * active_ptr - 1 , // Ever-active is 1-based
364
- 1 );
365
- active_ptr ++ ;
366
440
}
367
441
368
442
// Check KKT
0 commit comments