https://github.com/tansey/smoothfdr
Revision c5b693d0a66e83c9387433b33c0eab481bd4a763 authored by Wesley Tansey on 08 May 2020, 15:42:20 UTC, committed by Wesley Tansey on 08 May 2020, 15:42:20 UTC
1 parent 49cb69c
Raw File
Tip revision: c5b693d0a66e83c9387433b33c0eab481bd4a763 authored by Wesley Tansey on 08 May 2020, 15:42:20 UTC
Fixed bug in easy that created too large a support for the alternative distribution
Tip revision: c5b693d
braindt.cpp
#include"braindt.h"
//#include <iostream>

//#include<vector>
#include <cfloat>//for IsFiniteNumber and IsNumber function
#include <algorithm>
#include<cstdio>
#include<cstdlib>
#include<string>
//#include<cstring>
#define _USE_MATH_DEFINES
#include<math.h>
using namespace std;
const double braindt::TINY=1e-20;
const double braindt::mu0=0;
const double braindt::sigma0_sq=1;
//constructor function of class braindt 
braindt::braindt(int &LX, int &LY, int &LZ,int &Num,char *argv ,vector<int> &Loca,int &PN,vector<double>& est,int &L_hat,int sweep_b, int sweep_r,int sweep_lis,int iter_max):\
	Lx(LX),Ly(LY),Lz(LZ),N(Num),pN(PN),y(PN),L(L_hat),U(2),invI(3),I(3),swp_b(sweep_b),swp_r(sweep_r),max_iter(iter_max),initial(PN ),delta(2),\
    H_mean0(2),H0(sweep_r,vector<double>(2)),H_cond_mean(2),mu1_hat_pre(L_hat ),sigma1_sq_hat_pre(L_hat ),pEll_hat_pre(L_hat ),LIS(PN),swp_lis(sweep_lis)
{
       
    
    
   
  

	vector<double> y_ori;//observed data on the whole image grid including the brain part and the non-brain part
	ifstream ifs(argv);//
	double temp_y;
	while(ifs>>temp_y)
		y_ori.push_back(temp_y);// read in y_ori
    
    
    
	
	int i;
        loca=Loca.begin();//the location of the brain region of interest (ROI) on the Lx*Ly*Lz image grid

	for(int pi=0;pi<pN;pi++)
	{
		i=loca[pi];
		y[pi]=y_ori[i];//the observed data of the ROI
		
	}
	

	YbyX=Ly*Lx;

	beta_hat=est[0];
	h_hat=est[1];

    int i3;
	for(int i=0;i<L;i++)
	{
        i3=i*3;
		mu1_hat.push_back(est[2+i3]);
		sigma1_sq_hat.push_back(est[3+i3]);
		pEll_hat.push_back(est[4+i3]);
		
	}
	
	
}

inline double braindt::normpdf(double &x, double &mu, double &sigma_sq)// The probability density function of the normal distribution with mean=mu, variance=sigma_sq

{
    return exp(-1*(x-mu)*(x-mu)/(2*sigma_sq))/(sqrt(2*M_PI*sigma_sq));
}


inline bool braindt::IsFiniteNumber(double &x)// Judge whether x is a finite numebr
{
	return (x<=DBL_MAX && x>=-DBL_MAX);
}        
inline bool braindt::IsNumber(double &x)//Judge whether x is a numebr
{
	return (x==x);
}

double braindt::sigmasum(vector<double> &p, int begin, int end)//sum of elements of vector p
{
	double sum=0;
	for(int i=begin; i<end; i++)
	{
		sum+=p[i];
	}
	return sum;
}
double braindt::sigmasum(vector<double> &p1, vector<double> &p2, int begin, int end)//sum of elements of the entrywise-product of vectors p1 and p2
{
	double sum=0;
	for(int i=begin; i<end; i++)
	{
		sum+=p1[i]*p2[i];
	}
	return sum;
}
double braindt::sigmasum(vector<double> &p1, vector<double> &p2, double p2minus, int begin, int end)//sum of elements of the entrywise-product of vectors p1 and p3 squared, where p3=p2-p2minus
{
        double sum=0;
        double minus;
        for(int i=begin; i<end; i++)
        {
                minus=p2[i]-p2minus;
                sum+=p1[i]*minus*minus;
        }
        return sum;
        
}


void braindt::two_d_var_matrix_inv(ofstream &fileout, int splnumber)// compute the inverse matrix of a 2 by 2 matrix
{
	
	double s1,s2;
	
	vector<double> var(3);
	
	for(int i=0;i<splnumber;i++)
	{
		s1=H[i][0]-H_mean[0];
		var[0]+=s1*s1;
		s2=H[i][1]-H_mean[1];
		var[2]+=s2*s2;
		var[1]+=s1*s2;//non-diagonal entry
		
	
		
	}
	
	
	
	splnumber-=1;
	var[0]/=splnumber;
	var[2]/=splnumber;
	var[1]/=splnumber;
        for(int t=0;t<3;t++)
        {fileout<<"I["<<t<<"]="<<var[t]<<endl;}
		
	double denom=var[0]*var[2]-var[1]*var[1];
	if(denom>0) 
	{
		invI[0]=var[2]/denom;
		invI[2]=var[0]/denom;
		invI[1]=-var[1]/denom;
		if(!(IsFiniteNumber(invI[0])&&IsFiniteNumber(invI[1])&&IsFiniteNumber(invI[2])&&IsNumber(invI[0])&&IsNumber(invI[1])&&IsNumber(invI[2])))
		{
			fileout<<"invI is almost non-invertible matrix"<<endl;
			var[0]+=TINY;
			var[2]+=TINY;
			denom=var[0]*var[2]-var[1]*var[1];
			invI[0]=var[2]/denom;
			invI[2]=var[0]/denom;
			invI[1]=-var[1]/denom;
			if(!(IsFiniteNumber(invI[0])&&IsFiniteNumber(invI[1])&&IsFiniteNumber(invI[2])&&IsNumber(invI[0])&&IsNumber(invI[1])&&IsNumber(invI[2])))
			{
				fileout<<"we choose invI=I"<<endl;
                invI[0]=1;
                invI[1]=0;
                invI[2]=1;
                
			}
			
			
		}
		
		
		
	}
	else {
		fileout<<"invI is non-invertible matrix"<<endl;
		var[0]+=TINY;
		var[2]+=TINY;
		denom=var[0]*var[2]-var[1]*var[1];
		invI[0]=var[2]/denom;
		invI[2]=var[0]/denom;
		invI[1]=-var[1]/denom;
		if(!(IsFiniteNumber(invI[0])&&IsFiniteNumber(invI[1])&&IsFiniteNumber(invI[2])&&IsNumber(invI[0])&&IsNumber(invI[1])&&IsNumber(invI[2])))
		{
            fileout<<"we choose invI=I"<<endl;
            invI[0]=1;
            invI[1]=0;
            invI[2]=1;
		}
		
	}
	I=var;
	
	

}


