Пример #1
0
// Standard CG method starting from zero vector
// (because we solve for the increment)
// x... comes as right-hand side, leaves as solution
bool CommonSolverCG::_solve(Matrix* A, double *x, double tol, int maxiter)
{
    printf("CG solver\n");

    int n_dof = A->get_size();
    double *r = new double[n_dof];
    double *p = new double[n_dof];
    double *help_vec = new double[n_dof];
    if (r == NULL || p == NULL || help_vec == NULL) {
        _error("a vector could not be allocated in solve_linear_system_iter().");
    }
    // r = b - A*x0  (where b is x and x0 = 0)
    for (int i=0; i < n_dof; i++) r[i] = x[i];
    // p = r
    for (int i=0; i < n_dof; i++) p[i] = r[i];

    // setting initial condition x = 0
    for (int i=0; i < n_dof; i++) x[i] = 0;

    // CG iteration
    int iter_current = 0;
    double tol_current;
    while (1)
    {
        mat_dot(A, p, help_vec, n_dof);
        double r_times_r = vec_dot(r, r, n_dof);
        double alpha = r_times_r / vec_dot(p, help_vec, n_dof);
        for (int i=0; i < n_dof; i++) {
            x[i] += alpha*p[i];
            r[i] -= alpha*help_vec[i];
        }
        double r_times_r_new = vec_dot(r, r, n_dof);
        iter_current++;
        tol_current = sqrt(r_times_r_new);
        if (tol_current < tol
            || iter_current >= maxiter) break;
        double beta = r_times_r_new/r_times_r;
        for (int i=0; i < n_dof; i++) p[i] = r[i] + beta*p[i];
    }
    bool flag;
    if (tol_current <= tol)
        flag = true;
    else
        flag = false;

    if (r != NULL) delete [] r;
    if (p != NULL) delete [] p;
    if (help_vec != NULL) delete [] help_vec;

    printf("CG solver: maxiter: %i, tol: %e\n",
           iter_current, tol_current);

    return flag;
}
      virtual Eigen::Matrix<double,6,6> get_xyz_vel()
      {
	Eigen::Matrix3d mat = get();
	Eigen::Matrix3d mat_dot = get_dot();
	Eigen::Matrix<double,6,6> retval;
	
	for (register int i = 0; i < 3; ++i) {
	  for (register int j = 0; j < 3; ++j) {
	    retval(i,j) = mat(i,j);
	    retval(i,j+3) = 0;
	    retval(i+3,j) = mat_dot(i,j);
	    retval(i+3,j+3) = mat(i,j);
	  }
	}
	return retval;
      }
