Skip to content

Commit 248ce54

Browse files
C code for one row of M
1 parent be89769 commit 248ce54

File tree

2 files changed

+170
-0
lines changed

2 files changed

+170
-0
lines changed

selectiveInference/R/funs.fixed.R

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,25 @@ InverseLinfty <- function(sigma, n, e, resol=1.5, mu=NULL, maxiter=50, threshold
334334
return(M)
335335
}
336336

337+
InverseLinftyOneRowC <- function ( sigma, i, mu, maxiter=50, threshold=1e-2 ) {
338+
339+
p = nrow(sigma)
340+
theta = rep(0, p)
341+
342+
val = .C("find_one_row",
343+
Sigma=as.double(sigma),
344+
nrow=as.integer(p),
345+
bound=as.double(mu),
346+
theta=as.double(theta),
347+
maxiter=as.integer(maxiter),
348+
row=as.integer(i-1),
349+
coord=as.integer(i-1),
350+
dup=FALSE,
351+
package="selectiveInference")
352+
353+
return(val$theta)
354+
}
355+
337356
InverseLinftyOneRow <- function ( sigma, i, mu, maxiter=50, threshold=1e-2 ) {
338357
p <- nrow(sigma);
339358
rho <- max(abs(sigma[i,-i])) / sigma[i,i];
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
#include <stdio.h>
2+
#include <math.h> // for fabs
3+
4+
// Find an approximate row of \hat{Sigma}^{-1}
5+
6+
// Problem (4) of ????
7+
8+
// Update one coordinate
9+
10+
double update_one_coord(double *Sigma, /* A covariance matrix: X^TX/n */
11+
int nrow, /* How many rows in Sigma */
12+
double bound, /* feasibility parameter */
13+
double *theta, /* current value */
14+
int row, /* which row: 0-based */
15+
int coord) /* which coordinate to update: 0-based */
16+
{
17+
18+
double linear_term = 0;
19+
double quadratic_term = 0;
20+
double value = 0;
21+
double *Sigma_ptr;
22+
double *theta_ptr = theta;
23+
int icol = 0;
24+
25+
Sigma_ptr = ((double *) Sigma + nrow * coord);
26+
27+
for (icol=0; icol < nrow; icol++) {
28+
if (icol != coord) {
29+
linear_term += (*Sigma_ptr) * (*theta_ptr);
30+
}
31+
else {
32+
quadratic_term = (*Sigma_ptr);
33+
}
34+
Sigma_ptr += 1;
35+
theta_ptr += 1;
36+
}
37+
38+
if (row == coord) {
39+
linear_term += 1;
40+
}
41+
42+
// Now soft-threshold the coord entry of theta
43+
44+
// Objective is t \mapsto q/2 * t^2 + l * t + bound |t|
45+
// with q=quadratic_term and l=linear_term
46+
47+
if (linear_term < -bound) {
48+
value = - (-linear_term - bound) / quadratic_term;
49+
}
50+
else if (linear_term > bound) {
51+
value = (linear_term - bound) / quadratic_term;
52+
}
53+
54+
theta_ptr = ((double *) theta + coord);
55+
*theta_ptr = value;
56+
return(value);
57+
58+
}
59+
60+
double objective(double *Sigma, /* A covariance matrix: X^TX/n */
61+
int nrow, /* how many rows in Sigma */
62+
int row, /* which row: 0-based */
63+
double bound, /* Lagrange multipler for \ell_1 */
64+
double *theta) /* current value */
65+
{
66+
int irow, icol;
67+
double value = 0;
68+
double *Sigma_ptr = Sigma;
69+
double *theta_row_ptr, *theta_col_ptr;
70+
71+
theta_row_ptr = theta;
72+
theta_col_ptr = theta;
73+
74+
for (irow=0; irow<nrow; irow++) {
75+
double *theta_col_ptr = theta;
76+
for (icol=0; icol<nrow; icol++) {
77+
value += (*Sigma_ptr) * (*theta_row_ptr) * (*theta_col_ptr);
78+
Sigma_ptr++;
79+
theta_col_ptr++;
80+
}
81+
if (irow == row) {
82+
value += (*theta_row_ptr); // the elementary basis vector term
83+
}
84+
85+
value = value + bound * fabs((*theta_row_ptr)); // the \ell_1 term
86+
theta_row_ptr++;
87+
}
88+
89+
return(value);
90+
}
91+
92+
void find_one_row(double *Sigma, /* A covariance matrix: X^TX/n */
93+
int *nrow_ptr, /* How many rows in Sigma */
94+
double *bound_ptr, /* feasibility parameter */
95+
double *theta, /* current value */
96+
int *maxiter_ptr, /* how many iterations */
97+
int *row_ptr, /* which row: 0-based */
98+
int *coord_ptr) /* which coordinate to update: 0-based */
99+
{
100+
101+
int maxiter = *maxiter_ptr;
102+
int iter = 0;
103+
int icoord = 0;
104+
int coord = *coord_ptr;
105+
int row = *row_ptr;
106+
double bound = *bound_ptr;
107+
int nrow = *nrow_ptr;
108+
double old_value = objective(Sigma,
109+
nrow,
110+
row,
111+
bound,
112+
theta);
113+
double new_value;
114+
double tol=1.e-10;
115+
116+
for (iter=0; iter<maxiter; iter++) {
117+
118+
// Update the diagonal first
119+
120+
update_one_coord(Sigma,
121+
nrow,
122+
bound,
123+
theta,
124+
row,
125+
row);
126+
127+
for (icoord=0; icoord<nrow; icoord++) {
128+
129+
update_one_coord(Sigma,
130+
nrow,
131+
bound,
132+
theta,
133+
row,
134+
icoord);
135+
}
136+
137+
new_value = objective(Sigma,
138+
nrow,
139+
row,
140+
bound,
141+
theta);
142+
143+
if (((old_value - new_value) < tol * fabs(new_value)) && (iter > 3)) {
144+
break;
145+
}
146+
old_value = new_value;
147+
}
148+
149+
*nrow_ptr = iter-1;
150+
}
151+

0 commit comments

Comments
 (0)