void braindt::two_d_var_matrix_inv( int splnumber)// compute the inverse matrix of a 2by2 matrix
{
	
	double s1,s2;
	
	vector<double> var(3);
	
	for(int i=0;i<splnumber;i++)
	{
		s1=H[i][0]-H_mean[0];
		var[0]+=s1*s1;
		s2=H[i][1]-H_mean[1];
		var[2]+=s2*s2;
		var[1]+=s1*s2;//non-diagonal entry
		
        
		
	}
	
	
	
	splnumber-=1;
	var[0]/=splnumber;
	var[2]/=splnumber;
	var[1]/=splnumber;
    
    
	double denom=var[0]*var[2]-var[1]*var[1];
	if(denom>0)
	{
		invI[0]=var[2]/denom;
		invI[2]=var[0]/denom;
		invI[1]=-var[1]/denom;
		if(!(IsFiniteNumber(invI[0])&&IsFiniteNumber(invI[1])&&IsFiniteNumber(invI[2])&&IsNumber(invI[0])&&IsNumber(invI[1])&&IsNumber(invI[2])))
		{
			
			var[0]+=TINY;
			var[2]+=TINY;
			denom=var[0]*var[2]-var[1]*var[1];
			invI[0]=var[2]/denom;
			invI[2]=var[0]/denom;
			invI[1]=-var[1]/denom;
			if(!(IsFiniteNumber(invI[0])&&IsFiniteNumber(invI[1])&&IsFiniteNumber(invI[2])&&IsNumber(invI[0])&&IsNumber(invI[1])&&IsNumber(invI[2])))
			{
				
                invI[0]=1;
                invI[1]=0;
                invI[2]=1;
                
			}
			
			
		}
		
		
		
	}
	else {
		
		var[0]+=TINY;
		var[2]+=TINY;
		denom=var[0]*var[2]-var[1]*var[1];
		invI[0]=var[2]/denom;
		invI[2]=var[0]/denom;
		invI[1]=-var[1]/denom;
		if(!(IsFiniteNumber(invI[0])&&IsFiniteNumber(invI[1])&&IsFiniteNumber(invI[2])&&IsNumber(invI[0])&&IsNumber(invI[1])&&IsNumber(invI[2])))
		{
            
            invI[0]=1;
            invI[1]=0;
            invI[2]=1;
		}
		
	}
	I=var;
	
	
    
}


