Skip to content

Commit 0c1f9ea

Browse files
renaming function, but all linesearch logic into a row-wise function
1 parent 7fa5120 commit 0c1f9ea

File tree

1 file changed

+129
-106
lines changed

1 file changed

+129
-106
lines changed

selectiveInference/R/funs.fixed.R

Lines changed: 129 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -158,10 +158,8 @@ fixedLassoInf <- function(x, y, beta, lambda, family=c("gaussian","binomial","co
158158

159159
# Approximate inverse covariance matrix for when (n < p) from lasso_Inference.R
160160

161-
htheta <- InverseLinfty(hsigma, n, length(S), verbose=FALSE, max.try=linesearch.try)
161+
htheta = debiasing_matrix(hsigma, n, 1:length(S), verbose=FALSE, max_try=linesearch.try, warn_kkt=TRUE)
162162

163-
# htheta <- InverseLinfty(hsigma, n, verbose=FALSE)
164-
165163
FS = rbind(diag(length(S)),matrix(0,pp-length(S),length(S)))
166164
GS = cbind(diag(length(S)),matrix(0,length(S),pp-length(S)))
167165
ithetasigma = (GS-(htheta%*%hsigma))
@@ -269,137 +267,162 @@ fixedLasso.poly=
269267
### Functions borrowed and slightly modified from lasso_inference.R
270268

271269
## Approximates inverse covariance matrix theta
272-
InverseLinfty <- function(sigma, n, e, resol=1.2, mu=NULL, maxiter=50, threshold=1e-2, verbose = TRUE, max.try=10) {
273270

274-
max_active = max(50, 2 * sqrt(n))
271+
debiasing_matrix = function(Sigma,
272+
nsample,
273+
rows,
274+
verbose=FALSE,
275+
mu=NULL, # starting value of mu
276+
linesearch=TRUE, # do a linesearch?
277+
resol=1.2, # multiplicative factor for linesearch
278+
max_active=NULL, # how big can active set get?
279+
max_try=10, # how many steps in linesearch?
280+
warn_kkt=FALSE, # warn if KKT does not seem to be satisfied?
281+
max_iter=100, # how many iterations for each optimization problem
282+
kkt_tol=1.e-4, # tolerance for the KKT conditions
283+
objective_tol=1.e-4 # tolerance for relative decrease in objective
284+
) {
285+
286+
287+
if (is.null(max_active)) {
288+
max_active = max(50, 0.3 * nsample)
289+
}
290+
291+
p = nrow(Sigma);
292+
M = matrix(0, length(rows), p);
275293

276-
isgiven <- 1;
277-
if (is.null(mu)){
278-
isgiven <- 0;
294+
if (is.null(mu)) {
295+
mu = (1/sqrt(nsample)) * qnorm(1-(0.1/(p^2)))
279296
}
280-
281-
p <- nrow(sigma);
282-
M <- matrix(0, e, p);
297+
283298
xperc = 0;
284299
xp = round(p/10);
285-
for (i in 1:e) {
286-
if ((i %% xp)==0){
300+
idx = 1;
301+
for (row in rows) {
302+
303+
if ((idx %% xp)==0){
287304
xperc = xperc+10;
288305
if (verbose) {
289306
print(paste(xperc,"% done",sep="")); }
290307
}
291-
if (isgiven==0){
292-
mu <- (1/sqrt(n)) * qnorm(1-(0.1/(p^2)));
293-
}
294-
mu.stop <- 0;
295-
try.no <- 1;
296-
incr <- 0;
297308

298-
output = NULL
309+
output = debiasing_row(Sigma,
310+
row,
311+
mu,
312+
linesearch=linesearch,
313+
resol=resol,
314+
max_active=max_active,
315+
max_try=max_try,
316+
warn_kkt=FALSE,
317+
max_iter=max_iter,
318+
kkt_tol=kkt_tol,
319+
objective_tol=objective_tol)
320+
321+
if (warn_kkt && (!output$kkt_check)) {
322+
warning("Solution for row of M does not seem to be feasible")
323+
}
324+
325+
M[idx,] = output$soln;
326+
idx = idx + 1;
327+
}
328+
return(M)
329+
}
299330

300-
last.beta = NULL
331+
debiasing_row = function (Sigma,
332+
row,
333+
mu,
334+
linesearch=TRUE, # do a linesearch?
335+
resol=1.2, # multiplicative factor for linesearch
336+
max_active=NULL, # how big can active set get?
337+
max_try=10, # how many steps in linesearch?
338+
warn_kkt=FALSE, # warn if KKT does not seem to be satisfied?
339+
max_iter=100, # how many iterations for each optimization problem
340+
kkt_tol=1.e-4, # tolerance for the KKT conditions
341+
objective_tol=1.e-4 # tolerance for relative decrease in objective
342+
) {
301343

302-
while ((mu.stop != 1) && (try.no<max.try) ){
344+
p = nrow(Sigma)
303345

304-
output <- InverseLinftyOneRow(sigma, i, mu, maxiter=maxiter, soln_result=output, max_active=max_active) # uses a warm start
305-
beta <- output$soln
346+
if (is.null(max_active)) {
347+
max_active = nrow(Sigma)
348+
}
306349

307-
iter <- output$iter
350+
# Initialize variables
308351

309-
if (isgiven==1) {
310-
mu.stop <- 1
311-
}
312-
else {
313-
if (try.no==1){
314-
if (iter == (maxiter+1)){
315-
incr <- 1;
316-
mu <- mu*resol;
317-
} else {
318-
incr <- 0;
319-
mu <- mu/resol;
320-
}
321-
}
322-
if (try.no > 1){
323-
if ((incr == 1)&&(iter == (maxiter+1))){
324-
mu <- mu*resol;
325-
}
326-
if ((incr == 1)&&(iter < (maxiter+1))){
327-
mu.stop <- 1;
328-
}
329-
if ((incr == 0)&&(iter < (maxiter+1))){
330-
mu <- mu/resol;
331-
}
332-
if ((incr == 0) && (iter == (maxiter+1))){
333-
mu <- mu*resol;
334-
beta <- last.beta;
335-
mu.stop <- 1;
336-
}
337-
}
338-
if (output$max_active_check) {
339-
mu.stop <- 1;
340-
beta <- last.beta;
341-
}
342-
}
343-
try.no <- try.no+1
344-
last.beta <- beta
345-
}
346-
M[i,] <- beta;
347-
}
348-
return(M)
349-
}
352+
soln = rep(0, p)
350353

354+
ever_active = rep(0, p)
355+
ever_active[1] = row # 1-based
356+
ever_active = as.integer(ever_active)
357+
nactive = as.integer(1)
351358

352-
InverseLinftyOneRow <- function (Sigma, i, mu, maxiter=50, soln_result=NULL, kkt_tol=1.e-6, objective_tol=1.e-6,
353-
use_QP=TRUE, max_active=NULL) {
359+
linear_func = rep(0, p)
360+
linear_func[row] = -1
361+
linear_func = as.numeric(linear_func)
362+
gradient = 1. * linear_func
354363

355-
# If soln_result is not Null, it is used as a warm start.
356-
# It should be a list
357-
# with entries "soln", "gradient", "ever_active", "nactive"
364+
counter_idx = 1;
365+
incr = 0;
358366

359-
p = nrow(Sigma)
367+
last_output = NULL
360368

361-
if (is.null(max_active)) {
362-
max_active = 50 # arbitrary?
363-
}
369+
while (counter_idx < max_try) {
364370

365-
if (is.null(soln_result)) {
366-
soln = rep(0, p)
367-
ever_active = rep(0, p)
368-
ever_active[1] = i # 1-based
369-
ever_active = as.integer(ever_active)
370-
nactive = as.integer(1)
371-
if (use_QP) {
372-
linear_func = rep(0, p)
373-
linear_func[i] = -1
374-
linear_func = as.numeric(linear_func)
375-
gradient = 1. * linear_func
376-
} else {
377-
gradient = rep(0, p)
378-
}
379-
}
380-
else {
381-
soln = soln_result$soln
382-
gradient = soln_result$gradient
383-
ever_active = as.integer(soln_result$ever_active)
384-
nactive = as.integer(soln_result$nactive)
385-
if (use_QP) {
386-
linear_func = soln_result$linear_func
387-
}
388-
}
371+
result = solve_QP(Sigma, mu, max_iter, soln, linear_func, gradient, ever_active, nactive, kkt_tol, objective_tol, max_active)
389372

390-
if (use_QP) {
391-
result = solve_QP(Sigma, mu, maxiter, soln, linear_func, gradient, ever_active, nactive, kkt_tol, objective_tol, max_active)
392-
} else {
393-
result = find_one_row_debiasingM(Sigma, i, mu, maxiter, soln, gradient, ever_active, nactive, kkt_tol, objective_tol, max_active) # C function uses 1-based indexing for active set
394-
}
373+
iter = result$iter
374+
375+
# Logic for whether we should continue the line search
376+
377+
if (!linesearch) {
378+
break
379+
}
380+
381+
if (counter_idx == 1){
382+
if (iter == (max_iter+1)){
383+
incr = 1; # was the original problem feasible? 1 if not
384+
} else {
385+
incr = 0; # original problem was feasible
386+
}
387+
}
388+
389+
if (incr == 1) { # trying to find a feasible point
390+
if ((iter < (max_iter+1)) && (counter_idx > 1)) {
391+
break; # we've found a feasible point and solved the problem
392+
}
393+
mu = mu * resol;
394+
} else { # trying to drop the bound parameter further
395+
if ((iter == (max_iter + 1)) && (counter_idx > 1)) {
396+
result = last_output; # problem seems infeasible because we didn't solve it
397+
break; # so we revert to previously found solution
398+
}
399+
mu = mu / resol;
400+
}
401+
402+
# If the active set has grown to a certain size
403+
# then we stop, presuming problem has become
404+
# infeasible.
405+
406+
# We revert to the previous solution
407+
408+
if (result$max_active_check) {
409+
result = last_output;
410+
break;
411+
}
412+
413+
counter_idx = counter_idx + 1
414+
last_output = list(soln=result$soln,
415+
kkt_check=result$kkt_check)
416+
}
395417

396418
# Check feasibility
397419

398-
if (!result$kkt_check) {
420+
if (warn_kkt && (!result$kkt_check)) {
399421
warning("Solution for row of M does not seem to be feasible")
400422
}
401423

402-
return(result)
424+
return(list(soln=result$soln,
425+
kkt_check=result$kkt_check))
403426

404427
}
405428

0 commit comments

Comments
 (0)