void mexFunction( int nlhs, mxArray *plhs[] , int nrhs, const mxArray *prhs[] )

{
	
	
	double *PI , *A, *L ;
	
	double *alpha, *beta, *gamma, *loglik, *xi_summed; 
	
	const int *dimsPI , *dimsA , *dimsL ;
	
	
	int K , N , numdimsPI , numdimsA  , numdimsL  , filter = 2;
	
	double  *scale, *tmp_xi;
	
	/*---------------------------------------------------------------*/
	/*---------------------- PARSE INPUT ----------------------------*/	
	/*---------------------------------------------------------------*/
	
	if( (nrhs < 3) | (nrhs >5))
		
	{
		
		mexErrMsgTxt("3 or 4 input are requiered");
		
	}
	
	PI         = mxGetPr(prhs[0]);
    
  numdimsPI  = mxGetNumberOfDimensions(prhs[0]);
    
	dimsPI     = mxGetDimensions(prhs[0]);
	
	if ( (numdimsPI != 2) | (dimsPI[1] > dimsPI[0]) )
	{
		
		mexErrMsgTxt("PI must be (N x 1)");			 
		
	}
	
	
	A         = mxGetPr(prhs[1]);
    
  numdimsA  = mxGetNumberOfDimensions(prhs[1]);
    
	dimsA     = mxGetDimensions(prhs[1]);
	
	if ( (numdimsA != 3) | (dimsA[1] != dimsA[0]) )
	{
		
		mexErrMsgTxt("A must be (N x N x K-1)");			 
		
	}
	
	
	L         = mxGetPr(prhs[2]);
    
  numdimsL  = mxGetNumberOfDimensions(prhs[2]);
    
	dimsL     = mxGetDimensions(prhs[2]);
	
	if ( (numdimsL != 2) | (dimsL[0] != dimsA[0]) )
	{
		
		mexErrMsgTxt("L must be (N x K)");			 
		
	}
	
  N         = dimsL[0];
	
	K         = dimsL[1];
		
	
	if (nrhs == 4)
		
	{
		filter = (int)mxGetScalar(prhs[3]);
		
	}
	
	
	/*---------------------------------------------------------------*/
	/*---------------------- PARSE OUTPUT ---------------------------*/	
	/*---------------------------------------------------------------*/
	
	plhs[0]       = mxCreateDoubleMatrix(N , K , mxREAL);
	
	alpha         = mxGetPr(plhs[0]);
	
	
	plhs[1]       = mxCreateDoubleMatrix(N , K , mxREAL);
    
	gamma         = mxGetPr(plhs[1]);
	
	
	plhs[2]       = mxCreateDoubleMatrix(1 , 1 , mxREAL);
    
	loglik        = mxGetPr(plhs[2]);
	
	
	if (filter > 0) { /*calculate beta*/
				plhs[3]       = mxCreateDoubleMatrix(N , K , mxREAL);
	    
				beta          = mxGetPr(plhs[3]);
	}
	

	
	if (filter > 1) { /*calculate xi_summed*/
				plhs[4]       = mxCreateDoubleMatrix(N , N , mxREAL);
			    
				xi_summed     = mxGetPr(plhs[4]);
	}
	

	
	/*---------------------------------------------------------------*/
	/*--------- Internal Tempory vector & matrices ------------------*/
	/*---------------------------------------------------------------*/

	scale         = (double *)mxMalloc(K*sizeof(double));
	
	tmp_xi				= (double *)mxMalloc(N*N*sizeof(double));
	/*---------------------------------------------------------------*/
	/*------------------------ MAIN CALL ----------------------------*/
	/*---------------------------------------------------------------*/
	
	ForwardWithScale(N, K, filter, PI, A, L, alpha, gamma, loglik, scale);
	
	if (filter > 0) /*calculate both alpha and beta, but xi_summed is not calculated*/
			BackwardWithScale(N, K, PI, A, L, beta);
			
	if (filter == 1) /*calculate gamma with alpha and beta*/
			ComputeGamma(N, K, alpha, beta, gamma);			
			
	if (filter > 1) /*calculate gamma and xi_summed based on xi*/
			ComputeXi(N, K, A, L, alpha, beta, gamma, tmp_xi, xi_summed);
	
	/*---------------------------------------------------------------*/
	/*------------------------ FREE MEMORY --------------------------*/
	/*---------------------------------------------------------------*/
	
	
 	mxFree(scale);
	
	mxFree(tmp_xi);
	
}
Esempio n. 2
0
void BaumWelch(HMM *phmm, int T, int *O, double **alpha, double **beta,
	double **gamma, int *pniter, 
	double *plogprobinit, double *plogprobfinal)
{
	int	i, j, k;
	int	t, l = 0;

	double	logprobf, logprobb,  threshold;
	double	numeratorA, denominatorA;
	double	numeratorB, denominatorB;

	double ***xi, *scale;
	double delta, deltaprev, logprobprev;

	deltaprev = 10e-70;

	xi = AllocXi(T, phmm->N);
	scale = dvector(1, T);

	ForwardWithScale(phmm, T, O, alpha, scale, &logprobf);
	*plogprobinit = logprobf; /* log P(O |intial model) */
	BackwardWithScale(phmm, T, O, beta, scale, &logprobb);
	ComputeGamma(phmm, T, alpha, beta, gamma);
	ComputeXi(phmm, T, O, alpha, beta, xi);
	logprobprev = logprobf;

	do  {	

		/* reestimate frequency of state i in time t=1 */
		for (i = 1; i <= phmm->N; i++) 
			phmm->pi[i] = .001 + .999*gamma[1][i];

		/* reestimate transition matrix  and symbol prob in
		   each state */
		for (i = 1; i <= phmm->N; i++) { 
			denominatorA = 0.0;
			for (t = 1; t <= T - 1; t++) 
				denominatorA += gamma[t][i];

			for (j = 1; j <= phmm->N; j++) {
				numeratorA = 0.0;
				for (t = 1; t <= T - 1; t++) 
					numeratorA += xi[t][i][j];
				phmm->A[i][j] = .001 + 
						.999*numeratorA/denominatorA;
			}

			denominatorB = denominatorA + gamma[T][i]; 
			for (k = 1; k <= phmm->M; k++) {
				numeratorB = 0.0;
				for (t = 1; t <= T; t++) {
					if (O[t] == k) 
						numeratorB += gamma[t][i];
				}

				phmm->B[i][k] = .001 +
						.999*numeratorB/denominatorB;
			}
		}

		ForwardWithScale(phmm, T, O, alpha, scale, &logprobf);
		BackwardWithScale(phmm, T, O, beta, scale, &logprobb);
		ComputeGamma(phmm, T, alpha, beta, gamma);
		ComputeXi(phmm, T, O, alpha, beta, xi);

		/* compute difference between log probability of 
		   two iterations */
		delta = logprobf - logprobprev; 
		logprobprev = logprobf;
		l++;
		
	}
	while (delta > DELTA); /* if log probability does not 
                                  change much, exit */ 
 
	*pniter = l;
	*plogprobfinal = logprobf; /* log P(O|estimated model) */
	FreeXi(xi, T, phmm->N);
	free_dvector(scale, 1, T);
}
void BaumWelch(HMM *phmm, int T, int *O, double **alpha, double **beta,
	double **gamma)
{
	int	i, j, k;
	int	t, l = 0;

	double	probf, probb, val, threshold;
	double	numeratorA, denominatorA;
	double	numeratorB, denominatorB;

	double ***xi, *scale;
	double delta, deltaprev, probprev;
	double ratio;

	deltaprev = 10e-70;

	xi = AllocXi(T, phmm->N);
	scale = dvector(1, T);

	ForwardWithScale(phmm, T, O, alpha, scale, &probf);
	BackwardWithScale(phmm, T, O, beta, scale, &probb);
	ComputeGamma(phmm, T, alpha, beta, gamma);
	ComputeXi(phmm, T, O, alpha, beta, xi);
	probprev = probf;

	do  {	

		/* reestimate frequency of state i in time t=1 */
		for (i = 1; i <= phmm->N; i++) 
			phmm->pi[i] = .001 + .999*gamma[1][i];

		/* reestimate transition matrix  and symbol prob in
		   each state */
		for (i = 1; i <= phmm->N; i++) { 
			denominatorA = 0.0;
			for (t = 1; t <= T - 1; t++) 
				denominatorA += gamma[t][i];

			for (j = 1; j <= phmm->N; j++) {
				numeratorA = 0.0;
				for (t = 1; t <= T - 1; t++) 
					numeratorA += xi[t][i][j];
				phmm->A[i][j] = .001 + 
						.999*numeratorA/denominatorA;
			}

			denominatorB = denominatorA + gamma[T][i]; 
			for (k = 1; k <= phmm->M; k++) {
				numeratorB = 0.0;
				for (t = 1; t <= T; t++) {
					if (O[t] == k) 
						numeratorB += gamma[t][i];
				}

				phmm->B[i][k] = .001 +
						.999*numeratorB/denominatorB;
			}
		}

		ForwardWithScale(phmm, T, O, alpha, scale, &probf);
		BackwardWithScale(phmm, T, O, beta, scale, &probb);
		ComputeGamma(phmm, T, alpha, beta, gamma);
		ComputeXi(phmm, T, O, alpha, beta, xi);

		delta = probf - probprev;
		ratio = delta/deltaprev;
		probprev = probf;
		deltaprev = delta;
		l++;
		
	}
	while (ratio > DELTA);
	printf("num iterations: %d\n", l); 
	FreeXi(xi, T, phmm->N);
	free_dvector(scale, 1, T);
}
Esempio n. 4
0
int main() {

    const std::string Help =
        "-------------------------------------------------------------------------\n"
        "TestComputeAKV:                                                          \n"
        "-------------------------------------------------------------------------\n"
        "OPTIONS:                                                                 \n"
        "Nth=<int>  theta resolution [default 3]                                  \n"
        "Nph=<int>  phi resolution [default 4]                                    \n"
        "Radius=<double> radius of sphere. [default 1.0]                          \n"
        "AKVGuess=MyVector<double> a guess for the values of THETA, thetap, phip  \n"
        "         [default (0.,0.,0.)]                                            \n"
        "L_resid_tol=<double> tolerance for L residuals when finding approximate  \n"
        "            Killing vectors.  [default 1.e-12]                           \n"
        "v_resid_tol=<double> tolerance for v residuals when finding approximate  \n"
        "            Killing vectors.  [default 1.e-12]                           \n"
        "min_thetap = for values less than this, thetap is considered close to    \n"
        "               zero. [default 1.e-5]                                     \n"
        "symmetry_tol=<double> abs(THETA) must be less than this value to be      \n"
        "             considered an exact symmetry.  [default 1.e-11]             \n"
        "ResidualSize=<double> determines the tolerance for residuals from the    \n"
        "             multidimensional root finder.  [default to 1.e-11]          \n"
        "Solver = <std::string> which gsl multidimensional root finding algorith  \n"
        "        should be used. [default Newton]                                 \n"
        "Verbose=<bool> Print spectral coefficients and warnings if true          \n"
        "        [default false]                                                  \n"
        ;

    std::string Options = ReadFileIntoString("Test.input");
    OptionParser op(Options,Help);
    const int Nth = op.Get<int>("Nth", 3);
    const int Nph = op.Get<int>("Nph", 4);
    const double rad = op.Get<double>("Radius",1.0);
    MyVector<double> AKVGuess =
        op.Get<MyVector<double> >("AKVGuess",MyVector<double>(MV::Size(3),0.0));
    //must be three-dimensional
    REQUIRE(AKVGuess.Size()==3,"AKVGuess has Size " << AKVGuess.Size()
            << ", should be 3.");
    const double L_resid_tol = op.Get<double>("L_resid_tol", 1.e-12);
    const double v_resid_tol = op.Get<double>("L_resid_tol", 1.e-12);
    const double residualSize = op.Get<double>("ResidualSize", 1.e-11);
    const double min_thetap = op.Get<double>("min_theta",1.e-5);
    const double symmetry_tol = op.Get<double>("symmetry_tol",1.e-11);
    const std::string solver = op.Get<std::string>("Solver","Newton");
    const bool verbose = op.Get<bool>("Verbose", false);
    const MyVector<bool> printDiagnostic = MyVector<bool>(MV::Size(6), true);

    //create skm
    const StrahlkorperMesh skm(Nth, Nph);
    //create surface basis
    const SurfaceBasis sb(skm);
    //get theta, phi
    const DataMesh theta(skm.SurfaceCoords()(0));
    const DataMesh phi(skm.SurfaceCoords()(1));

    //set the initial guesses to be along particular axes
    const int axes = 3; //the number of perpendicular axes

    //create conformal factors for every rotation
    const int syms = 5; //the number of axisymmetries we are testing

    for(int s=4; s<5; s++) { //index over conformal factor symmetries
        //for(int s=0; s<syms; s++){//index over conformal factor symmetries
        //create conformal factor
        const DataMesh Psi = ConstructConformalFactor(theta, phi, s);

        //set the initial guesses
        double THETA[3] = {AKVGuess[0],0.,0.};
        double thetap[3] = {AKVGuess[1],0.,0.};
        double phip[3] = {AKVGuess[2],0.,0.};

        //save the v, xi solutions along particular axes
        MyVector<DataMesh> v(MV::Size(3),DataMesh::Empty);
        MyVector<DataMesh> rotated_v(MV::Size(3),DataMesh::Empty);
        MyVector<Tensor<DataMesh> > xi(MV::Size(axes),Tensor<DataMesh>(2,"1",DataMesh::Empty));

        //save the <v_i|v_j> inner product solutions
        double v0v0 = 0.;
        double v1v1 = 0.;
        double v2v2 = 0.;
        double v0v1 = 0.;
        double v0v2 = 0.;
        double v1v2 = 0.;
        //int symmetries[3] = 0; //counts the number of symmetries

        //compute some useful quantities
        const DataMesh rp2 = rad * Psi * Psi;
        const DataMesh r2p4 = rp2*rp2;
        const DataMesh llncf = sb.ScalarLaplacian(log(Psi));
        const DataMesh Ricci = 2.0 * (1.0-2.0*llncf) / r2p4;
        const Tensor<DataMesh> GradRicci = sb.Gradient(Ricci);

        for(int a=0; a<axes; a++) { //index over perpendicular axes to find AKV solutions

            //if the diagnostics below decide that there is a bad solution for v[a]
            //(usually a repeated solution), this flag will indicate that the
            //solver should be run again
            bool badAKVSolution = false;

            //generate a guess for the next axis of symmetry based on prior solutions.
            AxisInitialGuess(thetap, phip, a);

            //create L
            DataMesh L(DataMesh::Empty);

            //setup struct with all necessary data
            rparams p = {theta, phi, rp2, sb, llncf, GradRicci,
                         L, v[a], L_resid_tol, v_resid_tol, verbose, true
                        };

            RunAKVsolvers(THETA[a], thetap[a], phip[a], min_thetap,
                          residualSize, verbose, &p, solver);

            std::cout << "Solution found with : THETA[" << a << "] = " << THETA[a] << "\n"
                      << "                     thetap[" << a << "] = " << (180.0/M_PI)*thetap[a] << "\n"
                      << "                       phip[" << a << "] = " << (180.0/M_PI)*phip[a]
                      << std::endl;

            //check inner products
            // <v_i|v_j> = Integral 0.5 * Ricci * Grad(v_i) \cdot Grad(v_j) dA
            switch(a) {
            case 0:
                //compute inner product <v_0|v_0>
                v0v0 = AKVInnerProduct(v[0],v[0],Ricci,sb)*sqrt(2.)*M_PI;
                //if(v0v0<symmetry_tol) //symmetries++;
                std::cout << "<v_0|v_0> = " << v0v0 << std::endl;
                std::cout << "-THETA <v_0|v_0> = " << -THETA[a]*v0v0 << std::endl;
                break;
            case 1:
                //compute inner products <v_1|v_1>, <v_0|v_1>
                v1v1 = AKVInnerProduct(v[1],v[1],Ricci,sb)*sqrt(2.)*M_PI;
                v0v1 = AKVInnerProduct(v[0],v[1],Ricci,sb)*sqrt(2.)*M_PI;
                //if(v1v1<symmetry_tol) //symmetries++;
                std::cout << "<v_1|v_1> = " << v1v1 << std::endl;
                std::cout << "<v_0|v_1> = " << v0v1 << std::endl;
                std::cout << "-THETA <v_1|v_1> = " << -THETA[a]*v1v1 << std::endl;
                if(fabs(v0v0) == fabs(v1v2)) badAKVSolution = true;
                break;
            case 2:
                //compute inner products <v_2|v_2>, <v_0|v_2>, <v_1|v_2>
                v2v2 = AKVInnerProduct(v[2],v[2],Ricci,sb)*sqrt(2.)*M_PI;
                v0v2 = AKVInnerProduct(v[0],v[2],Ricci,sb)*sqrt(2.)*M_PI;
                v1v2 = AKVInnerProduct(v[1],v[2],Ricci,sb)*sqrt(2.)*M_PI;
                //if(v2v2<symmetry_tol) //symmetries++;
                std::cout << "<v_2|v_2> = " << v2v2 << std::endl;
                std::cout << "<v_0|v_2> = " << v0v2 << std::endl;
                std::cout << "<v_1|v_2> = " << v1v2 << std::endl;
                std::cout << "-THETA <v_2|v_2> = " << -THETA[a]*v2v2 << std::endl;
                if(fabs(v0v0) == fabs(v0v2)) badAKVSolution = true;
                if(fabs(v1v1) == fabs(v1v2)) badAKVSolution = true;
                break;
            }

            //Gram Schmidt orthogonalization
            switch(a) {
            case 1:
                if(v0v0<symmetry_tol && v1v1<symmetry_tol) { //two symmetries, v2v2 should also be symmetric
                    GramSchmidtOrthogonalization(v[0], v0v0, v[1], v0v1);
                }
                break;
            case 2:
                if(v0v0<symmetry_tol) {
                    if(v1v1<symmetry_tol) {
                        REQUIRE(v2v2<symmetry_tol, "Three symmetries required, but only two found.");
                        GramSchmidtOrthogonalization(v[0], v0v0, v[2], v0v2);
                        GramSchmidtOrthogonalization(v[1], v1v1, v[2], v1v2);
                    } else if(v2v2<symmetry_tol) {
                        REQUIRE(false, "Three symmetries required, but only two found.");
                    } else {
                        GramSchmidtOrthogonalization(v[1], v1v1, v[2], v1v2);
                    }
                } else if(v1v1<symmetry_tol) {
                    if(v2v2<symmetry_tol) {
                        REQUIRE(false, "Three symmetries required, but only two found.");
                    } else {
                        GramSchmidtOrthogonalization(v[0], v0v0, v[2], v0v2);
                    }
                } else if(v2v2<symmetry_tol) {
                    GramSchmidtOrthogonalization(v[0], v0v0, v[1], v0v1);
                }
                break;
            }

            //create xi (1-form)
            xi[a] = ComputeXi(v[a], sb);

            //perform diagnostics
            //Psi and xi are unscaled and unrotated
            KillingDiagnostics(sb, L, Psi, xi[a], rad, printDiagnostic);

            //rotate v, Psi for analysis
            rotated_v[a] = RotateOnSphere(v[a],theta,phi,
                                          sb,thetap[a],phip[a]);

            DataMesh rotated_Psi = RotateOnSphere(Psi,theta,phi,
                                                  sb,thetap[a],phip[a]);

            //compare scale factors

            const double scaleAtEquator =
                NormalizeAKVAtOnePoint(sb, rotated_Psi, rotated_v[a], rad, M_PI/2., 0.0);
            PrintSurfaceNormalization(sb,rotated_Psi,theta,phi,rotated_v[a],scaleAtEquator,rad);
            MyVector<double> scaleInnerProduct = InnerProductScaleFactors(v[a], v[a], Ricci, r2p4, sb);
            PrintSurfaceNormalization(sb,rotated_Psi,theta,phi,rotated_v[a],scaleInnerProduct[0],rad);
            PrintSurfaceNormalization(sb,rotated_Psi,theta,phi,rotated_v[a],scaleInnerProduct[1],rad);
            PrintSurfaceNormalization(sb,rotated_Psi,theta,phi,rotated_v[a],scaleInnerProduct[2],rad);
            OptimizeScaleFactor(rotated_v[a], rotated_Psi, rad, sb, theta,
                                phi, scaleAtEquator, scaleInnerProduct[0], scaleInnerProduct[1], scaleInnerProduct[2]);

            //scale v
            v[a] *= scaleAtEquator;

            //recompute scaled xi (1-form)
            xi[a] = ComputeXi(v[a], sb);

            if(badAKVSolution) {
                v[a] = 0.;
                thetap[a] += M_PI/4.;
                phip[a] += M_PI/4.;
                a--;
                std::cout << "This was a bad / repeated solution, and will be recomputed." << std::endl;
            }
            std::cout << std::endl;
        }//end loop over perpendicular AKV axes

        std::cout << "\n" << std::endl;
    }


    // Return 0 for success
    return NumberOfTestsFailed;
}
Esempio n. 5
0
/******************************************************************************
 **函数名称:BaumWelch
 **功能:BaumWelch算法
 **参数:phmm:HMM模型指针
 **      T:观察序列长度
 **      O:观察序列
 **      alpha,beta,gamma,pniter均为中间变量
 **      plogprobinit:初始概率
 **      plogprobfinal: 最终概率
 **/