void braindt::gem(ofstream &fileout,char* filename)//The Generalized EM Algorithm
{
    
    int i,j,sum,sum_cond,sweep,ell,pi;
	int t;///////
	
    
    
	fileout<<"The beginning of GEM with initial values:"<<endl;
	fileout<<"beta_hat="<<beta_hat<<endl;
	fileout<<"h_hat="<<h_hat<<endl;
    
	for(ell=0;ell<L;ell++)
	{
		fileout<<"mu1_hat["<<ell<<"]="<<mu1_hat[ell]<<endl;
		fileout<<"sigma1_sq_hat["<<ell<<"]="<<sigma1_sq_hat[ell]<<endl;
		fileout<<"pEll_hat["<<ell<<"]="<<pEll_hat[ell]<<endl;
		
		
	}
	fileout<<"End the beginning of GEM"<<endl<<endl;
    
    
    
    
    double TINY_L=TINY/L;
    
    int error_time=0;
    
    double temp_like;
    
    


	
	int seed=0;

	CRandomMersenne rnd1(seed);
	StochasticLib1  rnd2(seed);
	
	
	double a,b;//for penalized MLE (PMLE) when L>=2
	a=1;
	b=2;
	
	
	double del=1e-3;
	
	
	

	int succ_t=0;// to see the stopping rule successive time in the t iteration


	

	

    
    
	

	double exp_x[7];
	vector<double> exp_y(pN );

	
	double beta_hat_pre,h_hat_pre;//previous values for t iteration, i.e., the interations of GEM algorithm

	
	
	double d1=1;//error in t iteration of GEM
	
	vector<double> diff(2+3*L);
	
	
	
	double p_1;
	
	
	double temp2;

	
	vector<double> constant(L );
	
	
	
	vector<int> x(N );//x is the unobservable state 0 or 1
	vector<int> x_cond(N );// conditional x on y

	
	double constant_0=sqrt(2*M_PI*sigma0_sq);
	vector<double> temp1(pN);
	
	
	
	for(pi=0;pi<pN ;pi++)
	{
		
		initial[pi]=rnd1.Random()<0.5?1:0;
		temp1[pi]=constant_0*exp(pow(y[pi]-mu0,2)/(2*sigma0_sq));
	}

     
    
        vector<double> log_q2_sub(swp_r); // -phi^T*H(x)
    alam=0;
    int n_tout=1;

for(t=0;n_tout && t<max_iter;t++)
{
    
        fileout<<"The GEM iteration t="<<t<<endl;
	
		beta_hat_pre=beta_hat;
		h_hat_pre=h_hat; 
		
		vector<double> gamma_1(pN);
		
		for(i=0;i<L;i++)
		{
			constant[i]=pEll_hat[i]/sqrt(2*M_PI*sigma1_sq_hat[i]);
			
		}
		
		for(pi=0;pi<pN;pi++)
		{
			
			temp2=0;
			i=loca[pi];
			x[i]=x_cond[i]=initial[pi];
			for(j=0;j<L;j++)
			{
				temp2+=constant[j]*exp(-pow(y[pi]-mu1_hat[j],2)/(2*sigma1_sq_hat[j]));
			}
			exp_y[pi]=temp1[pi]*temp2;
		}

	for(i=0; i<7; i++)
	{
		exp_x[i]=exp(beta_hat*i+h_hat);
	}  
	
	
	H_cond_mean=H_mean0;//set to be zeros

	for(sweep=1;sweep<swp_b;sweep++)
	{
		for(pi=0; pi<pN;pi++)
		{
			i=loca[pi];
		
            
            
            sum=x[i+1]+x[i-1]+x[i+Lx]+x[i-Lx]+x[i+YbyX]+x[i-YbyX];
            sum_cond=x_cond[i+1]+x_cond[i-1]+x_cond[i+Lx]+x_cond[i-Lx]+x_cond[i+YbyX]+x_cond[i-YbyX];
			
			p_1=1-1/(1+exp_x[sum]);
			x[i]=rnd2.Bernoulli(p_1);
			p_1=1-1/(1+exp_x[sum_cond]*exp_y[pi]);
			x_cond[i]=rnd2.Bernoulli(p_1);

		}

	}	
	


	   H_mean=H_mean0;//set to be zeros

	   H=H0;
	
	for(sweep=0;sweep<swp_r;sweep++)
	{
        
        
        
        
        for(pi=0; pi<pN;pi++)
		{
            
			i=loca[pi];
            
            sum=x[i+1]+x[i-1]+x[i+Lx]+x[i-Lx]+x[i+YbyX]+x[i-YbyX];
            sum_cond=x_cond[i+1]+x_cond[i-1]+x_cond[i+Lx]+x_cond[i-Lx]+x_cond[i+YbyX]+x_cond[i-YbyX];
			
			
			
			p_1=1-1/(1+exp_x[sum]);
            
			x[i]=rnd2.Bernoulli(p_1);
			p_1=1-1/(1+exp_x[sum_cond]*exp_y[pi]);
            
			x_cond[i]=rnd2.Bernoulli(p_1);
			
		}

		for(pi=0; pi<pN;pi++)
		{

			i=loca[pi];
            
            sum=x[i+1]+x[i-1]+x[i+Lx]+x[i-Lx]+x[i+YbyX]+x[i-YbyX];
            sum_cond=x_cond[i+1]+x_cond[i-1]+x_cond[i+Lx]+x_cond[i-Lx]+x_cond[i+YbyX]+x_cond[i-YbyX];
			
			
			
		
			H_cond_mean[0]+=x_cond[i]*sum_cond;//warning:1/2 in the later, for compute twice//Don't forgot to divide swp_r at the end
			H_cond_mean[1]+=x_cond[i];
			
			
			
			H[sweep][0]+=x[i]*sum*0.5;
			H[sweep][1]+=x[i];
			
			gamma_1[pi]+=x_cond[i];//r_[i][1]
//////////////////////////////////////////////////////////////
            

        
			
		}
		
        log_q2_sub[sweep]=-H[sweep][0]*beta_hat-H[sweep][1]*h_hat;
//////////////////////////////////////////////////////////////////
		
		H_mean[0]+=H[sweep][0];//don't forgot to divide swp_r at the end
		H_mean[1]+=H[sweep][1];

		
	}
///////////////////////////////////////////////////////////////////////
    temp_like=*max_element(log_q2_sub.begin(), log_q2_sub.end());
    log_plikelihood=0;
    for(sweep=0;sweep<swp_r;sweep++)
    {
        log_plikelihood+=exp(log_q2_sub[sweep]-temp_like);
    }
    
    q2=temp_like+log(log_plikelihood);//-logZ
    //fileout<<"q2="<<q2<<endl;


    
    
    
	///////////////// U	  
	H_cond_mean[0]/=2;
    
	fileout<<"The score function U:"<<endl;
	
	for(i=0;i<2;i++)
	{
	
		H_cond_mean[i]/=swp_r;
		H_mean[i]/=swp_r;

		U[i]=H_cond_mean[i]-H_mean[i];		
                fileout<<"U["<<i<<"]="<<U[i]<<endl;
                fileout<<"H_cond_mean["<<i<<"]="<<H_cond_mean[i]<<endl;
                fileout<<"H_mean["<<i<<"]="<<H_mean[i]<<endl;
	}	
	
     
	fileout<<"The information matrix I:"<<endl;
	two_d_var_matrix_inv(fileout,swp_r);// for I update
//////////////////////////revised by 20140219
   
    
    
		for(pi=0;pi<pN;pi++)
		{
			gamma_1[pi]=gamma_1[pi]/swp_r;
			
		}
	
		double gamma_1_sum=sigmasum(gamma_1,0,pN);

		
	
    
    
		mu1_hat_pre=mu1_hat;
		sigma1_sq_hat_pre=sigma1_sq_hat;
		pEll_hat_pre=pEll_hat;			  
		
		if(L==1)
		{
			pEll_hat[0]=1;
			mu1_hat[0]=(sigmasum(gamma_1,y,0,pN)+TINY)/(gamma_1_sum+TINY);//+TINY to avoid the case gamma_1_sum=0
			sigma1_sq_hat[0]=(sigmasum(gamma_1,y,mu1_hat[0],0,pN )+TINY)/(gamma_1_sum+TINY);
		}
		else 
		{


			vector<double> f1y(pN);
			vector<double> omega_sum(L);
			vector<vector<double> > omega(L,vector<double>(pN));
			
			for(pi=0;pi<pN;pi++)
			{
				
				
				for(ell=0;ell<L;ell++)
				{
					f1y[pi]+=pEll_hat[ell]*normpdf(y[pi], mu1_hat[ell], sigma1_sq_hat[ell]); 
					
				}
				for(ell=0;ell<L;ell++)
				{
					omega[ell][pi]=gamma_1[pi]*pEll_hat[ell] \
					*normpdf(y[pi],mu1_hat[ell],sigma1_sq_hat[ell])/f1y[pi];
					omega_sum[ell]+=omega[ell][pi];
				}
			}
			

			
			
			
			for(ell=0;ell<L;ell++)
			{
			
               
                    
				mu1_hat[ell]=(sigmasum(omega[ell],y,0,pN )+TINY)/(omega_sum[ell]+TINY);// +TINY to avoid omega_sum[ell]=0
				sigma1_sq_hat[ell]=(sigmasum(omega[ell],y,mu1_hat[ell],0,pN )+2*a)/(omega_sum[ell]+2*b);//PMLE
                
              

                
                
                if(ell==(L-1))
				{
					pEll_hat[ell]=0;
					for(int ell_sub=0;ell_sub<ell;ell_sub++)
					{
						pEll_hat[ell]+=pEll_hat[ell_sub];
					}
					pEll_hat[ell]=1-pEll_hat[ell];
                    
                    
                    
                    
                    ///////if pELL_hat[L-1]<0, because of precision problem, to be like -2.22045e-16
                    if(pEll_hat[ell]<0)
                    {
                        pEll_hat[(ell-1)]+=pEll_hat[ell];
                        pEll_hat[ell]=0;
                    }
                    
                    
				}
				else {
					pEll_hat[ell]=(omega_sum[ell]+TINY_L)/(gamma_1_sum+TINY);//+TINY to avoid gamma_1_sum=0
                   // fileout<<"omega_sum["<<ell<<"]="<<omega_sum[ell]<<endl;
                   // fileout<<"gamma_1_sum="<<gamma_1_sum<<endl;
				}
                
                
		
			}
			
	
			
			
			
			
		}
	

		
/* 		
    fileout<<"before backtrack"<<endl;
    fileout<<"beta_hat="<<beta_hat<<endl;
    fileout<<"h_hat="<<h_hat<<endl;
    fileout<<"U[0]="<<U[0]<<endl;
    fileout<<"U[1]="<<U[1]<<endl;
 */
	
	     fileout<<"Go to backtracking linear seach"<<endl;
		 backtrack(fileout,rnd2);
	     fileout<<"Back to GEM from backtracking linear seach"<<endl;
//m iteration is over
	



		///////////////////////
		diff[0]=fabs(beta_hat_pre-beta_hat)/(fabs(beta_hat_pre)+del);
		diff[1]=fabs(h_hat_pre-h_hat)/(fabs(h_hat_pre)+del);
		
        fileout<<"The estimates obtained in the iteration of GEM t="<<t<<":"<<endl;
		fileout<<"beta_hat="<<beta_hat<<endl;
		fileout<<"h_hat="<<h_hat<<endl;
		
		for(ell=0;ell<L;ell++)
		{
            if(pEll_hat_pre[ell]<1e-3 && pEll_hat[ell]<1e-3)
            {
                fileout<<"pEll_hat_pre and pEll_hat are too close to 0 to be accounted into d1"<<endl;
                diff[2+ell]=0;
                diff[2+L+ell]=0;
                diff[2+2*L+ell]=0;
                
            }
            else
            {
            
			   diff[2+ell]=fabs(mu1_hat_pre[ell]-mu1_hat[ell])/(fabs(mu1_hat_pre[ell])+del );
			   diff[2+L+ell]=fabs(sigma1_sq_hat_pre[ell]-sigma1_sq_hat[ell])/(fabs(sigma1_sq_hat_pre[ell])+del );
			   diff[2+2*L+ell]=fabs(pEll_hat_pre[ell]-pEll_hat[ell])/(fabs(pEll_hat_pre[ell])+del );
                
                
                fileout<<"mu1_hat["<<ell<<"]="<<mu1_hat[ell]<<endl;
                fileout<<"sigma1_sq_hat["<<ell<<"]="<<sigma1_sq_hat[ell]<<endl;
                fileout<<"pEll_hat["<<ell<<"]="<<pEll_hat[ell]<<endl;
                
                
                
			  
            }
		}
		d1=*max_element(diff.begin(), diff.end());
		fileout<<"The scaled distance between previous and current estimates, d1="<<d1<<endl<<endl;
	
	
	   if(d1<1e-3 && alam==1 && stpover==0)
       {
           succ_t++;
       }
       else
       {
           succ_t=0;
       }
    
       if(succ_t==3)
       {
           n_tout=0;//satisfying the stopping rule for consecutive three times
       }
    
    
        
	
		
		
}// t iteration is over
    
    
    

/////////////////////////////////////////////////////////
 //   ofstream fileout;
    ofstream fileout2;
    

	fileout2.open (filename);
	
    fileout<<"Summary:"<<endl;
    fileout<<"The number of voxels, pN="<<pN<<endl;
    fileout<<"The iterations of GEM used="<<t<<endl;
    fileout<<"The indicator of satisfying the stopping rule for consecutive three times="<<1-n_tout<<endl;
    fileout<<"The scaled distance between previous and current estimates, d1="<<d1<<endl;
    fileout<<"The proportion of the regular Newton step used in the final GEM iteration,lambda="<<alam<<endl;
	
	fileout<<"The score function U:"<<endl;
    fileout<<"U[0]="<<U[0]<<endl;
    
    fileout<<"H_cond_mean[0]="<<H_cond_mean[0]<<endl;
    fileout<<"H_mean[0]="<<H_mean[0]<<endl;
    
    fileout<<"U[1]="<<U[1]<<endl;
    fileout<<"H_cond_mean[1]="<<H_cond_mean[1]<<endl;
    fileout<<"H_mean[1]="<<H_mean[1]<<endl;
	
	fileout<<"The final estimates:"<<endl;
	fileout<<"beta_hat="<<beta_hat<<endl;
	fileout<<"h_hat="<<h_hat<<endl;
    
 	for(ell=0;ell<L;ell++)
	{
		fileout<<"mu1_hat["<<ell<<"]="<<mu1_hat[ell]<<endl;
		fileout<<"sigma1_sq_hat["<<ell<<"]="<<sigma1_sq_hat[ell]<<endl;
		fileout<<"pEll_hat["<<ell<<"]="<<pEll_hat[ell]<<endl;
		
		
	}
    
	fileout2<<beta_hat<<" "<<h_hat;
    for(ell=0;ell<L;ell++)
	{
		fileout2<<" "<<mu1_hat[ell];
		fileout2<<" "<<sigma1_sq_hat[ell];
		fileout2<<" "<<pEll_hat[ell];
	}
    

    
        fileout2.close();
}


