// tri-diagonalize a symmetric matrix.  The matrix will be destroyed and
// the diagonal will be returned in d and off diagonal in e.   It uses
// the Householder transformation
// WARNING: allocates space
void Matrix::tridiagonalize(double *&d, double *&e)
{
    d = new double [maxc];  // the diagonal elements
    e = new double [maxc];  // the off-diagonal elements

    householder(m, maxc, d, e);
}
예제 #2
0
void main()
{
    double sum,s,c,r;
	int i,j,k,n;        
    scanf("%d",&n);
    double w[MAX], v[MAX], q[MAX];
    double tridiagonal[MAX][MAX]; 
    tridiagonal[0][0]=1.0;
    for (i = 1;i<=n;i++)
        for (j=1;j<=n;j++)
            scanf("%lf",&tridiagonal[i][j]);
    for (k=1;k<=n-2;k++)
    {
		sum = 0;
		for (j = k+1; j <= n; j++) 
			sum += tridiagonal[j][k] * tridiagonal[j][k];
		s=sqrt(sum);
		if ( tridiagonal[k+1][k] < 0 ) 
			s=-s;
		r = sqrt( 2.0 * tridiagonal[k+1][k] * s + 2.0 * s * s );
		for (j = 1; j <= k; j++) 
			w[j] = 0.0;
		w[k+1] = ( tridiagonal[k+1][k] + s ) / r;
		for (j=k+2;j<=n;j++) 
			w[j] = tridiagonal[j][k] / r;
		for (i=1;i<=k;i++) 
			v[i] = 0.0;
		for (i = k+1; i <= n; i++) 
		{
			sum = 0.0;
			for (j = k+1; j <= n; j++) 
				sum += tridiagonal[i][j] * w[j];
			v[i] = sum;
		}            
		c = 0;
		for (j = k+1; j <= n; j++) 
			c += w[j] * v[j];
		for (j = 1; j <= k; j++)   
			q[j] = 0.0;
		for (j = k+1; j <= n; j++) 
			q[j] = v[j] - c * w[j];
		for (j=k+2;j<=n;j++) 
			tridiagonal[j][k] = tridiagonal[k][j] = 0.0;
		tridiagonal[k+1][k] = tridiagonal[k][k+1] = -s;
		for (j = k; j <= n; j++) 
			tridiagonal[j][j] -= 4.0 * q[j] * w[j];
		for (i = k+1; i <= n; i++) 
		{
			for (j = i+1; j <= n; j++) 
			{
				tridiagonal[i][j] = tridiagonal[i][j] - 2.0 * w[i] * q[j] - 2.0 * q[i] * w[j];
				tridiagonal[j][i] = tridiagonal[i][j];
			}
		}
    } 
   print(tridiagonal, n);
   householder(tridiagonal,n);
   eigen(tridiagonal,n);
}
예제 #3
0
void test_householder()
{
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1( householder(Matrix<double,2,2>()) );
    CALL_SUBTEST_2( householder(Matrix<float,2,3>()) );
    CALL_SUBTEST_3( householder(Matrix<double,3,5>()) );
    CALL_SUBTEST_4( householder(Matrix<float,4,4>()) );
    CALL_SUBTEST_5( householder(MatrixXd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE),internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
    CALL_SUBTEST_6( householder(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE),internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
    CALL_SUBTEST_7( householder(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE),internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
    CALL_SUBTEST_8( householder(Matrix<double,1,1>()) );
  }
}
예제 #4
0
void partlyKnownDifferencesInPhaseConstraints(int M, int K, cv::Mat& Q2)
{
  //constraints equation: PartlyKnownDifferencesInPhase
  cv::Mat ce = cv::Mat::eye(M, M, cv::DataType<double>::type);
  for(int i = 1; i < K-1; ++i)
  {
    cv::vconcat(ce, cv::Mat::eye(M, M, cv::DataType<double>::type), ce);
  }
  
  cv::hconcat(ce, -1 * cv::Mat::eye((K-1)*M, (K-1)*M, cv::DataType<double>::type), ce);
  ce.row(0) = cv::abs(ce.row(0));
  ce.row(1) = cv::abs(ce.row(1));
  ce.row(2) = cv::abs(ce.row(2));
  cv::Mat Q, R;
  householder(ce.t(), Q, R);
  // extracts A columns, 1 (inclusive) to 3 (exclusive).
  //Mat B = A(Range::all(), Range(1, 3));
  //Select last Np colums of Q to become the constraints null space
  int Np = (M*K) - ce.rows;
  Q2 = Q(cv::Range::all(), cv::Range(Q.cols - Np, Q.cols ));
}
matrix tridiagonalize(matrix A){
	/*
	Tridiagonalize a symmetric matrix using Householder transformations.
	Transformations are performed in place with Householder vectors and coefficients,
	rather than explicitly forming matrices and explicitly computing their products.

	Returns T = Q^t * A * Q

	Source: Golub and Van Loan, "Matrix Computations" p. 415

	Input:
	    Matrix A                  Matrix to tridiagonalize.

	  Output:
	    Matrix T (returned)       Tridiagonal matrix similar to input matrix.
	*/


	double *v = (double *) malloc(A.n * sizeof(double)) ;
	double *p = (double *) malloc(A.n * sizeof(double)) ;
	double *w = (double *) malloc(A.n * sizeof(double)) ;
 	double beta ;
 	double temp ;

 	double t1, t2;

 	int currentVectorLength = A.n - 1 ;
 	int n = A.n ;

 	int iVector, jVector;

	int i,j,k;
	for(k=0; k < n-2; k++){
		beta = householder(A, k+1, k, v) ;
		matrixVectorMultiply(A, k+1, k+1, v, beta, p) ;

		temp = - 0.5 * beta * innerProduct(p, v, currentVectorLength ) ;
		vectorPlusConstantByVector(w, p, temp, v, currentVectorLength ) ;

		temp = 0.0;
		for(j=k+1; j<n; j++){
			temp += A.values[j][k] * A.values[j][k] ;
		}
		temp = sqrt(temp) ;
		A.values[k+1][k] = temp ;
		A.values[k][k+1] = temp ;

		for(i=k+1, iVector=0; i<n; i++, iVector++){
			for(j=k+1, jVector=0; j<n; j++, jVector++){
				t1 = v[i]*w[j] ;
				t2 = v[j]*w[i] ;
				A.values[i][j] -= (v[iVector]*w[jVector] + v[jVector]*w[iVector]) ;
			}
		}

		currentVectorLength-- ;
	}

	// zero off diagonal multipliers
	for(i=0; i<n-1; i++){
		for(j=i+2; j<n; j++){
			A.values[i][j] = 0.0 ;
			A.values[j][i] = 0.0 ;
		}
	}

	free(v) ;
	free(p) ;
	free(w) ;

	return A;
}
예제 #6
0
/*
* the eigvalue, 有可能在数学上出问题(虚数) Error
*/
Matrix* calc_eig(Matrix* p)
{
	Matrix *oldAns = ans, *oldAns2;
	Matrix *temp = NULL,*temp2 = NULL;
	Matrix *v = NULL;
	double r1;
	int i, j, k = 0;
	if (p == NULL)
	{
		//Error
		return NULL;
	}
	if (p->m != p->n)
	{
		//Error
		return NULL;
	}
	if (!stor_createMatrix(&v, p->m, 1))
	{
		//Error
		return NULL;
	}
	if (!stor_createMatrix(&temp, p->m, p->n))
	{
		//Error
		return NULL;
	}
	if (!stor_createMatrix(&temp2, p->m, p->n))
	{
		//Error
		return NULL;
	}
	if (!stor_assign(temp, p))
	{
		//Error
		return NULL;
	}
	for (i = 0; i < p->n - 2; i++)
	{
		for (j = 0; j < p->m; j++)
		{
			*stor_entry(v, j, 0) = *stor_entry(temp, j, i);
		}
		if (!householder(v, i + 1))
		{
			//Error
			return NULL;
		}
		oldAns2 = ans;
		ans = NULL;
		if (!calc_mul(calc_mul(oldAns2, temp), oldAns2))  //H*A*H
		{
			//Error
			return NULL;
		}
		stor_freeMatrix(temp);
		temp = ans;
		ans = NULL;
		stor_freeMatrix(oldAns2);
	}
	//temp is 拟三角阵
	while (k<=500 && !isUpTrian(temp))//最多500次迭代
	{
		k++;
		ans = NULL;
		if (!(temp2 = calc_eye(p->n)))
		{
			//Error
			return NULL;
		}
		ans = NULL;
		for (i = 0; i < p->n - 1; i++)
		{
			if (!calc_eye(p->n))
			{
				//Error
				return NULL;
			}
			r1 = sqrt(*stor_entry(temp, i, i) * *stor_entry(temp, i, i)
				+ *stor_entry(temp, i + 1, i)* *stor_entry(temp, i + 1, i));
			if (util_isZero(r1))
			{
				//Error
				return NULL;
			}
			*stor_entry(ans, i, i) = *stor_entry(temp, i, i) / r1;
			*stor_entry(ans, i + 1, i + 1) = *stor_entry(temp, i, i) / r1;
			*stor_entry(ans, i + 1, i) = -*stor_entry(temp, i + 1, i) / r1;
			*stor_entry(ans, i, i + 1) = *stor_entry(temp, i + 1, i) / r1;
			oldAns2 = ans;
			ans = NULL;
			if (!calc_mul(temp2, calc_trans(oldAns2)))//Q
			{
				//Error
				return NULL;
			}
			stor_freeMatrix(temp2);
			temp2 = ans;
			ans = NULL;
			if (!calc_mul(oldAns2, temp))//R
			{
				//Error
				return NULL;
			}
			stor_freeMatrix(temp);
			temp = ans;
			ans = NULL;
			stor_freeMatrix(oldAns2);
		}
		if (!calc_mul(temp, temp2))
		{
			//Error
			return NULL;
		}
		stor_freeMatrix(temp);
		temp = ans;
	}
	//优化迭代, 好像可以证明RQ一定是拟上三角阵
	for (i = 0; i < p->m; i++)
	{
		for (j = 0; j < p->n; j++)
		{
			if (i != j) *stor_entry(ans, i, j) = 0;
		}
	}
	return ans;
}
예제 #7
0
/*----------------------------------------------------------------------------*/
void NOMAD::Directions::compute ( std::list<NOMAD::Direction> & dirs		,
                                 NOMAD::poll_type              poll			,
                                 const NOMAD::OrthogonalMesh  & mesh		)
{
    
    dirs.clear();
    
    // categorical variables: do nothing:
    if ( _is_categorical )
        return;
    
    // binary variables: we use special directions:
    if ( _is_binary )
    {
        compute_binary_directions ( dirs );
        return;
    }
    
    NOMAD::Double                               pow_gps , cst;
    const NOMAD::Direction                    * bl;
    NOMAD::Direction                          * pd;
    int                                         i , j , k , hat_i;
    std::list<NOMAD::Direction>::iterator it2 , end2;
    
    const NOMAD::Point mesh_indices=mesh.get_mesh_indices();
    int mesh_index=int(mesh_indices[0].value()); // single mesh_index used only for isotropic mesh
    
    
    /*-----------------------------------*/
    /*  loop on the types of directions  */
    /*-----------------------------------*/
    const std::set<NOMAD::direction_type> & dir_types =
    (poll == NOMAD::PRIMARY) ? _direction_types : _sec_poll_dir_types;
    
    std::set<NOMAD::direction_type>::const_iterator it , end = dir_types.end() ;
    for ( it = dir_types.begin() ; it != end ; ++it )
    {
        
        if ( *it == NOMAD::UNDEFINED_DIRECTION ||
            *it == NOMAD::NO_DIRECTION        ||
            *it == NOMAD::MODEL_SEARCH_DIR       )
            continue;
        
        /*--------------------------------------------------*/
        /*  Ortho-MADS                                      */
        /* ---> dirs are on a unit n-sphere by construction */
        /*--------------------------------------------------*/
        if ( NOMAD::dir_is_orthomads (*it) )
        {
            bool success_dir;
            
            
            NOMAD::Direction dir ( _nc , 0.0 , *it );
            NOMAD::Double    alpha_t_l;
            
            success_dir=compute_dir_on_unit_sphere ( dir );
            
            if ( success_dir )
            {
#ifdef DEBUG
                if ( dynamic_cast<const NOMAD::XMesh*> ( &mesh ) )
                {
                    _out << std::endl
                    << NOMAD::open_block ( "compute Ortho-MADS directions with XMesh" )
                    << "type              = " << *it << std::endl;
                    NOMAD::Point mesh_indices=mesh.get_mesh_indices();
                    _out<< "Mesh indices  = ( ";
                    mesh_indices.NOMAD::Point::display( _out, " " , -1 , -1 );
                    _out << " )" << std::endl;
                    _out<< "Unit sphere Direction  = ( ";
                    dir.NOMAD::Point::display ( _out , " " , -1 , -1 );
                    _out << " )" << std::endl << NOMAD::close_block();
                }
                else if ( dynamic_cast<const NOMAD::SMesh*> ( &mesh ) )
                {
                    _out << std::endl
                    << NOMAD::open_block ( "compute Ortho-MADS directions with SMesh" )
                    << "type              = " << *it
                    << " on isotropic mesh " << std::endl
                    << "mesh index   (lk) = " << mesh_index   << std::endl
                    << "alpha     (tk,lk) = " << alpha_t_l    << std::endl
                    << "Unit sphere Direction  = ( ";
                    dir.NOMAD::Point::display ( _out , " " , -1 , -1 );
                    _out << " )" << std::endl << NOMAD::close_block();
                    
                }
                
#endif
                // Ortho-MADS 2n and n+1:
                // ----------------------
                if ( *it == NOMAD::ORTHO_2N || *it == NOMAD::ORTHO_NP1_QUAD || *it == NOMAD::ORTHO_NP1_NEG )
                {
                    
                    // creation of the 2n directions:
                    // For ORTHO_NP1 the reduction from 2N to N+1 is done in MADS::POLL
                    NOMAD::Direction ** H = new NOMAD::Direction * [2*_nc];
                    
                    // Ordering D_k alternates Hk and -Hk instead of [H_k -H_k]
                    for ( i = 0 ; i < _nc ; ++i )
                    {
                        dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , *it ) );
                        H[i    ] = &(*(--dirs.end()));
                        dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , *it ) );
                        H[i+_nc] = &(*(--dirs.end()));
                    }
                    
                    // Householder transformations on the 2n directions on a unit n-sphere:
                    householder ( dir , true , H );
                    
                    
                    delete [] H;
                    
                    
                }
                
                // Ortho-MADS 1 or Ortho-MADS 2:
                // -----------------------------
                else
                {
                    dirs.push_back ( dir );
                    if ( *it == NOMAD::ORTHO_2 )
                        dirs.push_back ( -dir );
                }
            }
        }
        
        /*--------------------------------*/
        /*  LT-MADS                       */
        /* ---> dirs NOT on unit n-sphere */
        /*--------------------------------*/
        else if ( NOMAD::dir_is_ltmads (*it) )
        {
            
            if ( !_lt_initialized)
                lt_mads_init();
            
            bl = get_bl ( mesh , *it , hat_i );
            
            // LT-MADS 1 or LT-MADS 2: -b(l) and/or b(l):
            // ------------------------------------------
            if ( *it == NOMAD::LT_1 || *it == NOMAD::LT_2 )
            {
                dirs.push_back ( - *bl );
                if ( *it == NOMAD::LT_2 )
                    dirs.push_back ( *bl );
            }
            
            // LT-MADS 2n or LT-MADS n+1:
            // --------------------------
            else {
                
                // row permutation vector:
                int * row_permutation_vector  = new int [_nc];
                row_permutation_vector[hat_i] = hat_i;
                
                NOMAD::Random_Pickup rp ( _nc );
                
                for ( i = 0 ; i < _nc ; ++i )
                    if ( i != hat_i )
                    {
                        j = rp.pickup();
                        if ( j == hat_i )
                            j = rp.pickup();
                        row_permutation_vector[i] = j;
                    }
                
                rp.reset();
                
                for ( j = 0 ; j < _nc ; ++j )
                {
                    i = rp.pickup();
                    if ( i != hat_i )
                    {
                        
                        dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , *it ) );
                        pd = &(*(--dirs.end()));
                        
                        create_lt_direction ( mesh , *it , i , hat_i , pd );
                        permute_coords ( *pd , row_permutation_vector );
                    }
                    else
                        dirs.push_back ( *bl );
                    
                    // completion to maximal basis:
                    if ( *it == NOMAD::LT_2N )
                        dirs.push_back ( NOMAD::Direction ( - *(--dirs.end()) , NOMAD::LT_2N ) );
                    
                }
                
                delete [] row_permutation_vector;
                
                // completion to minimal basis:
                if ( *it == NOMAD::LT_NP1 )
                {
                    dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , NOMAD::LT_NP1 ) );
                    pd = &(*(--dirs.end()));
                    
                    end2 = --dirs.end();
                    for ( it2 = dirs.begin() ; it2 != end2 ; ++it2 )
                    {
                        for ( i = 0 ; i < _nc ; ++i )
                            (*pd)[i] -= (*it2)[i];
                    }
                }
            }
            
            
        }
        
        /*--------------------------------*/
        /*  GPS                           */
        /* ---> dirs NOT on unit n-sphere */
        /*--------------------------------*/
        else
        {
            
            // GPS for binary variables: should'nt be here:
            if ( *it == NOMAD::GPS_BINARY )
            {
#ifdef DEBUG
                _out << std::endl << "Warning (" << "Directions.cpp" << ", " << __LINE__
                << "): tried to generate binary directions at the wrong place)"
                << std::endl << std::endl;
#endif
                dirs.clear();
                return;
            }
            
            // this value represents the non-zero values in GPS directions
            // (it is tau^{|ell_k|/2}, and it is such that delta_k * pow_gps = Delta_k):
            if ( !pow_gps.is_defined() )
                pow_gps = pow ( mesh.get_update_basis() , abs(mesh_index) / 2.0 );
            
            // GPS 2n, static:
            // ---------------
            
            if ( *it == NOMAD::GPS_2N_STATIC )
            {
                for ( i = 0 ; i < _nc ; ++i )
                {
                    dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , NOMAD::GPS_2N_STATIC ) );
                    pd = &(*(--dirs.end()));
                    (*pd)[i] = pow_gps;
                    
                    dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , NOMAD::GPS_2N_STATIC ) );
                    pd = &(*(--dirs.end()));
                    (*pd)[i] = -pow_gps;
                }
            }
            
            // GPS 2n, random:
            // ---------------
            else if ( *it == NOMAD::GPS_2N_RAND )
            {
                
                int v , cnt;
                
                std::list  <int>::const_iterator end3;
                std::list  <int>::iterator       it3;
                std::list  <int> rem_cols;
                std::vector<int> rem_col_by_row ( _nc );
                
                // creation of the 2n directions:
                std::vector<NOMAD::Direction *> pdirs ( 2 * _nc );
                
                for ( i = 0 ; i < _nc ; ++i )
                {
                    
                    dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , NOMAD::GPS_2N_RAND ) );
                    pdirs[i] = &(*(--dirs.end()));
                    (*pdirs[i])[i] = pow_gps;
                    
                    dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , NOMAD::GPS_2N_RAND ) );
                    pdirs[i+_nc] = &(*(--dirs.end()));
                    (*pdirs[i+_nc])[i] = -pow_gps;
                    
                    rem_cols.push_back(i);
                    rem_col_by_row[i] = i;
                }
                
                // random perturbations:
                for ( i = 1 ; i < _nc ; ++i )
                {
                    if ( rem_col_by_row[i] > 0 )
                    {
                        v = NOMAD::RNG::rand()%3 - 1; // v in { -1 , 0 , 1 }
                        if ( v )
                        {
                            
                            // we decide a (i,j) couple:
                            k    = NOMAD::RNG::rand()%(rem_col_by_row[i]);
                            cnt  = 0;
                            end3 = rem_cols.end();
                            it3  = rem_cols.begin();
                            while ( cnt != k )
                            {
                                ++it3;
                                ++cnt;
                            }
                            j = *it3;
                            
                            // the perturbation:
                            (*pdirs[i])[j] = (*pdirs[j+_nc])[i] = -v * pow_gps;
                            (*pdirs[j])[i] = (*pdirs[i+_nc])[j] =  v * pow_gps;
                            
                            // updates:
                            rem_cols.erase(it3);
                            it3 = rem_cols.begin();
                            while ( *it3 != i )
                                ++it3;
                            rem_cols.erase(it3);
                            for ( k = i+1 ; k < _nc ; ++k )
                                rem_col_by_row[k] -= j<k ? 2 : 1;
                        }
                    }
                }
            }
            
            // GPS n+1, static:
            // ----------------
            else if ( *it == NOMAD::GPS_NP1_STATIC )
            {
                
                // (n+1)^st direction:
                dirs.push_back ( NOMAD::Direction ( _nc , -pow_gps , NOMAD::GPS_NP1_STATIC ) );
                
                // first n directions:
                for ( i = 0 ; i < _nc ; ++i )
                {
                    dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , NOMAD::GPS_NP1_STATIC ) );
                    pd = &(*(--dirs.end()));
                    (*pd)[i] = pow_gps;
                }
            }
            
            // GPS n+1, random:
            // ----------------
            else if ( *it == NOMAD::GPS_NP1_RAND )
            {
                
                // (n+1)^st direction:
                dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , NOMAD::GPS_NP1_RAND ) );
                NOMAD::Direction * pd1 = &(*(--dirs.end()));
                
                NOMAD::Double d;
                
                // first n directions:
                for ( i = 0 ; i < _nc ; ++i )
                {
                    dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , NOMAD::GPS_NP1_RAND ) );
                    pd = &(*(--dirs.end()));
                    
                    d = NOMAD::RNG::rand()%2 ? -pow_gps : pow_gps;
                    (*pd )[i] =  d;
                    (*pd1)[i] = -d;
                }
            }
            
            // GPS n+1, static, uniform angles:
            // --------------------------------
            else if ( *it == NOMAD::GPS_NP1_STATIC_UNIFORM )
            {
                
                cst = pow_gps * sqrt(static_cast<double>(_nc)*(_nc+1))/_nc;
                
                // n first directions:
                for ( j = _nc-1 ; j >= 0 ; --j )
                {
                    dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , NOMAD::GPS_NP1_STATIC_UNIFORM ) );
                    pd = &(*(--dirs.end()));
                    
                    k = _nc-j-1;
                    
                    for ( i = 0 ; i < k ; ++i )
                        (*pd)[i] = -cst / sqrt(static_cast<double>(_nc-i)*(_nc-i+1));
                    
                    (*pd)[k] = (cst * (j+1)) / sqrt(static_cast<double>(j+1)*(j+2));
                    
                }
                
                // (n+1)^st direction:
                dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , NOMAD::GPS_NP1_STATIC_UNIFORM ) );
                pd = &(*(--dirs.end()));
                for ( i = 0 ; i < _nc ; ++i )
                    (*pd)[i] = -cst / sqrt(static_cast<double>(_nc-i)*(_nc-i+1));
                
            }
            
            // GPS n+1, random, uniform angles:
            // --------------------------------
            // (we apply the procedure defined in
            // "Pattern Search Methods for user-provided points:
            // application to molecular geometry problems",
            // by Alberto, Nogueira, Rocha and Vicente,
            // SIOPT 14-4, 1216-1236, 2004, doi:10.1137/S1052623400377955)
            else if ( *it == NOMAD::GPS_NP1_RAND_UNIFORM )
            {
                
                cst = pow_gps * sqrt(static_cast<double>(_nc)*(_nc+1))/_nc;
                
                // n first directions:
                for ( j = _nc-1 ; j >= 0 ; --j )
                {
                    dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , NOMAD::GPS_NP1_STATIC_UNIFORM ) );
                    pd = &(*(--dirs.end()));
                    
                    k = _nc-j-1;
                    
                    for ( i = 0 ; i < k ; ++i )
                        (*pd)[i] = -cst / sqrt(static_cast<double>(_nc-i)*(_nc-i+1));
                    
                    (*pd)[k] = (cst * (j+1)) / sqrt(static_cast<double>(j+1)*(j+2));
                    
                }
                
                // (n+1)^st direction:
                dirs.push_back ( NOMAD::Direction ( _nc , 0.0 , NOMAD::GPS_NP1_STATIC_UNIFORM ) );
                pd = &(*(--dirs.end()));
                for ( i = 0 ; i < _nc ; ++i )
                    (*pd)[i] = -cst / sqrt(static_cast<double>(_nc-i)*(_nc-i+1));
                
                // random perturbations:
                NOMAD::Random_Pickup                  rp   ( _nc );
                std::vector<bool>                     done ( _nc );
                bool                                  chg_sgn;
                std::list<NOMAD::Direction>::iterator it;
                NOMAD::Double                         tmp;
                
                end2 = dirs.end();
                for ( i = 0 ; i < _nc ; ++i )
                    done[i] = false;
                
                for ( i = 0 ; i < _nc ; ++i )
                {
                    k = rp.pickup();
                    if ( i != k && !done[i] )
                    {
                        chg_sgn = ( NOMAD::RNG::rand()%2 != 0 );
                        
                        for ( it = dirs.begin() ; it != end2 ; ++it )
                        {
                            tmp      = (*it)[i];
                            (*it)[i] = ( chg_sgn ? -1.0 : 1.0 ) * (*it)[k];
                            (*it)[k] = tmp;
                        }
                        
                        done[i] = done[k] = true;
                    }
                    else
                        if ( NOMAD::RNG::rand()%2 )
                            for ( it = dirs.begin() ; it != end2 ; ++it )
                                (*it)[i] = -(*it)[i];
                }
            }
        }
    } // end of loop on the types of directions
    
    // The direction are unscaled on a unit n-sphere when necessary (that is directions that are not orthomads)
    for ( it2 = dirs.begin() ; it2 != dirs.end() ; ++it2 )
        if ( ! NOMAD::dir_is_orthomads ( it2->get_type() ) )
        {
            NOMAD::Double norm_dir=it2->norm();
            for (int i=0 ; i < _nc ; ++i )
                (*it2)[i] /= norm_dir;
        }
    
}