void BaumWelch(HMM *phmm, int T, int *O, double **alpha, double **beta,
               double **gamma, int *pniter,
               double *plogprobinit, double *plogprobfinal)
{
    int	i, j, k;
    int	t, l = 0;
    
    double	logprobf, logprobb;
    double	numeratorA, denominatorA;
    double	numeratorB, denominatorB;
    
    double ***xi, *scale;
    double delta, deltaprev, logprobprev;
    
    deltaprev = 10e-70;
    
    xi = AllocXi(T, phmm->N);
    scale = dvector(1, T);
    
    ForwardWithScale(phmm, T, O, alpha, scale, &logprobf);
    *plogprobinit = logprobf; /* log P(O |初始状态) */
    BackwardWithScale(phmm, T, O, beta, scale, &logprobb);
    ComputeGamma(phmm, T, alpha, beta, gamma);
    ComputeXi(phmm, T, O, alpha, beta, xi);
    logprobprev = logprobf;
    
    do  {
        
        /* 重新估计 t=1 时,状态为i 的频率 */
        for (i = 1; i <= phmm->N; i++)
            phmm->pi[i] = .001 + .999*gamma[1][i];
        
        /* 重新估计转移矩阵和观察矩阵 */
        for (i = 1; i <= phmm->N; i++)
        {
            denominatorA = 0.0;
            for (t = 1; t <= T - 1; t++)
                denominatorA += gamma[t][i];
            
            for (j = 1; j <= phmm->N; j++)
            {
                numeratorA = 0.0;
                for (t = 1; t <= T - 1; t++)
                    numeratorA += xi[t][i][j];
                phmm->A[i][j] = .001 +
                .999*numeratorA/denominatorA;
            }
            
            denominatorB = denominatorA + gamma[T][i];
            for (k = 1; k <= phmm->M; k++)
            {
                numeratorB = 0.0;
                for (t = 1; t <= T; t++)
                {
                    if (O[t] == k)
                        numeratorB += gamma[t][i];
                }
                
                phmm->B[i][k] = .001 +
                .999*numeratorB/denominatorB;
            }
        }
        
        ForwardWithScale(phmm, T, O, alpha, scale, &logprobf);
        BackwardWithScale(phmm, T, O, beta, scale, &logprobb);
        ComputeGamma(phmm, T, alpha, beta, gamma);
        ComputeXi(phmm, T, O, alpha, beta, xi);
        
        /* 计算两次直接的概率差 */
        delta = logprobf - logprobprev;
        logprobprev = logprobf;
        l++;
    }
    while (delta > DELTA); /* 如果差的不太大,表明收敛,退出 */
    
    *pniter = l;
    *plogprobfinal = logprobf; /* log P(O|estimated model) */
    FreeXi(xi, T, phmm->N);
    free_dvector(scale, 1, T);
}