void braindt::gem(char* filename)//The Generalized EM Algorithm
{
    
    int i,j,sum,sum_cond,sweep,ell,pi;
	int t;///////
	
    
    

    
    
    double TINY_L=TINY/L;
    
    int error_time=0;
    
    double temp_like;
    
    
    
    
	
	int seed=0;
    
	CRandomMersenne rnd1(seed);
	StochasticLib1  rnd2(seed);
	
	
	double a,b;//for penalized MLE (PMLE) when L>=2
	a=1;
	b=2;
	
	
	double del=1e-3;
	
	
	
    
	int succ_t=0;// to see the stopping rule successive time in the t iteration
    

	

	
    
    
    
	
    
	double exp_x[7];
	vector<double> exp_y(pN );
    
	
	double beta_hat_pre,h_hat_pre;//for t iteration, i.e., the interations of GEM algorithm

		
	double d1=1;//error in t iteration of GEM

	vector<double> diff(2+3*L);
	
	
	
	double p_1;
	
	
	double temp2;
    
	
	vector<double> constant(L );
	
	
	
	vector<int> x(N );//x is the unobservable state 0 or 1
	vector<int> x_cond(N );// conditional x on y
    
	
	double constant_0=sqrt(2*M_PI*sigma0_sq);
	vector<double> temp1(pN);
	
	
	
	for(pi=0;pi<pN ;pi++)
	{
		
		initial[pi]=rnd1.Random()<0.5?1:0;
		temp1[pi]=constant_0*exp(pow(y[pi]-mu0,2)/(2*sigma0_sq));
	}
    
    
    
    vector<double> log_q2_sub(swp_r); // -phi^T*H(x)
    alam=0;
    int n_tout=1;
    
    for(t=0;n_tout && t<max_iter;t++)
    {
        
        
		beta_hat_pre=beta_hat;
		h_hat_pre=h_hat;
		
		vector<double> gamma_1(pN);
		
		for(i=0;i<L;i++)
		{
			constant[i]=pEll_hat[i]/sqrt(2*M_PI*sigma1_sq_hat[i]);
			
		}
		
		for(pi=0;pi<pN;pi++)
		{
			
			temp2=0;
			i=loca[pi];
			x[i]=x_cond[i]=initial[pi];
			for(j=0;j<L;j++)
			{
				temp2+=constant[j]*exp(-pow(y[pi]-mu1_hat[j],2)/(2*sigma1_sq_hat[j]));
			}
			exp_y[pi]=temp1[pi]*temp2;
		}
        
        for(i=0; i<7; i++)
        {
            exp_x[i]=exp(beta_hat*i+h_hat);
        }
        
        
        H_cond_mean=H_mean0;//set to be zeros
        
        for(sweep=1;sweep<swp_b;sweep++)
        {
            for(pi=0; pi<pN;pi++)
            {
                i=loca[pi];
                
                
                
                sum=x[i+1]+x[i-1]+x[i+Lx]+x[i-Lx]+x[i+YbyX]+x[i-YbyX];
                sum_cond=x_cond[i+1]+x_cond[i-1]+x_cond[i+Lx]+x_cond[i-Lx]+x_cond[i+YbyX]+x_cond[i-YbyX];
                
                p_1=1-1/(1+exp_x[sum]);
                x[i]=rnd2.Bernoulli(p_1);
                p_1=1-1/(1+exp_x[sum_cond]*exp_y[pi]);
                x_cond[i]=rnd2.Bernoulli(p_1);
                
            }
            
        }
        
        
        
        H_mean=H_mean0;//set to be zeros
        
        H=H0;
        
        for(sweep=0;sweep<swp_r;sweep++)
        {
            
           
            
            
            for(pi=0; pi<pN;pi++)
            {
                
                i=loca[pi];
                
                sum=x[i+1]+x[i-1]+x[i+Lx]+x[i-Lx]+x[i+YbyX]+x[i-YbyX];
                sum_cond=x_cond[i+1]+x_cond[i-1]+x_cond[i+Lx]+x_cond[i-Lx]+x_cond[i+YbyX]+x_cond[i-YbyX];
                
                
                
                p_1=1-1/(1+exp_x[sum]);
                
                x[i]=rnd2.Bernoulli(p_1);
                p_1=1-1/(1+exp_x[sum_cond]*exp_y[pi]);
                
                x_cond[i]=rnd2.Bernoulli(p_1);
                
            }
            
            for(pi=0; pi<pN;pi++)
            {
                
                i=loca[pi];
                
                sum=x[i+1]+x[i-1]+x[i+Lx]+x[i-Lx]+x[i+YbyX]+x[i-YbyX];
                sum_cond=x_cond[i+1]+x_cond[i-1]+x_cond[i+Lx]+x_cond[i-Lx]+x_cond[i+YbyX]+x_cond[i-YbyX];
                
                
                
                
                H_cond_mean[0]+=x_cond[i]*sum_cond;//warning:1/2 in the later, for compute twice//Don't forgot to divide swp_r at the end
                H_cond_mean[1]+=x_cond[i];
                
                
                
                H[sweep][0]+=x[i]*sum*0.5;
                H[sweep][1]+=x[i];
                
                gamma_1[pi]+=x_cond[i];//r_[i][1]
                //////////////////////////////////////////////////////////////
                
                
                
                
            }
            
            log_q2_sub[sweep]=-H[sweep][0]*beta_hat-H[sweep][1]*h_hat;
            //////////////////////////////////////////////////////////////////
            
            H_mean[0]+=H[sweep][0];//don't forgot to divide swp_r at the end
            H_mean[1]+=H[sweep][1];
            
            
        }
        ///////////////////////////////////////////////////////////////////////
        temp_like=*max_element(log_q2_sub.begin(), log_q2_sub.end());
        log_plikelihood=0;
        for(sweep=0;sweep<swp_r;sweep++)
        {
            log_plikelihood+=exp(log_q2_sub[sweep]-temp_like);
        }
        
        q2=temp_like+log(log_plikelihood);//-logZ

        
        
        
        
        
        ///////////////// U
        H_cond_mean[0]/=2;
        
        for(i=0;i<2;i++)
        {
            
            H_cond_mean[i]/=swp_r;
            H_mean[i]/=swp_r;
            
            U[i]=H_cond_mean[i]-H_mean[i];
            
        }
        
        
        
        two_d_var_matrix_inv( swp_r);// for I update
        //////////////////////////revised by 20140219
        
        
        
		for(pi=0;pi<pN;pi++)
		{
			gamma_1[pi]=gamma_1[pi]/swp_r;
			
		}
        
		double gamma_1_sum=sigmasum(gamma_1,0,pN);
        
		
        
        
        
		mu1_hat_pre=mu1_hat;
		sigma1_sq_hat_pre=sigma1_sq_hat;
		pEll_hat_pre=pEll_hat;
		
		if(L==1)
		{
			pEll_hat[0]=1;
			mu1_hat[0]=(sigmasum(gamma_1,y,0,pN)+TINY)/(gamma_1_sum+TINY);//+TINY to avoid the case gamma_1_sum=0
			sigma1_sq_hat[0]=(sigmasum(gamma_1,y,mu1_hat[0],0,pN )+TINY)/(gamma_1_sum+TINY);
		}
		else
		{
            
            
			vector<double> f1y(pN);
			vector<double> omega_sum(L);
			vector<vector<double> > omega(L,vector<double>(pN));
			
			for(pi=0;pi<pN;pi++)
			{
				
				
				for(ell=0;ell<L;ell++)
				{
					f1y[pi]+=pEll_hat[ell]*normpdf(y[pi], mu1_hat[ell], sigma1_sq_hat[ell]);
					
				}
				for(ell=0;ell<L;ell++)
				{
					omega[ell][pi]=gamma_1[pi]*pEll_hat[ell] \
					*normpdf(y[pi],mu1_hat[ell],sigma1_sq_hat[ell])/f1y[pi];
					omega_sum[ell]+=omega[ell][pi];
				}
			}
			
            
			
			
			
			for(ell=0;ell<L;ell++)
			{
                
                
                
				mu1_hat[ell]=(sigmasum(omega[ell],y,0,pN )+TINY)/(omega_sum[ell]+TINY);// +TINY to avoid omega_sum[ell]=0
				sigma1_sq_hat[ell]=(sigmasum(omega[ell],y,mu1_hat[ell],0,pN )+2*a)/(omega_sum[ell]+2*b);//PMLE
                
                
                
                
                
                if(ell==(L-1))
				{
					pEll_hat[ell]=0;
					for(int ell_sub=0;ell_sub<ell;ell_sub++)
					{
						pEll_hat[ell]+=pEll_hat[ell_sub];
					}
					pEll_hat[ell]=1-pEll_hat[ell];
                    
                    
                    
                    
                    ///////if pELL_hat[L-1]<0, because of precision problem, to be like -2.22045e-16
                    if(pEll_hat[ell]<0)
                    {
                        pEll_hat[(ell-1)]+=pEll_hat[ell];
                        pEll_hat[ell]=0;
                    }
                    
                    
				}
				else {
					pEll_hat[ell]=(omega_sum[ell]+TINY_L)/(gamma_1_sum+TINY);//+TINY to avoid gamma_1_sum=0
                   
				}
                
                
                
			}
			
            
			
			
			
			
		}
        
        
		
 	
        backtrack(rnd2);
        
        //m iteration is over
        
        
        
        
		///////////////////////
		diff[0]=fabs(beta_hat_pre-beta_hat)/(fabs(beta_hat_pre)+del);
		diff[1]=fabs(h_hat_pre-h_hat)/(fabs(h_hat_pre)+del);
		
        
		
		
		for(ell=0;ell<L;ell++)
		{
            if(pEll_hat_pre[ell]<1e-3 && pEll_hat[ell]<1e-3)
            {
                
                diff[2+ell]=0;
                diff[2+L+ell]=0;
                diff[2+2*L+ell]=0;
                
            }
            else
            {
                
                diff[2+ell]=fabs(mu1_hat_pre[ell]-mu1_hat[ell])/(fabs(mu1_hat_pre[ell])+del );
                diff[2+L+ell]=fabs(sigma1_sq_hat_pre[ell]-sigma1_sq_hat[ell])/(fabs(sigma1_sq_hat_pre[ell])+del );
                diff[2+2*L+ell]=fabs(pEll_hat_pre[ell]-pEll_hat[ell])/(fabs(pEll_hat_pre[ell])+del );
                
                
                
                
                
            }
		}
		d1=*max_element(diff.begin(), diff.end());
	
        
        
        if(d1<1e-3 && alam==1 && stpover==0)
        {
            succ_t++;
        }
        else
        {
            succ_t=0;
        }
        
        if(succ_t==3)
        {
            n_tout=0;//satisfying the stopping rule for consecutive three times 
        }
        
        
        
        
		
		
    }// t iteration is over
    
    
    
    
    /////////////////////////////////////////////////////////
    //   ofstream fileout2;
    ofstream fileout2;
    
    
	fileout2.open (filename);
	
    
    
	fileout2<<beta_hat<<" "<<h_hat;
    for(ell=0;ell<L;ell++)
	{
		fileout2<<" "<<mu1_hat[ell];
		fileout2<<" "<<sigma1_sq_hat[ell];
		fileout2<<" "<<pEll_hat[ell];
	}
    
    
    
    fileout2.close();
}