void cvx_clustering ( double ** dist_mat, int fw_max_iter, int max_iter, int D, int N, double* lambda, double ** W) {
    // parameters
    double alpha = 0.1;
    double rho = 1;
    // iterative optimization
    double error = INF;
    double ** wone = mat_init (N, N);
    double ** wtwo = mat_init (N, N);
    double ** yone = mat_init (N, N);
    double ** ytwo = mat_init (N, N);
    double ** z = mat_init (N, N);
    double ** diffzero = mat_init (N, N);
    double ** diffone = mat_init (N, N);
    double ** difftwo = mat_init (N, N);
    mat_zeros (yone, N, N);
    mat_zeros (ytwo, N, N);
    mat_zeros (z, N, N);
    mat_zeros (diffzero, N, N);
    mat_zeros (diffone, N, N);
    mat_zeros (difftwo, N, N);

    int iter = 0; // Ian: usually we count up (instead of count down)
    while ( iter < max_iter ) { // stopping criteria

#ifdef SPARSE_CLUSTERING_DUMP
        cout << "it is place 0 iteration #" << iter << ", going to get into frank_wolfe"  << endl;
#endif
        // mat_set (wone, z, N, N);
        // mat_set (wtwo, z, N, N);
        // mat_zeros (wone, N, N);
        // mat_zeros (wtwo, N, N);
        // STEP ONE: resolve w_1 and w_2
        frank_wolf (dist_mat, yone, z, wone, rho, N, fw_max_iter); // for w_1
#ifdef SPARSE_CLUSTERING_DUMP
        cout << "norm2(w_1) = " << mat_norm2 (wone, N, N) << endl;
#endif

        blockwise_closed_form (ytwo, z, wtwo, rho, lambda, N);  // for w_2
#ifdef SPARSE_CLUSTERING_DUMP
        cout << "norm2(w_2) = " << mat_norm2 (wtwo, N, N) << endl;
#endif

        // STEP TWO: update z by averaging w_1 and w_2
        mat_add (wone, wtwo, z, N, N);
        mat_dot (0.5, z, z, N, N);
#ifdef SPARSE_CLUSTERING_DUMP
        cout << "norm2(z) = " << mat_norm2 (z, N, N) << endl;
#endif

        // STEP THREE: update the y_1 and y_2 by w_1, w_2 and z

        mat_sub (wone, z, diffone, N, N);
        double trace_wone_minus_z = mat_norm2 (diffone, N, N);
        mat_dot (alpha, diffone, diffone, N, N);
        mat_add (yone, diffone, yone, N, N);

        mat_sub (wtwo, z, difftwo, N, N);
        //double trace_wtwo_minus_z = mat_norm2 (difftwo, N, N);
        mat_dot (alpha, difftwo, difftwo, N, N);
        mat_add (ytwo, difftwo, ytwo, N, N);

        // STEP FOUR: trace the objective function
        if (iter % 100 == 0) {
            error = overall_objective (dist_mat, lambda, N, z);
            // get current number of employed centroid
#ifdef NCENTROID_DUMP
            int nCentroids = get_nCentroids (z, N, N);
#endif
            cout << "[Overall] iter = " << iter
                 << ", Overall Error: " << error
#ifdef NCENTROID_DUMP
                 << ", nCentroids: " << nCentroids
#endif
                 << endl;
        }
        iter ++;
    }

    // STEP FIVE: memory recollection
    mat_free (wone, N, N);
    mat_free (wtwo, N, N);
    mat_free (yone, N, N);
    mat_free (ytwo, N, N);
    mat_free (diffone, N, N);
    mat_free (difftwo, N, N);
    // STEP SIX: put converged solution to destination W
    mat_copy (z, W, N, N);
}
void blockwise_closed_form (double ** ytwo, double ** ztwo, double ** wtwo, double rho, double* lambda, int N) {

    // STEP ONE: compute the optimal solution for truncated problem
    double ** wbar = mat_init (N, N);
    mat_zeros (wbar, N, N);
    mat_dot (rho, ztwo, wbar, N, N); // wbar = rho * z_2
    mat_sub (wbar, ytwo, wbar, N, N); // wbar = rho * z_2 - y_2
    mat_dot (1.0/rho, wbar, wbar, N, N); // wbar = (rho * z_2 - y_2) / rho

    // STEP TWO: find the closed-form solution for second subproblem
    for (int j = 0; j < N; j ++) {
        // 1. bifurcate the set of values
        vector< pair<int,double> > alpha_vec;
        for (int i = 0; i < N; i ++) {
            double value = wbar[i][j];
            /*if( wbar[i][j] < 0 ){
              cerr << "wbar[" << i << "][" << j << "]" << endl;
              exit(0);
              }*/
            alpha_vec.push_back (make_pair(i, abs(value)));
        }
        // 2. sorting
        std::sort (alpha_vec.begin(), alpha_vec.end(), pairComparator);
        /*
           for (int i = 0; i < N; i ++) {
           if (alpha_vec[i].second != 0)
           cout << alpha_vec[i].second << endl;
           }
           */
        // 3. find mstar
        int mstar = 0; // number of elements support the sky
        double separator;
        double max_term = -INF, new_term;
        double sum_alpha = 0.0;
        for (int i = 0; i < N; i ++) {
            sum_alpha += alpha_vec[i].second;
            new_term = (sum_alpha - lambda[j]) / (i + 1.0);
            if ( new_term > max_term ) {
                separator = alpha_vec[i].second;
                max_term = new_term;
                mstar = i;
            }
        }
        // 4. assign closed-form solution to wtwo
        if( max_term < 0 ) {
            for(int i=0; i<N; i++)
                wtwo[i][j] = 0.0;
            continue;
        }
        for (int i = 0; i < N; i ++) {
            // harness vector of pair
            double value = wbar[i][j];
            if ( abs(value) >= separator ) {
                wtwo[i][j] = max_term;
            } else {
                // its ranking is above m*, directly inherit the wbar
                wtwo[i][j] = max(wbar[i][j],0.0);
            }
        }
    }
    // compute value of objective function
    double penalty = second_subproblem_obj (ytwo, ztwo, wtwo, rho, N, lambda);
    // report the #iter and objective function
    /*cout << "[Blockwise] second_subproblem_obj: " << penalty << endl;
      cout << endl;*/

    // STEP THREE: recollect temporary variable - wbar
    mat_free (wbar, N, N);
}