void fill_row_q(int imin, int imax, int q, std::vector< std::vector<ldouble> > & S, std::vector< std::vector<size_t> > & J, const std::vector<ldouble> & sum_x, const std::vector<ldouble> & sum_x_sq, const std::vector<ldouble> & sum_w, const std::vector<ldouble> & sum_w_sq, const enum DISSIMILARITY criterion) { // Assumption: each cluster must have at least one point. for(int i=imin; i<=imax; ++i) { S[q][i] = S[q-1][i-1]; J[q][i] = i; int jmin = std::max(q, (int)J[q-1][i]); for(int j=i-1; j>=jmin; --j) { ldouble Sj(S[q-1][j-1] + dissimilarity(criterion, j, i, sum_x, sum_x_sq, sum_w, sum_w_sq) // ssq(j, i, sum_x, sum_x_sq, sum_w) ); if(Sj < S[q][i]) { S[q][i] = Sj; J[q][i] = j; } } } }
/* * find the location of queen q */ void solve_queen_at(int q, int* i, int* j) { if(q < 0 || q >= SOLVE_NQUEENS || !queen_on(q)) *i = *j = -1; else { *i = Si(q); *j = Sj(q); } }
/* * set the board to either add or remove queen q */ static int sr_queen(int q, int inc) { int i, j; int qi = Si(q); int qj = Sj(q); if(!queen_on(q)) return -1; // spot board[qi][qj] += inc; // row for(j = 0; j < SOLVE_SIZE; ++j) if(j != qj) board[qi][j] += inc; // col for(i = 0; i < SOLVE_SIZE; ++i) if(i != qi) board[i][qj] += inc; // diag - right & down for(i = qi + 1, j = qj + 1; i < SOLVE_SIZE && j < SOLVE_SIZE; ++i, ++j) board[i][j] += inc; // diag - right & up for(i = qi - 1, j = qj + 1; i >= 0 && j < SOLVE_SIZE; --i, ++j) board[i][j] += inc; // diag - left & down for(i = qi + 1, j = qj - 1; i < SOLVE_SIZE && j >= 0; ++i, --j) board[i][j] += inc; // diag - left & up for(i = qi - 1, j = qj - 1; i >= 0 && j >= 0; --i, --j) board[i][j] += inc; return 0; }
BasicMesh MeshTransferer::transfer(const vector<PhGUtils::Matrix3x3d> &S1grad) { if( !(S0set && T0set) ) { throw "S0 or T0 not set."; } auto &S = S1grad; auto &T = T0grad; int nfaces = S0.faces.nrow; int nverts = S0.verts.nrow; // assemble sparse matrix A int nrowsA = nfaces * 3; int nsv = stationary_vertices.size(); int nrowsC = nsv; int nrows = nrowsA + nrowsC; int ncols = nverts; int ntermsA = nfaces*9; int ntermsC = stationary_vertices.size(); int nterms = ntermsA + ntermsC; SparseMatrix A(nrows, ncols, nterms); // fill in the deformation gradient part for(int i=0, ioffset=0;i<nfaces;++i) { /* * Ai: * 1 2 3 4 5 ... nfaces*3 * 1 2 3 4 5 ... nfaces*3 * 1 2 3 4 5 ... nfaces*3 * Ai = reshape(Ai, 1, nfaces*9) * * Aj = reshape(repmat(S0.faces', 3, 1), 1, nfaces*9) * Av = reshape(cell2mat(T)', 1, nfaces*9) */ int *f = S0.faces.rowptr(i); auto Ti = T[i]; A.append(ioffset, f[0], Ti(0)); A.append(ioffset, f[1], Ti(1)); A.append(ioffset, f[2], Ti(2)); ++ioffset; A.append(ioffset, f[0], Ti(3)); A.append(ioffset, f[1], Ti(4)); A.append(ioffset, f[2], Ti(5)); ++ioffset; A.append(ioffset, f[0], Ti(6)); A.append(ioffset, f[1], Ti(7)); A.append(ioffset, f[2], Ti(8)); ++ioffset; } // fill in the lower part of A, stationary vertices part for(int i=0;i<nsv;++i) { A.append(nrowsA+i, stationary_vertices[i], 1); } ofstream fA("A.txt"); fA<<A; fA.close(); // fill in c matrix DenseMatrix c(nrows, 3); for(int i=0;i<3;++i) { for(int j=0, joffset=0;j<nfaces;++j) { auto &Sj = S[j]; c(joffset, i) = Sj(0, i); ++joffset; c(joffset, i) = Sj(1, i); ++joffset; c(joffset, i) = Sj(2, i); ++joffset; } } for(int i=0;i<3;++i) { for(int j=0, joffset=nrowsA;j<nsv;++j,++joffset) { auto vj = T0.verts.rowptr(stationary_vertices[j]); c(joffset, i) = vj[i]; } } cholmod_sparse *G = A.to_sparse(); cholmod_sparse *Gt = cholmod_transpose(G, 2, global::cm); // compute GtD // just multiply Dsi to corresponding elemenets double *Gtx = (double*)Gt->x; const int* Gtp = (const int*)(Gt->p); for(int i=0;i<nrowsA;++i) { int fidx = i/3; for(int j=Gtp[i];j<Gtp[i+1];++j) { Gtx[j] *= Ds(fidx); } } // compute GtDG cholmod_sparse *GtDG = cholmod_ssmult(Gt, G, 0, 1, 1, global::cm); GtDG->stype = 1; // compute GtD * c cholmod_dense *GtDc = cholmod_allocate_dense(ncols, 3, ncols, CHOLMOD_REAL, global::cm); double alpha[2] = {1, 0}; double beta[2] = {0, 0}; cholmod_sdmult(Gt, 0, alpha, beta, c.to_dense(), GtDc, global::cm); // solve for GtDG \ GtDc cholmod_factor *L = cholmod_analyze(GtDG, global::cm); cholmod_factorize(GtDG, L, global::cm); cholmod_dense *x = cholmod_solve(CHOLMOD_A, L, GtDc, global::cm); // make a copy of T0 BasicMesh Td = T0; // change the vertices with x double *Vx = (double*)x->x; for(int i=0;i<nverts;++i) { Td.verts(i, 0) = Vx[i]; Td.verts(i, 1) = Vx[i+nverts]; Td.verts(i, 2) = Vx[i+nverts*2]; } // release memory cholmod_free_sparse(&G, global::cm); cholmod_free_sparse(&Gt, global::cm); cholmod_free_sparse(&GtDG, global::cm); cholmod_free_dense(&GtDc, global::cm); cholmod_free_factor(&L, global::cm); cholmod_free_dense(&x, global::cm); return Td; }
/* * make the next solve move */ int solve_next_move() { int moved = 0; int on; // done - found solution if(queen == SOLVE_NQUEENS) { sprintf(move_buff[(move_count++)%MOVE_WRAP], "Complete!!!"); return 1; } // done - did not find solution if(queen < 0) { sprintf(move_buff[(move_count++)%MOVE_WRAP], "Failed."); return -1; } // should only run once or twice while(!moved) { on = queen_on(queen); moved = 1; // from last time if(on) { remove_queen(queen); } // add to board else { stack[queen].di = rand()%SOLVE_SIZE; stack[queen].dj = rand()%SOLVE_SIZE; stack[queen].i = 0; } // find open spot do { // increment position ++stack[queen].j; if(stack[queen].j == SOLVE_SIZE){ stack[queen].j = 0; ++stack[queen].i; // exhausted - backtrack if(stack[queen].i == SOLVE_SIZE) { stack[queen].i = stack[queen].j = -1; --queen; if(on){ mn = 0; sprintf(move_buff[(move_count++)%MOVE_WRAP], "...Exhausted spaces for Queen %d.", queen+2); return 0; } mn = 1; sprintf(move_buff[(move_count++)%MOVE_WRAP], "...No place for Queen %d.", queen+2); moved = 0; break; } } } while(!solve_spot_open(Si(queen), Sj(queen))); } mn = 0; sprintf(move_buff[(move_count++)%MOVE_WRAP], "Move Queen %d to %c%d.", queen+1, Si(queen)+'A', Sj(queen)+1); // place queen set_queen(queen); // get next queen ++queen; return 0; }