void braindt::func(ofstream &fileout,StochasticLib1 &rnd2)//update U and q2 in the Armijo condition
{
    vector<double> log_q2_sub(swp_r);// -phi^T*H(x)
   
    double temp_like;
    H_mean=H_mean0;
    H=H0;
	int pi,i,sweep,sum;
	double p_1;
	vector<int> x(N );
	for(pi=0;pi<pN;pi++)
	{
		i=loca[pi];
		x[i]=initial[pi];
	}
	
	
	double exp_x[7];
	for(i=0; i<7; i++)
	{
		exp_x[i]=exp(beta_hat*i+h_hat);
	}  
	for(sweep=1;sweep<swp_b;sweep++)
	{
		for(pi=0; pi<pN;pi++)
		{
			
			
			
			i=loca[pi];
            
            sum=x[i+1]+x[i-1]+x[i+Lx]+x[i-Lx]+x[i+YbyX]+x[i-YbyX];
 
			
			p_1=1-1/(1+exp_x[sum]);
			
			x[i]=rnd2.Bernoulli(p_1);
			
			
		}
		
	}	
	

	
	for(sweep=0;sweep<swp_r;sweep++)
	{
      
        for(pi=0; pi<pN;pi++)
		{
			
			
			
			i=loca[pi];
            
			sum=x[i+1]+x[i-1]+x[i+Lx]+x[i-Lx]+x[i+YbyX]+x[i-YbyX];
			p_1=1-1/(1+exp_x[sum]);
			
			x[i]=rnd2.Bernoulli(p_1);
			
			
		}
		
		
		for(pi=0;pi<pN;pi++)
		{
			
			
			
			i=loca[pi];
            
			sum=x[i+1]+x[i-1]+x[i+Lx]+x[i-Lx]+x[i+YbyX]+x[i-YbyX];
			
			
			
			H[sweep][0]+=x[i]*sum*0.5;
			H[sweep][1]+=x[i];
            //////////////////////////////////////////////////////////////
           
            
			
		}
		log_q2_sub[sweep]=-H[sweep][0]*beta_hat-H[sweep][1]*h_hat;
       
        //////////////////////////////////////////////////////////////////
			
		
		H_mean[0]+=H[sweep][0];//don't forgot to divide  swp_r at the end
		H_mean[1]+=H[sweep][1];
		
		
	}
	///////////////////////////////

    
    
    
    temp_like=*max_element(log_q2_sub.begin(), log_q2_sub.end());
    log_plikelihood=0;
    for(sweep=0;sweep<swp_r;sweep++)
    {
        log_plikelihood+=exp(log_q2_sub[sweep]-temp_like);
    }
    
    q2=temp_like+log(log_plikelihood);//-logZ
    //fileout<<"q2="<<q2<<endl;
    

	fileout<<"The score function U:"<<endl;

	for(i=0;i<2;i++)
	{
		H_mean[i]/=swp_r;
		
		U[i]=H_cond_mean[i]-H_mean[i];
		
		fileout<<"U["<<i<<"]="<<U[i]<<endl;
		fileout<<"H_cond_mean["<<i<<"]="<<H_cond_mean[i]<<endl;
		fileout<<"H_mean["<<i<<"]="<<H_mean[i]<<endl;
		
	}
	
	
	
	
}
void braindt::func(StochasticLib1 &rnd2)//update U and q2 in the Armijo condition
{
    vector<double> log_q2_sub(swp_r);// -phi^T*H(x)
   
    double temp_like;
    H_mean=H_mean0;
    H=H0;
	int pi,i,sweep,sum;
	double p_1;
	vector<int> x(N );
	for(pi=0;pi<pN;pi++)
	{
		i=loca[pi];
		x[i]=initial[pi];
	}
	
	
	double exp_x[7];
	for(i=0; i<7; i++)
	{
		exp_x[i]=exp(beta_hat*i+h_hat);
	}
	for(sweep=1;sweep<swp_b;sweep++)
	{
		for(pi=0; pi<pN;pi++)
		{
			
			
			
			i=loca[pi];
            
            sum=x[i+1]+x[i-1]+x[i+Lx]+x[i-Lx]+x[i+YbyX]+x[i-YbyX];
            
			
			p_1=1-1/(1+exp_x[sum]);
			
			x[i]=rnd2.Bernoulli(p_1);
			
			
		}
		
	}
	
    
	
	for(sweep=0;sweep<swp_r;sweep++)
	{
      
        for(pi=0; pi<pN;pi++)
		{
			
			
			
			i=loca[pi];
            
			sum=x[i+1]+x[i-1]+x[i+Lx]+x[i-Lx]+x[i+YbyX]+x[i-YbyX];
			p_1=1-1/(1+exp_x[sum]);
			
			x[i]=rnd2.Bernoulli(p_1);
			
			
		}
		
		
		for(pi=0;pi<pN;pi++)
		{
			
			
			
			i=loca[pi];
            
			sum=x[i+1]+x[i-1]+x[i+Lx]+x[i-Lx]+x[i+YbyX]+x[i-YbyX];
			
			
			
			H[sweep][0]+=x[i]*sum*0.5;
			H[sweep][1]+=x[i];
            //////////////////////////////////////////////////////////////
            
            
			
		}
		log_q2_sub[sweep]=-H[sweep][0]*beta_hat-H[sweep][1]*h_hat;
        
        //////////////////////////////////////////////////////////////////
        
		
		H_mean[0]+=H[sweep][0];//don't forgot to divide  swp_r at the end
		H_mean[1]+=H[sweep][1];
		
		
	}
	///////////////////////////////
    
    
    
    
    temp_like=*max_element(log_q2_sub.begin(), log_q2_sub.end());
    log_plikelihood=0;
    for(sweep=0;sweep<swp_r;sweep++)
    {
        log_plikelihood+=exp(log_q2_sub[sweep]-temp_like);
    }
    
    q2=temp_like+log(log_plikelihood);//-logZ
    
    
    

	
	
}


