[R] Problem with constrOptim when hitting boundary

Elizabeth Purdom epurdom at stat.berkeley.edu
Thu Apr 26 20:02:05 CEST 2012


Hello,

I am using constrOptim to maximize a likelihood function (the values of my parameter vector must be between zero and one and must sum up to <=1). I am getting the error 'initial value in 'vmmin' is not finite'. I've tracked it down to a problem in the function 'R' defined within the constrOptim function. It is performing a check on my values, and its not passing the check, and therefore returning NaN. This is not my initial value, but rather during an internal iteration.

This is the function defined in constrOptim (the following is code from debugging it)

debugging in: R(theta, theta.old)
debug: {
    ui.theta <- ui %*% theta
    gi <- ui.theta - ci
    if (any(gi < 0)) 
        return(NaN)
    gi.old <- ui %*% theta.old - ci
    bar <- sum(gi.old * log(gi) - ui.theta)
    if (!is.finite(bar)) 
        bar <- -Inf
    f(theta, ...) - mu * bar
}

I see that I am getting the gi values that are just machine error below 0 (-8.881784e-16):

Browse[3]> ui.theta
     [,1]
[1,]   -1
[2,]    1
Browse[3]> ci
[1] -1  0
Browse[3]> gi
              [,1]
[1,] -8.881784e-16
[2,]  1.000000e+00

I'm a bit surprised that constrOptim wouldn't be robust to that. I'm wondering what I can do to get around this, if anything. Is this a sign that my function that I defined is not behaving correctly in some way (e.g. should I be handling machine error in the function I defined?). I would note in my example below, I am only optimizing over a one-dimensional parameter, for which I understand optim is not optimal, but my function is general and in other situations it could be a vector of length greater than 1. 

I give an example below, as well as my function and session info. The example is pathological (x, the successes, are equal to m the trials) but I'm running simulations, and this is being created in my simulations. When I run a large set of simulations (over many different parameters) I am actually getting about half the time an error like this, and so I don't know if it is always a pathological example like this. This is just an example I found where I know it failed.

Thanks for your help,
Elizabeth Purdom

Example data:
> x <- c(12, 17,  9, 15, 15,  9, 15, 11, 12,  7) 
> m <- c(12,17,  9, 15, 15,  9, 15, 11, 12,  7)
> AMat<-matrix(c(1,0,0,1),byrow=T,nrow=2,ncol=2)
> eventTiming(x, m, history = AMat)

Error message:
Error in optim(theta.old, fun, gradient, control = control, method = method,  : 
  initial value in 'vmmin' is not finite

Enter a frame number, or 0 to exit   

1: eventTiming(x, m, history = AMat)
2: eventTiming.R#84: constrOptim(theta = init, f = neglik, grad = neggr, ui = 
3: eventTiming.R#84: optim(theta.old, fun, gradient, control = control, method

> sessionInfo()
R version 2.15.0 (2012-03-30)
Platform: x86_64-pc-linux-gnu (64-bit)

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=C                 LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

loaded via a namespace (and not attached):
[1] tools_2.15.0

My function:
eventTiming<-function(x,m,history, exactAllele=FALSE,normCont=0,verbose=FALSE,coverageCutoff=1,minMutations=10){
	
	A<-history
	if(is.null(dim(A))) stop("'history' should be a matrix of size nCopies x (nEvents +1)")
	nCopies<-nrow(A)
	K<-ncol(A)-1
	possAlleles<-(1:nCopies)/nCopies*(1-normCont)
	nMuts<-length(x)
	if(length(m)!=nMuts) stop("x and m must be of same length")
	if(coverageCutoff<1) stop("coverageCutoff must be at least 1")
	if(any(m<coverageCutoff)){
		if(verbose) warning("some mutations have no reads, will be ignored")
		nBelowCutoff<-length(which(m<coverageCutoff))
		nZero<-length(which(m==0))
		x<-x[which(m>=coverageCutoff)]
		m<-m[which(m>=coverageCutoff)]
	}
	else{
		nBelowCutoff<-0
		nZero<-0
	}
	if(length(m)<minMutations){
		if(length(normCont)>0){
			if(length(possAlleles)!=K+1) stop("invalid length for possible Allele Frequency values")
			if(is.null(names(possAlleles))) names(possAlleles)<-paste("AlleleFreq",1:length(possAlleles),sep="")
			return(list(pi=rep(NA,length=K+1),alleleSet=possAlleles,optimOut=NA,nBelowCutoff=nBelowCutoff,nZero=nZero,nMut=length(m)))
		}
		else return(list(pi=rep(NA,length=K+1),alleleSet=NA,optimOut=NA,nBelowCutoff=nBelowCutoff,nZero=nZero,nMut=length(m)))
	}
	
	###Make 'weight matrix' of P(X=X[i]|X>0, P=p(k,s)) of size nStages x nCopies for each x -- 
	###an array that is nMuts x nCopies of the prob of X given a certain allele
	probX<-function(p){
		dbinom(x=x,size=m,prob=p)
	}
	wtMat<-sapply(possAlleles,probX)  #nMuts x nAlleles
	if(is.null(dim(wtMat))){
		if(length(x)==1) wtMat<-matrix(wtMat,nrow=1)
		else stop("Programming error -- single row wtMat")
	}
	###Need to convert so in terms of pi[-0]
	transMat<-rbind(rep(-1,K),diag(K))
	Aid<-A%*%transMat
	numGr<-wtMat %*% Aid #N x K matrix
	init<-rep(1/(K+1),length=K) #equal distribution; could perhaps choose better init value
	getProbFromTheta<-function(theta){
		return(c(1-sum(theta),theta))
	}
	neglik<-function(theta){
		probDist<-as.vector(A%*%getProbFromTheta(theta)) #should be a vector of probabilities
		if(length(probDist)!=K+1) stop("Programming error -- wrong length")
		if(any(probDist< -1e-10)) stop("Programming error -- negative probabilities")
		if(any(probDist> 1+1e-10)) stop("Programming error -- >1 probabilities")
		-sum(log(rowSums(sweep(wtMat,2,probDist,FUN="*"))))
	}
	#numerator of grad  because linear in pi -- same regardless of value of theta
	neggr<-function(theta){
		#denominator:
		probDist<-as.vector(A%*%getProbFromTheta(theta))
		if(length(probDist)!=K+1) stop("Programming error -- wrong length")
		if(any(probDist< -1e-10)) stop("Programming error -- negative probabilities")
		if(any(probDist> 1+1e-10)) stop("Programming error -- >1 probabilities")
		denom<-rowSums(sweep(wtMat,2,probDist,FUN="*")) #should be a vector length equal to N
		
		-sum(sweep(numGr,1,denom,"/"))
		
	}
	
	lengthOfTheta<-K
	uiL1<-diag(rep(-1,lengthOfTheta),nrow=lengthOfTheta,ncol=lengthOfTheta)
	ciL1<-rep(1,lengthOfTheta)
	uiGr0<-diag(rep(1,lengthOfTheta),nrow=lengthOfTheta,ncol=lengthOfTheta)
	ciGr0<-rep(0,lengthOfTheta)
	ui<-rbind(uiL1,uiGr0)
	ci<- c(-ciL1,-ciGr0)
	#The feasible region is defined by ui %*% theta - ci >= 0. 
	out<-constrOptim(theta=init,f = neglik, grad=neggr, ui=ui, ci=ci)
	
	return(list(pi=getProbFromTheta(out$par),alleleSet=possAlleles,optimOut=out,nBelowCutoff=nBelowCutoff,nZero=nZero,nMut=length(m)))
}



More information about the R-help mailing list