void Evrot::evrot() { // definitions int max_iter = 200; double dQ,Q,Q_new,Q_old1,Q_old2,Q_up,Q_down; double alpha; int iter,d; Eigen::VectorXd theta = Eigen::VectorXd::Zero(mNumAngles); Eigen::VectorXd theta_new = Eigen::VectorXd::Zero(mNumAngles); Q = evqual(mX); // initial quality if( DEBUG ) std::cout << "Q = " << Q << std::endl; Q_old1 = Q; Q_old2 = Q; iter = 0; while( iter < max_iter ){ // iterate to refine quality iter++; for( d = 0; d < mNumAngles; d++ ){ if( mMethod == 2 ){ // descend through numerical drivative alpha = 0.1; { // move up theta_new[d] = theta[d] + alpha; Eigen::MatrixXd& Xrot = rotate_givens(theta_new); Q_up = evqual(Xrot); delete &Xrot; } { // move down theta_new[d] = theta[d] - alpha; Eigen::MatrixXd& Xrot = rotate_givens(theta_new); Q_down = evqual(Xrot); delete &Xrot; } // update only if at least one of them is better if( Q_up > Q || Q_down > Q){ if( Q_up > Q_down ){ theta[d] = theta[d] + alpha; theta_new[d] = theta[d]; Q = Q_up; } else { theta[d] = theta[d] - alpha; theta_new[d] = theta[d]; Q = Q_down; } } } else { // descend through true derivative alpha = 1.0; dQ = evqualitygrad(theta, d); theta_new[d] = theta[d] - alpha * dQ; Eigen::MatrixXd& Xrot = rotate_givens(theta_new); Q_new = evqual(Xrot); delete &Xrot; if( Q_new > Q){ theta[d] = theta_new[d]; Q = Q_new; } else{ theta_new[d] = theta[d]; } } } // stopping criteria if( iter > 2 ){ if( Q - Q_old2 < 1e-3 ){ break; } } Q_old2 = Q_old1; Q_old1 = Q; } if (DEBUG) std::cout << "Done after " << iter << " iterations, Quality is " << Q << std::endl; mXrot = rotate_givens(theta_new); cluster_assign(); //output mQuality = Q; }
double evrot(double* mat,int dim,int ndata,int* out_clusts,double* out_xrot,int method) { int tmpi=0; int tmpk=0; int tmpj=0; int vari=0; int varj=0; int dk=5; int max_iter = 200; double dQ=0; double Q=0; double Q_new=0; double Q_old1=0; double Q_old2=0; double Q_up=0; double Q_down=0; double alpha=0; int iter=0; int d=0; double tmpDouble=0; int angle_num=0; angle_num=(int)(dim*(dim-1)/2); double* theta=new double[angle_num]; double* theta_new=new double[angle_num]; int* jk=new int[angle_num]; int* ik=new int[angle_num]; double* p_theta=theta; double* p_theta_new=theta_new; tmpi=0; for(vari=0;vari<dim-1;vari++) for(varj=vari+1;varj<=dim-1;varj++) { ik[tmpi]=vari; jk[tmpi]=varj; tmpi++; } Q = evqual(mat,dim,ndata); ///getchar(); Q_old1 = Q; Q_old2 = Q; iter = 0; MatrixInitZeros(out_xrot,dim,ndata); MatrixInitZeros(p_theta,1,angle_num); MatrixInitZeros(p_theta_new,1,angle_num); while( iter < max_iter ) {/* iterate to refine quality */ iter++; cout<<"iter "<<iter<<endl; for( d = 0; d < angle_num; d++ ) { if( method == 2 ) { /* descend through numerical drivative */ alpha = 0.1; /* move up */ p_theta_new[d] = p_theta[d] + alpha; rotate_givens(mat,theta_new,ik,jk,angle_num,ndata,dim,out_xrot); Q_up = evqual(out_xrot,dim,ndata); MatrixInitZeros(out_xrot,ndata,dim); /* move down */ p_theta_new[d] = p_theta[d] - alpha; rotate_givens(mat,theta_new,ik,jk,angle_num,ndata,dim,out_xrot); Q_down = evqual(out_xrot,dim,ndata); MatrixInitZeros(out_xrot,ndata,dim); /* update only if at least one of them is better */ if( Q_up > Q || Q_down > Q) { if( Q_up > Q_down ) { p_theta[d] = p_theta[d] + alpha; p_theta_new[d] = p_theta[d]; Q = Q_up; } else { p_theta[d] = p_theta[d] - alpha; p_theta_new[d] = p_theta[d]; Q = Q_down; } } } else { /* descend through true derivative */ alpha = 1.0; dQ = evqualitygrad(mat,theta,ik,jk,angle_num,d,dim,ndata); //cout<<"the dQ is \t "<<dQ<<endl; p_theta_new[d] = p_theta[d] - alpha * dQ; rotate_givens(mat,theta_new,ik,jk,angle_num,ndata,dim,out_xrot); Q_new = evqual(out_xrot,dim,ndata); if( Q_new > Q) { p_theta[d] = p_theta_new[d]; Q = Q_new; } else { p_theta_new[d] = p_theta[d]; } MatrixInitZeros(out_xrot,dim,ndata); } } /* stopping criteria */ if( iter > 2 ) { if( Q - Q_old2 < 1e-3 ) { break; } } Q_old2 = Q_old1; Q_old1 = Q; } rotate_givens(mat,theta_new,ik,jk,angle_num,ndata,dim,out_xrot); cluster_assign(out_xrot,out_clusts,dim,ndata); /* free allocated memory */ delete [] theta; delete [] theta_new; delete [] ik; delete [] jk; return Q; };