void braindt::backtrack(ofstream &fileout,StochasticLib1 &rnd2)//The backtracking line search method
{//see P479 code of the book Numerical Recipe, 3rd
    stpover=0;
	q2_old=q2;
	
    double del=1e-3;
    
	beta_hat_old=beta_hat;
	h_hat_old=h_hat;
	


	const double ALF=1e-4;//alpha in the Armijo condition
	const double tolx=1e-4;//tolerance for error in m iteration of backtracking 
	const double stpmax=5;// the maximum length of the newton step
	
	
	double alamin;//the minimum lambda in the Armijo condition
	
	
	double temp,test;
	

	
    delta[0]=invI[0]*U[0]+invI[1]*U[1];
	delta[1]=invI[1]*U[0]+invI[2]*U[1];
	
	double sum=delta[0]*delta[0]+delta[1]*delta[1];//delta=p in the book, is the regular newton step
	sum=sqrt(sum);
	if(sum>stpmax)//Scale if attempted step is too big.
	{
        stpover=1;
		delta[0]*=stpmax/sum;
		delta[1]*=stpmax/sum;
        //fileout<<"in backtrack firt delta1="<<delta[0]<<endl;
        //fileout<<"in backtrack firt delta2="<<delta[1]<<endl;
        fileout<<"Over the max step in backtracking,the step is thus scaled"<<endl;
	}
    
    
	double slope=U[0]*delta[0]+U[1]*delta[1];
	//fileout<<"U*invI*U="<<slope<<endl;

	
	temp=fabs(delta[0])/(fabs(beta_hat_old)+del);
	test=fabs(delta[1])/(fabs(h_hat_old)+del);
	test=test>temp?test:temp;
	alamin=tolx/test;
	alam=1;
	int m=0;//
	
	
	fileout<<"The backtracking iteration m=0"<<endl;
	fileout<<"lambda="<<alam<<endl;
	
	for(;;)
	{
		if(alam<alamin)
		{
           
            fileout<<"Converge at the case that lambda less than the minimum limit"<<endl;
			beta_hat=beta_hat_old;
			h_hat=h_hat_old;
            
			break;
		}
		else {
			
			beta_hat=beta_hat_old+alam*delta[0];
			h_hat=h_hat_old+alam*delta[1];
			
			
			fileout<<"beta_hat="<<beta_hat<<endl;
			fileout<<"h_hat="<<h_hat<<endl;
			
            
			
			func(fileout,rnd2);//update q2
            

           // fileout<<"q2_old="<<q2_old<<endl;
           // fileout<<"q2="<<q2<<endl;
            delta_q2=(beta_hat-beta_hat_old)*H_cond_mean[0]+(h_hat-h_hat_old)*H_cond_mean[1]+q2-q2_old;//q2-q2old
            fileout<<"delta_Q2="<<delta_q2<<endl;
            
			
			if(delta_q2<(ALF*alam*slope))
			{
				m++;
				fileout<<"The backtracking iteration m="<<m<<endl;
                alam*=0.5;
				fileout<<"lambda="<<alam<<endl;
			}
			else{
				
				fileout<<"End backtracking for the Q2 increase"<<endl;
				break;
			}
			
		}

        
        
	}
}


