Skip to content

Commit fb7f85f

Browse files
solving active problem more accurately with more iterations -- KKT check to break
1 parent 4d376c4 commit fb7f85f

File tree

1 file changed

+97
-23
lines changed

1 file changed

+97
-23
lines changed

selectiveInference/src/quadratic_program_wide.c

Lines changed: 97 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -163,11 +163,11 @@ int check_KKT_wide(double *theta_ptr, /* current theta */
163163
double *gradient_ptr, /* X^TX/ncase times theta + linear_func*/
164164
double *X_theta_ptr, /* Current fitted values */
165165
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 */
167167
int *need_update_ptr, /* Which coordinates need to be updated? */
168168
int nfeature, /* how many columns in X */
169169
int ncase, /* how many rows in X */
170-
double bound, /* Lagrange multipler for \ell_1 */
170+
double bound, /* Lagrange multipler for \ell_1 */
171171
double tol) /* precision for checking KKT conditions */
172172
{
173173
// First check inactive
@@ -204,6 +204,59 @@ int check_KKT_wide(double *theta_ptr, /* current theta */
204204
return(1);
205205
}
206206

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+
207260
double update_one_coord_wide(double *X_ptr, /* A design matrix*/
208261
double *linear_func_ptr, /* Linear term in objective */
209262
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
323376
int ifeature = 0;
324377
int iactive = 0;
325378
int *active_ptr;
326-
327379
int check_objective = 1;
328-
329380
double old_value, new_value;
381+
int niter_active = 5;
382+
int iter_active;
330383

331384
if (check_objective) {
332385

@@ -343,26 +396,47 @@ int solve_wide(double *X_ptr, /* Sqrt of non-neg def matrix -- X^TX
343396

344397
for (iter=0; iter<maxiter; iter++) {
345398

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+
}
347439

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++;
366440
}
367441

368442
// Check KKT

0 commit comments

Comments
 (0)