Skip to content

Commit c391bd3

Browse files
using active sets
1 parent 1a8e2ad commit c391bd3

File tree

2 files changed

+133
-13
lines changed

2 files changed

+133
-13
lines changed

selectiveInference/R/funs.fixed.R

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,8 @@ InverseLinftyOneRowC <- function (Sigma, i, mu, maxiter=50) {
350350
Sigma=as.double(Sigma),
351351
Sigma_diag=as.double(diag(Sigma)),
352352
Sigma_theta=as.double(rep(0, p)),
353+
ever_active=as.integer(i),
354+
nactive_ptr=as.integer(1),
353355
nrow=as.integer(p),
354356
bound=as.double(mu),
355357
theta=as.double(theta),

selectiveInference/src/debiasing_matrix.c

Lines changed: 131 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
// Update one coordinate
1313

1414
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 */
1517
int nrow, /* how many rows in Sigma */
1618
int row, /* which row: 0-based */
1719
double bound, /* Lagrange multipler for \ell_1 */
@@ -21,33 +23,106 @@ double objective(double *Sigma, /* A covariance matrix: X^TX/n */
2123
double value = 0;
2224
double *Sigma_ptr = Sigma;
2325
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;
2429

2530
theta_row_ptr = theta;
2631
theta_col_ptr = theta;
2732

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+
2891
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;
35108
}
36109
}
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+
}
39114
}
40-
value = value + bound * fabs((*theta_row_ptr)); // the \ell_1 term
41-
theta_row_ptr++;
42115
}
43116

44-
return(value);
117+
return(fail == 0);
45118
}
46119

47120

48121
double update_one_coord(double *Sigma, /* A covariance matrix: X^TX/n */
49122
double *Sigma_diag, /* Diagonal entries of Sigma */
50123
double *Sigma_theta, /* Sigma times theta */
124+
int *ever_active, /* Ever active set */
125+
int *nactive_ptr, /* Size of ever active set */
51126
int nrow, /* How many rows in Sigma */
52127
double bound, /* feasibility parameter */
53128
double *theta, /* current value */
@@ -67,6 +142,8 @@ double update_one_coord(double *Sigma, /* A covariance matrix: X^TX/n
67142
double *quadratic_ptr = ((double *) Sigma_diag + coord);
68143
double quadratic_term = *quadratic_ptr;
69144

145+
int *ever_active_ptr;
146+
70147
Sigma_theta_ptr = ((double *) Sigma_theta + coord);
71148
linear_term = *Sigma_theta_ptr;
72149

@@ -97,7 +174,17 @@ double update_one_coord(double *Sigma, /* A covariance matrix: X^TX/n
97174
value = -(linear_term - bound) / quadratic_term;
98175
}
99176

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))) {
101188

102189
delta = value - old_value;
103190
Sigma_ptr = ((double *) Sigma + coord * nrow);
@@ -121,6 +208,8 @@ double update_one_coord(double *Sigma, /* A covariance matrix: X^TX/n
121208
void find_one_row(double *Sigma, /* A covariance matrix: X^TX/n */
122209
double *Sigma_diag, /* Diagonal entry of covariance matrix */
123210
double *Sigma_theta, /* Sigma times theta */
211+
int *ever_active, /* Ever active set */
212+
int *nactive_ptr, /* Size of ever active set */
124213
int *nrow_ptr, /* How many rows in Sigma */
125214
double *bound_ptr, /* feasibility parameter */
126215
double *theta, /* current value */
@@ -135,13 +224,17 @@ void find_one_row(double *Sigma, /* A covariance matrix: X^TX/n */
135224
double bound = *bound_ptr;
136225
int nrow = *nrow_ptr;
137226

227+
fprintf(stderr, "starting now\n");
228+
138229
double old_value = objective(Sigma,
230+
ever_active,
231+
nactive_ptr,
139232
nrow,
140233
row,
141234
bound,
142235
theta);
143236
double new_value;
144-
double tol=1.e-6;
237+
double tol=1.e-5;
145238

146239
for (iter=0; iter<maxiter; iter++) {
147240

@@ -150,31 +243,56 @@ void find_one_row(double *Sigma, /* A covariance matrix: X^TX/n */
150243
update_one_coord(Sigma,
151244
Sigma_diag,
152245
Sigma_theta,
246+
ever_active,
247+
nactive_ptr,
153248
nrow,
154249
bound,
155250
theta,
156251
row,
157252
row);
158253

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+
159263
for (icoord=0; icoord<nrow; icoord++) {
160264

161265
update_one_coord(Sigma,
162266
Sigma_diag,
163267
Sigma_theta,
268+
ever_active,
269+
nactive_ptr,
164270
nrow,
165271
bound,
166272
theta,
167273
row,
168274
icoord);
169275
}
170276

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+
171286
new_value = objective(Sigma,
287+
ever_active,
288+
nactive_ptr,
172289
nrow,
173290
row,
174291
bound,
175292
theta);
176293

177294
if (((old_value - new_value) < tol * fabs(new_value)) && (iter > 0)) {
295+
fprintf(stderr, "ending in objective value check\n");
178296
break;
179297
}
180298

0 commit comments

Comments
 (0)