void braindt::backtrack(StochasticLib1 &rnd2)//The backtracking line search method
{//see P479 code of the book Numerical Recipe, 3rd
    stpover=0;
	q2_old=q2;
	
    double del=1e-3;
    
	beta_hat_old=beta_hat;
	h_hat_old=h_hat;
	

    
	const double ALF=1e-4;//alpha in the Armijo condition
	const double tolx=1e-4;//tolerance for error in m iteration of backtracking
	const double stpmax=5;// the maximum length of the newton step
	
	
	double alamin;//the minimum lambda in the Armijo condition
	
	
	double temp,test;
	
	
	
    delta[0]=invI[0]*U[0]+invI[1]*U[1];
	delta[1]=invI[1]*U[0]+invI[2]*U[1];
	
	double sum=delta[0]*delta[0]+delta[1]*delta[1];//delta=p in the book, is the regular newton step
	sum=sqrt(sum);
	if(sum>stpmax)//Scale if attempted step is too big.
	{
        stpover=1;
		delta[0]*=stpmax/sum;
		delta[1]*=stpmax/sum;
    
	}
    
    
	double slope=U[0]*delta[0]+U[1]*delta[1];
	
	
	
	temp=fabs(delta[0])/(fabs(beta_hat_old)+del);
	test=fabs(delta[1])/(fabs(h_hat_old)+del);
	test=test>temp?test:temp;
	alamin=tolx/test;
	alam=1;

	for(;;)
	{
		if(alam<alamin)
		{
            
            
			beta_hat=beta_hat_old;
			h_hat=h_hat_old;
            
			break;
		}
		else {
			beta_hat=beta_hat_old+alam*delta[0];
			h_hat=h_hat_old+alam*delta[1];
			
			
			
			
            
			
			func(rnd2);//update q2
            
            
           
            delta_q2=(beta_hat-beta_hat_old)*H_cond_mean[0]+(h_hat-h_hat_old)*H_cond_mean[1]+q2-q2_old;//q2-q2old
            
            
			
			if(delta_q2<(ALF*alam*slope))
			{

				
                
                alam*=0.5;
			}
			else{
				
				
				break;
			}
			
		}
        
        
        
	}
}



