VectorXd lsq_weigh_nonneg(const MatrixXd& A, const VectorXd& b, const VectorXd& w) { const unsigned m = A.rows(); const unsigned n = A.cols(); if(b.size() != m || w.size() != m || n < 1 || m < 1) { std::cerr<<"#error in lsq_weigh_nonneg: If A is a m by n matrix, then b and w must have length m. We also want n >= 1 and m >= 1. A is "<< m <<" by "<< n <<", b has length "<< b.size() <<" and w has length "<< w.size() <<"."<<std::endl; throw std::invalid_argument("lsq_weigh_nonneg: dimension mismatch"); } // initialization const MatrixXd H = A.transpose() * w.asDiagonal() * A; const VectorXd f = - A.transpose() * w.asDiagonal() * b; VectorXd x = VectorXd::Zero(n), mu = f; // iterate double relerr; do { for(unsigned k = 0; k < n; ++k) { const double xtmp = x(k); x(k) -= mu(k) / H(k,k); if(x(k) < 0) x(k) = 0; const double d = x(k) - xtmp; if(d != 0) mu += d * H.col(k); } relerr = 0; for(unsigned k = 0; k < n; ++k) { if(x(k) != 0) { double err = mu(k) / x(k); if(err < 0) err = -err; if(err > relerr) relerr = err; } } } while(relerr >= 1e-2); // update non-zero columns with more costly, but also more precise calculation const VectorXi p = find(x.array() > 0); const VectorXd xp = lscov(pick_col(A, p), b, w); if(find(xp.array() >= 0).all()) set_ind(x, p, xp); return x; }
int sim_ann_v1(int n, int k, int* object, int old_k, int* old_object, int num_iterations, double initial_temp, double cool_rate) { int h = n*n; // copy of the best found object int* best_object = malloc(sizeof(int)*h*(k)); int min_found_cost=0; // evaluate the existing object int total = (k)*(k-1)/2; int* cv = malloc(sizeof(int)*total*h); int* missing = malloc(sizeof(int)*(k+old_k)); // addition: cost vector with old_object int* old_cv; if (old_k > 0) { old_cv = malloc(sizeof(int)*old_k*k*h); // addition: initialize the old_cv, and adjust num_missing old_cost_vector(n, k, object, old_k, old_object, old_cv); } cost_vector(n, k, object, cv); num_missing(n, k, cv, old_k, old_cv, missing); copy_array(h*(k), object, best_object); for(int c=0; c<k+old_k; c++) min_found_cost += missing[c]; min_found_cost = min_found_cost/2; // printf("missing: "); // print_int_matrix(missing, 1, k, stdout); // printf("min found cost=%d \n", min_found_cost); // printf("old cv: \n"); // print_int_matrix(old_cv, h, k*old_k, stdout); // printf("cv: \n"); // print_int_matrix(cv, h, total, stdout); int min_cost; int max_cost; int col, row11, row12, row21, row22, row1, row2; int total_cost1, total_cost2, total_cost; int swap; int curr_cost = min_found_cost; double current_temp = initial_temp; int good; // build index matrix int* idx_mat = malloc(sizeof(int)*(k)*(k)); int count = 0; for(int c1=0; c1<k; c1++) { idx_mat[c1*(k)+c1] = -1; for(int c2=c1+1; c2<k; c2++) { idx_mat[c1*(k)+c2] = count; idx_mat[c2*(k)+c1] = count; count ++; } } long unsigned iter=0; while(iter<num_iterations && min_found_cost>0) //(curr_cost > 0) { // evaluate the current object and find min and max costs min_cost = h*(k+old_k); max_cost = 0; for(int c=0; c<k; c++) { if(min_cost>missing[old_k+c]) min_cost=missing[old_k+c]; if(max_cost<missing[old_k+c]) max_cost=missing[old_k+c]; } // pick a random (with priority) column col = pick_col(old_k, k, missing, min_cost, max_cost); row11 = rand()%h; row12 = row11; while(row12 == row11) row12 = rand()%h; row21 = rand()%h; row22 = row21; while(row22 == row21) row22 = rand()%h; //printf("column = %d \n", col); //printf("first choice of rows: %d, %d \n", row11, row12); //printf("second choice of rows: %d, %d \n", row21, row22); total_cost1 = swap_cost(row11, row12, col, n, k, object, cv, idx_mat, old_k, old_object, old_cv); total_cost2 = swap_cost(row21, row22, col, n, k, object, cv, idx_mat, old_k, old_object, old_cv); //printf("total_cost1 = %d, total_cost2=%d \n", total_cost1, total_cost2); if(total_cost1<total_cost2) { total_cost = total_cost1; row1 = row11; row2 = row12; } else { total_cost = total_cost2; row1 = row21; row2 = row22; } good=0; if(total_cost <= 0) good=1; else if(acceptance_prob(total_cost, current_temp)> ( ((double)rand())/ ((double)RAND_MAX+1) )) { good=1; current_temp = current_temp*cool_rate; if(current_temp < 0.0001) current_temp=0.0001; } if(good==1) { // make changes to cv and missing make_adjustments(col, row1, row2, n,k, object, cv, old_k, old_object, old_cv, missing, idx_mat); // accept swap swap = object[col*h+row1]; object[row1+col*h] = object[row2+col*h]; object[row2+col*h] = swap; curr_cost += total_cost; if(min_found_cost>curr_cost) { min_found_cost=curr_cost; copy_array(h*(k), object, best_object); //printf("new_cost=%d \n", curr_cost); } //printf("total_cost = %d new cost = %d iter=%lu \n", total_cost, curr_cost, iter); //printf("current array: \n"); //print_int_matrix(object, h, k, stdout); //printf("cv: \n"); //print_int_matrix(cv, h, total, stdout); //printf("missing: "); //print_int_matrix(missing, 1, k+old_k, stdout); //printf("\n\n"); } iter++; //if(iter%1000==0) printf("iter=%lu \n", iter); } free(idx_mat); free(cv); if (old_k > 0) { free(old_cv); } free(missing); copy_array(h*(k), best_object, object); free(best_object); return min_found_cost; }