// 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); }
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); }
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>()) ); } }
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; }
/* * 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; }
/*----------------------------------------------------------------------------*/ 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; } }