////////////////computing LIS
void braindt::computeLIS(char* filename)
{
    
    int seed=0;
	CRandomMersenne rnd1(seed);
	StochasticLib1  rnd2(seed);
	
    
	int i,j,k,nn,sum,sum_cond,sweep,ell,pi;
	int m;///////
	
	
    
	double exp_x[7];
	vector<double> exp_y(pN );
	
	
	
	double p_1;
	
	
	double temp,temp2;
    
	
	vector<double> constant(L );
	
	vector<int> x_cond(N );// conditional x
    
	
	double constant_0=sqrt(2*M_PI*sigma0_sq);
	vector<double> temp1(pN);
	
	
	
	for(pi=0;pi<pN ;pi++)
	{
		temp1[pi]=constant_0*exp(pow(y[pi]-mu0,2)/(2*sigma0_sq));
	}
    
    
	for(i=0; i<7; i++)
	{
		exp_x[i]=exp(beta_hat*i+h_hat);
	}
    
    
    
	for(i=0;i<L;i++)
	{
		constant[i]=pEll_hat[i]/sqrt(2*M_PI*sigma1_sq_hat[i]);
		
	}
	for(pi=0;pi<pN;pi++)
	{
		i=loca[pi];
		x_cond[i]=initial[pi];//
		temp2=0;
		for(j=0;j<L;j++)
		{
			temp2+=constant[j]*exp(-pow(y[pi]-mu1_hat[j],2)/(2*sigma1_sq_hat[j]));
		}
		exp_y[pi]=temp1[pi]*temp2;
		
	}
	
    
	for(int sweep=1;sweep<swp_b;sweep++)
	{
        
		for(pi=0; pi<pN;pi++)
		{
			i=loca[pi];
            
            
            sum_cond=x_cond[i+1]+x_cond[i-1]+x_cond[i+Lx]+x_cond[i-Lx]+x_cond[i+YbyX]+x_cond[i-YbyX];
            
			p_1=1-1/(1+exp_x[sum_cond]*exp_y[pi]);
			x_cond[i]=rnd2.Bernoulli(p_1);
		}
		
		
		
        
		
		
		
		
        
		
	}
	
	for(int sweep=0;sweep<swp_lis;sweep++)
	{
        
		for(pi=0; pi<pN;pi++)
		{
			i=loca[pi];
            
            sum_cond=x_cond[i+1]+x_cond[i-1]+x_cond[i+Lx]+x_cond[i-Lx]+x_cond[i+YbyX]+x_cond[i-YbyX];
			
			
            
			p_1=1-1/(1+exp_x[sum_cond]*exp_y[pi]);
			x_cond[i]=rnd2.Bernoulli(p_1);
			
			
            LIS[pi]+=x_cond[i];
            
            
			
		}
        
	}
    
    
    ofstream file;
    
    file.open (filename);
    
    for(pi=0;pi<pN ;pi++)
    {
        LIS[pi]=1-LIS[pi]/swp_lis;
        file<<LIS[pi]<<" ";
    }
	
    file.close();
    
    
}







back to top