int main(int argc, char** argv) { srandom((argc <= 1)? time(NULL): atoi(argv[1])); #if 0 const std::vector< std::vector<int> > costs = { { 0, 0, 0, 0}, { 0, 2, 3, 3}, { 0, 3, 2, 3}, { 0, 3, 3, 2}, }; #else // const std::vector< std::vector<int> > costs = gen_cost_matrix<int>(6, 20); const std::vector< std::vector<int> > costs = { {0, 0, 0, 0, 0, 0}, {0, 15, 16, 17, 18, 19}, {0, 1, 1, 3, 1, 16}, {0, 2, 8, 8, 6, 17}, {0, 2, 2, 2, 8, 18}, {0, 4, 6, 7, 8, 19}, }; #endif const std::vector<size_t>& pairs_ehm = solve_ap_ehm(costs); const std::vector<size_t>& pairs_rec = solve_ap_rec(costs); printf("[%s] cost=%d (%d)\n", __FUNCTION__, calc_cost(costs, pairs_ehm), calc_cost(costs, pairs_rec)); return 0; }
/*========================================== * 必要ならpathを追加/修正する *------------------------------------------ */ static int add_path(int *heap,struct tmp_path *tp,int x,int y,int dist,int dir,int before,int x1,int y1) { int i; i=calc_index(x,y); if(tp[i].x==x && tp[i].y==y){ if(tp[i].dist>dist){ tp[i].dist=dist; tp[i].dir=dir; tp[i].before=before; tp[i].cost=calc_cost(&tp[i],x1,y1); if(tp[i].flag) push_heap_path(heap,tp,i); else update_heap_path(heap,tp,i); tp[i].flag=0; } return 0; } if(tp[i].x || tp[i].y) return 1; tp[i].x=x; tp[i].y=y; tp[i].dist=dist; tp[i].dir=dir; tp[i].before=before; tp[i].cost=calc_cost(&tp[i],x1,y1); tp[i].flag=0; push_heap_path(heap,tp,i); return 0; }
int ast_register_translator(struct ast_translator *t) { char tmp[80]; t->srcfmt = powerof(t->srcfmt); t->dstfmt = powerof(t->dstfmt); if (t->srcfmt >= MAX_FORMAT) { ast_log(LOG_WARNING, "Source format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt)); return -1; } if (t->dstfmt >= MAX_FORMAT) { ast_log(LOG_WARNING, "Destination format %s is larger than MAX_FORMAT\n", ast_getformatname(t->dstfmt)); return -1; } calc_cost(t,1); if (option_verbose > 1) ast_verbose(VERBOSE_PREFIX_2 "Registered translator '%s' from format %s to %s, cost %d\n", term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt), t->cost); ast_mutex_lock(&list_lock); if (!added_cli) { ast_cli_register(&show_trans); added_cli++; } t->next = list; list = t; rebuild_matrix(0); ast_mutex_unlock(&list_lock); return 0; }
int init_cost(int edge[][SIZE+1]) { int i=0; for (i=1; i<=N; i++) population[i]->cost = calc_cost(population[i], edge); return 1; }
int local_optimization(int n, int edge[][SIZE+1]) { int i, j, k; int improved = 1; int modify = 0; int cost = (offsprings[n]->cost = calc_cost(offsprings[n], edge)); int permutation[SIZE+1]; Chromosome *c; init_chromosome(&c); for (i=0; i<=SIZE; i++) c->ch[i] = offsprings[n]->ch[i]; int num = 0; init_permutation(permutation); while (improved) { improved = 0; for (i=1; i<=SIZE; i++) { int tmp = 0; c->ch[permutation[i]] = (1 - c->ch[permutation[i]]) % 2; tmp = calc_cost(c, edge); if (tmp > cost) { offsprings[n]->ch[permutation[i]] = c->ch[permutation[i]]; improved = 1; cost = tmp; offsprings[n]->cost = tmp; } else c->ch[permutation[i]] = (1 - c->ch[permutation[i]]) % 2; } } free_chromosome(c); return 1; }
v3s16 pathfinder::get_dir_heuristic(std::vector<v3s16>& directions,path_gridnode& g_pos) { int minscore = -1; v3s16 retdir = v3s16(0,0,0); v3s16 srcpos = g_pos.pos; DEBUG_OUT("Pathfinder: remaining dirs at beginning:" << directions.size() << std::endl); for (std::vector<v3s16>::iterator iter = directions.begin(); iter != directions.end(); ++iter) { v3s16 pos1 = v3s16(srcpos.X + iter->X,0,srcpos.Z+iter->Z); int cur_manhattan = get_manhattandistance(pos1); path_cost cost = g_pos.get_cost(*iter); if (!cost.updated) { cost = calc_cost(g_pos.pos,*iter); g_pos.set_cost(*iter,cost); } if (cost.valid) { int score = cost.value + cur_manhattan; if ((minscore < 0)|| (score < minscore)) { minscore = score; retdir = *iter; } } } if (retdir != v3s16(0,0,0)) { for (std::vector<v3s16>::iterator iter = directions.begin(); iter != directions.end(); ++iter) { if(*iter == retdir) { DEBUG_OUT("Pathfinder: removing return direction" << std::endl); directions.erase(iter); break; } } } else { DEBUG_OUT("Pathfinder: didn't find any valid direction clearing" << std::endl); directions.clear(); } DEBUG_OUT("Pathfinder: remaining dirs at end:" << directions.size() << std::endl); return retdir; }
/*! \brief Use the list of translators to build a translation matrix */ static void rebuild_matrix(int samples) { struct ast_translator *t; int changed; int x,y,z; if (option_debug) ast_log(LOG_DEBUG, "Resetting translation matrix\n"); memset(tr_matrix, 0, sizeof(tr_matrix)); t = list; while(t) { if(samples) calc_cost(t, samples); if (!tr_matrix[t->srcfmt][t->dstfmt].step || tr_matrix[t->srcfmt][t->dstfmt].cost > t->cost) { tr_matrix[t->srcfmt][t->dstfmt].step = t; tr_matrix[t->srcfmt][t->dstfmt].cost = t->cost; } t = t->next; } do { changed = 0; /* Don't you just love O(N^3) operations? */ for (x=0; x< MAX_FORMAT; x++) /* For each source format */ for (y=0; y < MAX_FORMAT; y++) /* And each destination format */ if (x != y) /* Except ourselves, of course */ for (z=0; z < MAX_FORMAT; z++) /* And each format it might convert to */ if ((x!=z) && (y!=z)) /* Don't ever convert back to us */ if (tr_matrix[x][y].step && /* We can convert from x to y */ tr_matrix[y][z].step && /* And from y to z and... */ (!tr_matrix[x][z].step || /* Either there isn't an x->z conversion */ (tr_matrix[x][y].cost + tr_matrix[y][z].cost < /* Or we're cheaper than the existing */ tr_matrix[x][z].cost) /* solution */ )) { /* We can get from x to z via y with a cost that is the sum of the transition from x to y and from y to z */ tr_matrix[x][z].step = tr_matrix[x][y].step; tr_matrix[x][z].cost = tr_matrix[x][y].cost + tr_matrix[y][z].cost; if (option_debug) ast_log(LOG_DEBUG, "Discovered %d cost path from %s to %s, via %d\n", tr_matrix[x][z].cost, ast_getformatname(x), ast_getformatname(z), y); changed++; } } while (changed); }
//---------------------------gen_match----------------------------------------- void ArchDesc::gen_match(FILE *fp, MatchList &mList, ProductionState &status, Dict &operands_chained_from) { const char *spaces4 = " "; const char *spaces6 = " "; fprintf(fp, "%s", spaces4); // Only generate child tests if this is not a leaf node bool has_child_constraints = mList._lchild || mList._rchild; const char *predicate_test = mList.get_pred(); if( has_child_constraints || predicate_test ) { // Open the child-and-predicate-test braces fprintf(fp, "if( "); status.set_constraint(hasConstraint); child_test(fp, mList); // Only generate predicate test if one exists for this match if( predicate_test ) { if( has_child_constraints ) { fprintf(fp," &&\n"); } fprintf(fp, "%s %s", spaces6, predicate_test); } // End of outer tests fprintf(fp," ) "); } else { // No child or predicate test needed status.set_constraint(noConstraint); } // End of outer tests fprintf(fp,"{\n"); // Calculate cost of this match const Expr *cost = calc_cost(fp, spaces6, mList, status); // Check against other match costs, and update cost & rule vectors cost_check(fp, spaces6, ArchDesc::getMachOperEnum(mList._resultStr), cost, mList._opcode, status); // If this is a member of an operand class, update the class cost & rule expand_opclass( fp, spaces6, cost, mList._resultStr, status); // Check if this rule should be used to generate the chains as well. const char *rule = /* set rule to "Invalid" for internal operands */ strcmp(mList._opcode,mList._resultStr) ? mList._opcode : "Invalid"; // If this rule produces an operand which has associated chain rules, // update the operands with the chain rule + this rule cost & this rule. chain_rule(fp, spaces6, mList._resultStr, cost, rule, operands_chained_from, status); // Close the child-and-predicate-test braces fprintf(fp, " }\n"); }
int find_ans(){ int dx,dy,cx,cy,i; /* enum each point to be destinaon */ for(dx=0;dx<C;dx++)for(dy=0;dy<R;dy++){ int mi = d_king[dx][dy];/* the king's minimal cost to get to destination */ /* enum each point that king get touch with knight */ for(cx=0;cx<C;cx++)for(cy=0;cy<R;cy++)if( d_king[cx][cy] < mi ){ for(i=0;i<n_knight;i++){/* which knight to get touch with */ int cost = calc_cost(dx,dy,cx,cy,i); if(cost<mi)mi=cost; } } if( (d_all[dx][dy] + mi) < mi_s ) mi_s = d_all[dx][dy] + mi; } return 0; }
int replacement(int edge[][SIZE+1]) { int i=0, r=0; for (i=1; i<=K; i++) offsprings[i]->cost = calc_cost(offsprings[i], edge); for (i=1; i<=K; i++) { if ((offsprings[i]->p1 < r) || (population[offsprings[i]->p1]->cost > offsprings[i]->cost)) { r++; memcpy(population[r], offsprings[i], sizeof(Chromosome)); } else memcpy(population[offsprings[i]->p1], offsprings[i], sizeof(Chromosome)); } return 1; }
Results* join_clusters2_restart (double *x,//array/matrix of data SymNoDiag *W,//lower triangle of weight matrix unsigned int Px,//problem size double lambda,//starting point in regularization path double join_thresh, //tolerance for equality of points double opt_thresh, //tolerance for optimality double lambda_factor,//increase of lambda after optimality double smooth,//smoothing parameter int maxit, int linesearch_freq,//how often to do a linesearch? if 0, never. if //n>0, do n-1 linesearch steps for every //decreasing step size step. set this to 2 if //unsure. int linesearch_points,//how many points to check along the gradient //direction. set to 10 if unsure. int check_splits, int target_cluster, int verbose ){ unsigned int N = W->N; //W->print(); double old_lambda=0; std::vector<int> rows,rowsj; std::vector<int>::iterator rowit,ri,rj; std::list< std::vector<int> > clusters,tocheck; std::list< std::vector<int> >::iterator it,cj; unsigned int i,k,j; int tried_restart; for(i=0;i<N;i++){ rows.assign(1,i); clusters.push_back(rows); } double *old_alpha = new double[N*Px]; double *alpha = new double[N*Px]; double *xbar = new double[N*Px]; double *dir = new double[N*Px]; for(i=0;i<N*Px;i++){ alpha[i]=xbar[i]=x[i]; } Matrix amat(alpha,N,Px),xmat(x,N,Px); SymNoDiag diffs(N); diffs.calc_diffs(clusters,amat,nrm2); //store initial trivial solution Results *results = new Results(N,Px,opt_thresh); if(target_cluster==0)results->add(alpha,0,0); double weight,diff,step; while(clusters.size()>1){ double grad=opt_thresh; int iteration=1; tried_restart=0; //if we use the general (slower) algorithm for any weights, then //split the clusters to individual points if(check_splits){ clusters.clear(); //reassign original clusters for(i=0;i<N;i++){ rows.assign(1,i); clusters.push_back(rows); } //recopy original xbar for(i=0;i<N*Px;i++){ xbar[i]=x[i]; } } while(grad>=opt_thresh){ //first calc gradients grad = 0; for(it=clusters.begin();it!=clusters.end();it++){ rows = *it; i = rows[0]; for(k=0;k<Px;k++){ dir[i+k*N] = xbar[i+k*N] - alpha[i+k*N]; } for(cj=clusters.begin();cj!=clusters.end();cj++){ if(it!=cj){ rowsj = *cj; j=rowsj[0]; weight=0; diff = *diffs(i,j); if(diff!=0){ if(smooth!=0){ diff *= diff; //now squared l2 norm diff += smooth; //add smoothing parameter under sqrt diff = sqrt(diff);//put sqrt back } for(ri=rows.begin();ri!=rows.end();ri++){ for(rj=rowsj.begin();rj!=rowsj.end();rj++){ weight += W->getval(*ri,*rj); } } //weight *= lambda / diff / ((double)(N-1)) / ((double)rows.size()); weight *= lambda / diff / ((double)rows.size()); for(k=0;k<Px;k++){ dir[i+k*N] += weight * (alpha[j+k*N]-alpha[i+k*N]); } } } } grad += nrm2(Array(dir+i,N,Px)); } //store this iteration //results->add(alpha,lambda,grad); //then take a step if(linesearch_freq==0 || (iteration % linesearch_freq)==0 ){ //Decreasing step size //TDH and pierre 18 jan 2011 try sqrt dec step size step=1/((double)iteration); //step=1/sqrt((double)iteration); if(verbose>=2)printf("grad %f step %f it %d\n",grad,step,iteration); take_step(clusters,alpha,dir,N,Px,step); }else{ double cost_here,cost_step; std::map<double,double> cost_steps; std::map<double,double>::iterator step1,step2; for(i=0;i<N*Px;i++)old_alpha[i]=alpha[i];//copy alpha //compare current cost to cost after stepping in gradient direction cost_here=cost_step=calc_cost(clusters,amat,xmat,W,diffs,lambda); step = 0; cost_steps.insert(std::pair<double,double>(cost_here,0)); while(cost_step<=cost_here){ take_step(clusters,alpha,dir,N,Px,1); step += 1; diffs.calc_diffs(clusters,amat,nrm2); cost_step=calc_cost(clusters,amat,xmat,W,diffs,lambda); if(verbose>=2) printf("cost %.10f step %f cost_here %f\n",cost_step,step,cost_here); cost_steps.insert(std::pair<double,double>(cost_step,step)); } for(int cuts=0;cuts<linesearch_points;cuts++){ step1=step2=cost_steps.begin(); step2++; step = (step1->second + step2->second)/2; for(i=0;i<N*Px;i++){ alpha[i]=old_alpha[i]; } take_step(clusters,alpha,dir,N,Px,step); diffs.calc_diffs(clusters,amat,nrm2); cost_step=calc_cost(clusters,amat,xmat,W,diffs,lambda); if(verbose>=2)printf("cost %.10f step %f %d\n",cost_step,step,cuts); cost_steps.insert(std::pair<double,double>(cost_step,step)); } cost_steps.clear(); } if(iteration++ > maxit){ if(tried_restart){ printf("max iteration %d exit\n",maxit); delete old_alpha; delete alpha; delete xbar; delete dir; return results; }else{ if(verbose>=1)printf("max iterations, trying restart from x\n"); tried_restart=1; iteration=1; for(i=0;i<N*Px;i++)alpha[i]=x[i]; } } //calculate differences diffs.calc_diffs(clusters,amat,nrm2); //check for joins JoinPair tojoin; while(dojoin(tojoin=check_clusters_thresh(&clusters,diffs,join_thresh))){ //if(verbose>=1) // printf("join: %d %d\n",tojoin.first->front(),tojoin.second->front()); int ni=tojoin.first->size(); int nj=tojoin.second->size(); i=tojoin.first->front(); j=tojoin.second->front(); tojoin.first->insert(tojoin.first->end(), tojoin.second->begin(), tojoin.second->end()); for(k=0;k<Px;k++){ alpha[i+k*N] = (alpha[i+k*N]*ni + alpha[j+k*N]*nj)/(ni+nj); xbar[i+k*N] = (xbar[i+k*N]*ni + xbar[j+k*N]*nj)/(ni+nj); } clusters.erase(tojoin.second); iteration=1; if(clusters.size()>1){ diffs.calc_diffs(clusters,amat,nrm2);//inefficient }else{ grad=0;//so we can escape from the last optimization loop } } }//while(grad>=opt_thresh) if(verbose>=1) printf("solution iteration %d lambda %f nclusters %d\n", iteration,lambda,(int)clusters.size()); if(target_cluster == 0){ //for each cluster, there may be several points. we store the //alpha value just in the row of the first point. thus here we //copy this value to the other rows before copying the optimal //alpha to results. for(it=clusters.begin();it!=clusters.end();it++){ rows = *it; if(rows.size()>1){ for(i=1;i<rows.size();i++){ for(k=0;k<Px;k++){ alpha[rows[i]+k*N] = alpha[rows[0]+k*N]; } } } } results->add(alpha,lambda,grad); } //haven't yet reached the target number of clusters, multiply //lambda by lambda_factor and continue along the path if((int)clusters.size()>target_cluster){ old_lambda=lambda; lambda *= lambda_factor; } //if we have passed the target cluster number then decrease //lambda and go look for it! if((int)clusters.size()<target_cluster){ if(verbose>=1){ printf("missed target %d, going back for it\n",target_cluster); } lambda = (lambda+old_lambda)/2; clusters.clear(); //reassign original clusters for(i=0;i<N;i++){ rows.assign(1,i); clusters.push_back(rows); } //recopy original xbar for(i=0;i<N*Px;i++){ xbar[i]=x[i]; } } //this is the number of clusters that we were looking for, //save and quit! if((int)clusters.size()==target_cluster){ for(it=clusters.begin();it!=clusters.end();it++){ rows = *it; if(rows.size()>1){ for(i=1;i<rows.size();i++){ for(k=0;k<Px;k++){ alpha[rows[i]+k*N] = alpha[rows[0]+k*N]; } } } } results->add(alpha,lambda,grad); if(verbose>=1)printf("got target cluster %d exit\n",target_cluster); delete old_alpha; delete alpha; delete xbar; delete dir; return results; } } //TODO: consolidate cleanup... just use data structures that //automatically clean themselves up when the function exits. delete old_alpha; delete alpha; delete xbar; delete dir; return results; }
/*========================================== * path search (x0,y0)->(x1,y1) * wpd: path info will be written here * flag: &1 = easy path search only * cell: type of obstruction to check for *------------------------------------------*/ bool path_search (struct walkpath_data *wpd, int m, int x0, int y0, int x1, int y1, int flag, cell_chk cell) { int heap[MAX_HEAP + 1]; struct tmp_path tp[MAX_WALKPATH * MAX_WALKPATH]; register int i, j, len, x, y, dx, dy; int rp, xs, ys; struct map_data *md; struct walkpath_data s_wpd; if (wpd == NULL) wpd = &s_wpd; // use dummy output variable if (!map[m].cell) return false; md = &map[m]; #ifdef CELL_NOSTACK //Do not check starting cell as that would get you stuck. if (x0 < 0 || x0 >= md->xs || y0 < 0 || y0 >= md->ys) #else if (x0 < 0 || x0 >= md->xs || y0 < 0 || y0 >= md->ys /*|| map_getcellp(md,x0,y0,cell)*/) #endif return false; if (x1 < 0 || x1 >= md->xs || y1 < 0 || y1 >= md->ys || map_getcellp (md, x1, y1, cell)) return false; // calculate (sgn(x1-x0), sgn(y1-y0)) dx = ( (dx = x1 - x0)) ? ( (dx < 0) ? -1 : 1) : 0; dy = ( (dy = y1 - y0)) ? ( (dy < 0) ? -1 : 1) : 0; // try finding direct path to target x = x0; y = y0; i = 0; while (i < ARRAYLENGTH (wpd->path)) { wpd->path[i] = walk_choices[-dy + 1][dx + 1]; i++; x += dx; y += dy; if (x == x1) dx = 0; if (y == y1) dy = 0; if (dx == 0 && dy == 0) break; // success if (map_getcellp (md, x, y, cell)) break; // obstacle = failure } if (x == x1 && y == y1) { //easy path successful. wpd->path_len = i; wpd->path_pos = 0; return true; } if (flag & 1) return false; memset (tp, 0, sizeof (tp)); i = calc_index (x0, y0); tp[i].x = x0; tp[i].y = y0; tp[i].dist = 0; tp[i].before = 0; tp[i].cost = calc_cost (&tp[i], x1, y1); tp[i].flag = 0; heap[0] = 0; push_heap_path (heap, tp, calc_index (x0, y0)); xs = md->xs - 1; // あらかじめ1減算しておく ys = md->ys - 1; for (;;) { int e = 0, f = 0, dist, cost, dc[4] = {0, 0, 0, 0}; if (heap[0] == 0) return false; rp = pop_heap_path (heap, tp); x = tp[rp].x; y = tp[rp].y; dist = tp[rp].dist + 10; cost = tp[rp].cost; if (x == x1 && y == y1) break; // dc[0] : y++ の時のコスト増分 // dc[1] : x-- の時のコスト増分 // dc[2] : y-- の時のコスト増分 // dc[3] : x++ の時のコスト増分 if (y < ys && !map_getcellp (md, x , y + 1, cell)) { f |= 1; dc[0] = (y >= y1 ? 20 : 0); e += add_path (heap, tp, x , y + 1, dist, rp, cost + dc[0]); // (x, y+1) } if (x > 0 && !map_getcellp (md, x - 1, y , cell)) { f |= 2; dc[1] = (x <= x1 ? 20 : 0); e += add_path (heap, tp, x - 1, y , dist, rp, cost + dc[1]); // (x-1, y ) } if (y > 0 && !map_getcellp (md, x , y - 1, cell)) { f |= 4; dc[2] = (y <= y1 ? 20 : 0); e += add_path (heap, tp, x , y - 1, dist, rp, cost + dc[2]); // (x , y-1) } if (x < xs && !map_getcellp (md, x + 1, y , cell)) { f |= 8; dc[3] = (x >= x1 ? 20 : 0); e += add_path (heap, tp, x + 1, y , dist, rp, cost + dc[3]); // (x+1, y ) } if ( (f & (2 + 1)) == (2 + 1) && !map_getcellp (md, x - 1, y + 1, cell)) e += add_path (heap, tp, x - 1, y + 1, dist + 4, rp, cost + dc[1] + dc[0] - 6); // (x-1, y+1) if ( (f & (2 + 4)) == (2 + 4) && !map_getcellp (md, x - 1, y - 1, cell)) e += add_path (heap, tp, x - 1, y - 1, dist + 4, rp, cost + dc[1] + dc[2] - 6); // (x-1, y-1) if ( (f & (8 + 4)) == (8 + 4) && !map_getcellp (md, x + 1, y - 1, cell)) e += add_path (heap, tp, x + 1, y - 1, dist + 4, rp, cost + dc[3] + dc[2] - 6); // (x+1, y-1) if ( (f & (8 + 1)) == (8 + 1) && !map_getcellp (md, x + 1, y + 1, cell)) e += add_path (heap, tp, x + 1, y + 1, dist + 4, rp, cost + dc[3] + dc[0] - 6); // (x+1, y+1) tp[rp].flag = 1; if (e || heap[0] >= MAX_HEAP - 5) return false; } if (! (x == x1 && y == y1)) // will never happen... return false; for (len = 0, i = rp; len < 100 && i != calc_index (x0, y0); i = tp[i].before, len++); if (len == 100 || len >= sizeof (wpd->path)) return false; wpd->path_len = len; wpd->path_pos = 0; for (i = rp, j = len - 1; j >= 0; i = tp[i].before, j--) { int dx = tp[i].x - tp[tp[i].before].x; int dy = tp[i].y - tp[tp[i].before].y; int dir; if (dx == 0) { dir = (dy > 0 ? 0 : 4); } else if (dx > 0) { dir = (dy == 0 ? 6 : (dy < 0 ? 5 : 7)); } else { dir = (dy == 0 ? 2 : (dy > 0 ? 1 : 3)); } wpd->path[j] = dir; } return true; }
/*========================================== * path探索 (x0,y0)->(x1,y1) *------------------------------------------ */ int path_search(struct walkpath_data *wpd, map_local *m, int x0, int y0, int x1, int y1, int flag) { int heap[MAX_HEAP + 1]; int i, rp, x, y; int dx, dy; nullpo_ret(wpd); assert (m->gat); map_local *md = m; if (x1 < 0 || x1 >= md->xs || y1 < 0 || y1 >= md->ys || bool(read_gatp(md, x1, y1) & MapCell::UNWALKABLE)) return -1; // easy dx = (x1 - x0 < 0) ? -1 : 1; dy = (y1 - y0 < 0) ? -1 : 1; for (x = x0, y = y0, i = 0; x != x1 || y != y1;) { if (i >= sizeof(wpd->path)) return -1; if (x != x1 && y != y1) { if (!can_move(md, x, y, x + dx, y + dy)) break; x += dx; y += dy; wpd->path[i++] = (dx < 0) ? ((dy > 0) ? DIR::SW : DIR::NW) : ((dy < 0) ? DIR::NE : DIR::SE); } else if (x != x1) { if (!can_move(md, x, y, x + dx, y)) break; x += dx; wpd->path[i++] = (dx < 0) ? DIR::W : DIR::E; } else { // y!=y1 if (!can_move(md, x, y, x, y + dy)) break; y += dy; wpd->path[i++] = (dy > 0) ? DIR::S : DIR::N; } if (x == x1 && y == y1) { wpd->path_len = i; wpd->path_pos = 0; wpd->path_half = 0; return 0; } } if (flag & 1) return -1; struct tmp_path tp[MAX_WALKPATH * MAX_WALKPATH] {}; i = calc_index(x0, y0); tp[i].x = x0; tp[i].y = y0; tp[i].dist = 0; tp[i].dir = DIR::S; tp[i].before = 0; tp[i].cost = calc_cost(&tp[i], x1, y1); tp[i].flag = 0; heap[0] = 0; push_heap_path(heap, tp, calc_index(x0, y0)); while (1) { int e = 0; if (heap[0] == 0) return -1; rp = pop_heap_path(heap, tp); x = tp[rp].x; y = tp[rp].y; if (x == x1 && y == y1) { int len, j; for (len = 0, i = rp; len < 100 && i != calc_index(x0, y0); i = tp[i].before, len++); if (len == 100 || len >= sizeof(wpd->path)) return -1; wpd->path_len = len; wpd->path_pos = 0; wpd->path_half = 0; for (i = rp, j = len - 1; j >= 0; i = tp[i].before, j--) wpd->path[j] = tp[i].dir; return 0; } if (can_move(md, x, y, x + 1, y - 1)) e += add_path(heap, tp, x + 1, y - 1, tp[rp].dist + 14, DIR::NE, rp, x1, y1); if (can_move(md, x, y, x + 1, y)) e += add_path(heap, tp, x + 1, y, tp[rp].dist + 10, DIR::E, rp, x1, y1); if (can_move(md, x, y, x + 1, y + 1)) e += add_path(heap, tp, x + 1, y + 1, tp[rp].dist + 14, DIR::SE, rp, x1, y1); if (can_move(md, x, y, x, y + 1)) e += add_path(heap, tp, x, y + 1, tp[rp].dist + 10, DIR::S, rp, x1, y1); if (can_move(md, x, y, x - 1, y + 1)) e += add_path(heap, tp, x - 1, y + 1, tp[rp].dist + 14, DIR::SW, rp, x1, y1); if (can_move(md, x, y, x - 1, y)) e += add_path(heap, tp, x - 1, y, tp[rp].dist + 10, DIR::W, rp, x1, y1); if (can_move(md, x, y, x - 1, y - 1)) e += add_path(heap, tp, x - 1, y - 1, tp[rp].dist + 14, DIR::NW, rp, x1, y1); if (can_move(md, x, y, x, y - 1)) e += add_path(heap, tp, x, y - 1, tp[rp].dist + 10, DIR::N, rp, x1, y1); tp[rp].flag = 1; if (e || heap[0] >= MAX_HEAP - 5) return -1; } }
bool pathfinder::build_costmap() { INFO_TARGET << "Pathfinder build costmap: (" << m_limits.X.min << "," << m_limits.Z.min << ") (" << m_limits.X.max << "," << m_limits.Z.max << ")" << std::endl; m_data.resize(m_max_index_x); for (int x = 0; x < m_max_index_x; x++) { m_data[x].resize(m_max_index_z); for (int z = 0; z < m_max_index_z; z++) { m_data[x][z].resize(m_max_index_y); int surfaces = 0; for (int y = 0; y < m_max_index_y; y++) { v3s16 ipos(x,y,z); v3s16 realpos = getRealPos(ipos); MapNode current = m_env->getMap().getNodeNoEx(realpos); MapNode below = m_env->getMap().getNodeNoEx(realpos + v3s16(0,-1,0)); if ((current.param0 == CONTENT_IGNORE) || (below.param0 == CONTENT_IGNORE)) { DEBUG_OUT("Pathfinder: " << PPOS(realpos) << " current or below is invalid element" << std::endl); if (current.param0 == CONTENT_IGNORE) { m_data[x][z][y].type = 'i'; DEBUG_OUT(x << "," << y << "," << z << ": " << 'i' << std::endl); } continue; } //don't add anything if it isn't an air node if ((current.param0 != CONTENT_AIR) || (below.param0 == CONTENT_AIR )) { DEBUG_OUT("Pathfinder: " << PPOS(realpos) << " not on surface" << std::endl); if (current.param0 != CONTENT_AIR) { m_data[x][z][y].type = 's'; DEBUG_OUT(x << "," << y << "," << z << ": " << 's' << std::endl); } else { m_data[x][z][y].type = '-'; DEBUG_OUT(x << "," << y << "," << z << ": " << '-' << std::endl); } continue; } surfaces++; m_data[x][z][y].valid = true; m_data[x][z][y].pos = realpos; m_data[x][z][y].type = 'g'; DEBUG_OUT(x << "," << y << "," << z << ": " << 'a' << std::endl); if (m_prefetch) { m_data[x][z][y].directions[DIR_XP] = calc_cost(realpos,v3s16( 1,0, 0)); m_data[x][z][y].directions[DIR_XM] = calc_cost(realpos,v3s16(-1,0, 0)); m_data[x][z][y].directions[DIR_ZP] = calc_cost(realpos,v3s16( 0,0, 1)); m_data[x][z][y].directions[DIR_ZM] = calc_cost(realpos,v3s16( 0,0,-1)); } } if (surfaces >= 1 ) { for (int y = 0; y < m_max_index_y; y++) { if (m_data[x][z][y].valid) { m_data[x][z][y].surfaces = surfaces; } } } } } return true; }
int local_optimization(int n, int edge[][SIZE+1]) { int i, j, k; int loop = 0; int improved = 1; int modify = 0; int cost, num; int idx = -1; unsigned long seed = get_nano_seconds(); srand(seed); Chromosome *tmp; init_chromosome(&tmp, edge); for (i=0; i<=SIZE; i++) tmp->ch[i] = offsprings[n]->ch[i]; for (num=0; num<HUBS; num++) { int r = rand() % N + 1; int neighbors[SIZE+1]; int n_count = 0; for (i=1; i<= SIZE; i++) { if (edge[r][i] != 0) neighbors[++n_count] = i; } neighbors[0] = r; while (improved) { improved = 0; cost = calc_cost(offsprings[n], edge); for (i=0; i<= n_count; i++) { tmp->ch[neighbors[i]] = (1 - (tmp->ch[neighbors[i]])) % 2; calc_cost(tmp, edge); if (tmp->cost > cost) { cost = tmp->cost; idx = i; improved = 1; } tmp->ch[neighbors[i]] = (1 - (tmp->ch[neighbors[i]])) % 2; } if (improved) { offsprings[n]->ch[neighbors[idx]] = (1 - (offsprings[n]->ch[neighbors[idx]])) % 2; tmp->ch[neighbors[idx]] = (1 - (tmp->ch[neighbors[idx]])) % 2; } } } free_chromosome(tmp); return 1; }
ERL_NIF_TERM pathfind(ErlNifEnv *env, int argc, ERL_NIF_TERM argv[]) { /*debug("----------------------------\n");*/ int id, x0, y0, x1, y1; ERL_NIF_TERM eid, from, to, head, tail; eid = argv[0]; from = argv[1]; to = argv[2]; // Get the map ID enif_get_int(env, eid, &id); // Get the From X, Y enif_get_list_cell(env, from, &head, &tail); enif_get_int(env, head, &x0); enif_get_int(env, tail, &y0); // Get the To X, Y enif_get_list_cell(env, to, &head, &tail); enif_get_int(env, head, &x1); enif_get_int(env, tail, &y1); struct map_data map = maps[id]; struct tmp_path tp[MAX_WALKPATH * MAX_WALKPATH]; int heap[151]; int rp, xs, ys; ERL_NIF_TERM *path; ERL_NIF_TERM *step; register int i = 0, j = 0, len, x = x0, y = y0, dx = ((dx = x1 - x0) ? ((dx < 0) ? -1 : 1) : 0), dy = ((dy = y1 - y0) ? ((dy < 0) ? -1 : 1) : 0); /* printmap(map); */ /* debug("Pathfinding.\n"); */ /* debug("\tMap: %d (%d x %d)\n", id, map.width, map.height); */ /* debug("\tFrom: (%d, %d)\n", x0, y0); */ /* debug("\tTo: (%d, %d)\n", x1, y1); */ /* debug("\tFirst step: %d\n", at(map, x + dx, y + dy)); */ step = (ERL_NIF_TERM *)malloc(3 * sizeof(ERL_NIF_TERM)); path = (ERL_NIF_TERM *)malloc(MAX_WALKPATH * sizeof(ERL_NIF_TERM)); for (i = 0; i < MAX_WALKPATH && (x != x1 || y != y1) && at(map, x + dx, y + dy) == 0; i++) { x += dx; y += dy; /* debug("OK: (%d, %d)\n", x, y); */ step[0] = enif_make_int(env, x); step[1] = enif_make_int(env, y); step[2] = enif_make_int(env, walk_choices[-dy + 1][dx + 1]); path[i] = enif_make_tuple(env, 3, step[0], step[1], step[2]); if (x == x1) dx = 0; if (y == y1) dy = 0; /* debug("Next cell? %d (Done: %d)\n", at(map, x + dx, y + dy), dx == 0 && dy == 0); */ } // Simple pathfinding was successful if (x == x1 && y == y1) return finish(env, path, step, i); memset(tp, 0, sizeof(tp)); i = calc_index(x0,y0); tp[i].x = x0; tp[i].y = y0; tp[i].dist = 0; tp[i].before = 0; tp[i].cost = calc_cost(&tp[i], x1, y1); tp[i].flag = 0; heap[0] = 0; push_heap_path(heap, tp, calc_index(x0,y0)); xs = map.width - 1; // あらかじめ1減算しておく ys = map.height - 1; while (1) { int e = 0, f = 0, dist, cost, dc[4] = {0, 0, 0, 0}; if(heap[0] == 0) return finish(env, path, step, 0); rp = pop_heap_path(heap,tp); x = tp[rp].x; y = tp[rp].y; dist = tp[rp].dist + 10; cost = tp[rp].cost; if (x == x1 && y == y1) break; // dc[0] : y++ の時のコスト増分 // dc[1] : x-- の時のコスト増分 // dc[2] : y-- の時のコスト増分 // dc[3] : x++ の時のコスト増分 if (y < ys && !at(map, x, y + 1)) { f |= 1; dc[0] = (y >= y1 ? 20 : 0); e += add_path(heap, tp, x, y + 1, dist, rp, cost + dc[0]); // (x, y+1) } if (x > 0 && !at(map, x - 1, y)) { f |= 2; dc[1] = (x <= x1 ? 20 : 0); e += add_path(heap, tp, x - 1, y, dist, rp, cost + dc[1]); // (x-1, y ) } if (y > 0 && !at(map, x, y - 1)) { f |= 4; dc[2] = (y <= y1 ? 20 : 0); e += add_path(heap, tp, x, y - 1, dist, rp, cost + dc[2]); // (x , y-1) } if (x < xs && !at(map, x + 1, y)) { f |= 8; dc[3] = (x >= x1 ? 20 : 0); e += add_path(heap, tp, x + 1, y, dist, rp, cost + dc[3]); // (x+1, y ) } if((f & (2+1)) == (2+1) && !at(map, x - 1, y + 1)) e += add_path(heap, tp, x - 1, y + 1, dist + 4, rp, cost + dc[1] + dc[0] - 6); // (x-1, y+1) if((f & (2+4)) == (2+4) && !at(map, x - 1, y - 1)) e += add_path(heap, tp, x - 1, y - 1, dist + 4, rp, cost + dc[1] + dc[2] - 6); // (x-1, y-1) if((f & (8+4)) == (8+4) && !at(map, x + 1, y - 1)) e += add_path(heap, tp, x + 1, y - 1, dist + 4, rp, cost + dc[3] + dc[2] - 6); // (x+1, y-1) if((f & (8+1)) == (8+1) && !at(map, x + 1, y + 1)) e += add_path(heap, tp, x + 1, y + 1, dist + 4, rp, cost + dc[3] + dc[0] - 6); // (x+1, y+1) tp[rp].flag = 1; if (e || heap[0] >= 150 - 5) return finish(env, path, step, 0); } for (len = 0, i = rp; len < 100 && i != calc_index(x0, y0); i = tp[i].before, len++); if (len == 100 || len >= MAX_WALKPATH) return finish(env, path, step, 0); for (i = rp, j = len - 1; j >= 0; i = tp[i].before, j--) { int dx = tp[i].x - tp[tp[i].before].x; int dy = tp[i].y - tp[tp[i].before].y; /* int dir; */ step[0] = enif_make_int(env, tp[i].x); step[1] = enif_make_int(env, tp[i].y); /* if (dx == 0) */ /* dir = (dy > 0 ? 0 : 4); */ /* else if (dx > 0) */ /* dir = (dy == 0 ? 6 : (dy < 0 ? 5 : 7)); */ /* else */ /* dir = (dy == 0 ? 2 : (dy > 0 ? 1 : 3)); */ step[2] = enif_make_int(env, walk_choices[-dy + 1][dx + 1]); path[j] = enif_make_tuple(env, 3, step[0], step[1], step[2]); } return finish(env, path, step, len); }
/*========================================== * path探索 (x0,y0)->(x1,y1) *------------------------------------------ */ int path_search(struct walkpath_data *wpd,int m,int x0,int y0,int x1,int y1,int flag) { int heap[MAX_HEAP+1]; struct tmp_path tp[MAX_WALKPATH*MAX_WALKPATH]; int i,rp,x,y; struct map_data *md; int dx,dy; if(!map[m].gat) return -1; md=&map[m]; if(x1<0 || x1>=md->xs || y1<0 || y1>=md->ys || (i=read_gatp(md,x1,y1))==1 || i==5) return -1; // easy dx = (x1-x0<0) ? -1 : 1; dy = (y1-y0<0) ? -1 : 1; for(x=x0,y=y0,i=0;x!=x1 || y!=y1;){ if(i>=sizeof(wpd->path)) return -1; if(x!=x1 && y!=y1){ if(!can_move(md,x,y,x+dx,y+dy,flag)) break; x+=dx; y+=dy; wpd->path[i++]=(dx<0) ? ((dy>0)? 1 : 3) : ((dy<0)? 5 : 7); } else if(x!=x1){ if(!can_move(md,x,y,x+dx,y ,flag)) break; x+=dx; wpd->path[i++]=(dx<0) ? 2 : 6; } else { // y!=y1 if(!can_move(md,x,y,x ,y+dy,flag)) break; y+=dy; wpd->path[i++]=(dy>0) ? 0 : 4; } if(x==x1 && y==y1){ wpd->path_len=i; wpd->path_pos=0; wpd->path_half=0; return 0; } } if(flag&1) return -1; memset(tp,0,sizeof(tp)); i=calc_index(x0,y0); tp[i].x=x0; tp[i].y=y0; tp[i].dist=0; tp[i].dir=0; tp[i].before=0; tp[i].cost=calc_cost(&tp[i],x1,y1); tp[i].flag=0; heap[0]=0; push_heap_path(heap,tp,calc_index(x0,y0)); while(1){ int e=0,fromdir; if(heap[0]==0) return -1; rp=pop_heap_path(heap,tp); x=tp[rp].x; y=tp[rp].y; if(x==x1 && y==y1){ int len,j; for(len=0,i=rp;len<100 && i!=calc_index(x0,y0);i=tp[i].before,len++); if(len==100 || len>=sizeof(wpd->path)) return -1; wpd->path_len=len; wpd->path_pos=0; wpd->path_half=0; for(i=rp,j=len-1;j>=0;i=tp[i].before,j--) wpd->path[j]=tp[i].dir; return 0; } fromdir=tp[rp].dir; if(can_move(md,x,y,x+1,y-1,flag)) e+=add_path(heap,tp,x+1,y-1,tp[rp].dist+14,5,rp,x1,y1); if(can_move(md,x,y,x+1,y ,flag)) e+=add_path(heap,tp,x+1,y ,tp[rp].dist+10,6,rp,x1,y1); if(can_move(md,x,y,x+1,y+1,flag)) e+=add_path(heap,tp,x+1,y+1,tp[rp].dist+14,7,rp,x1,y1); if(can_move(md,x,y,x ,y+1,flag)) e+=add_path(heap,tp,x ,y+1,tp[rp].dist+10,0,rp,x1,y1); if(can_move(md,x,y,x-1,y+1,flag)) e+=add_path(heap,tp,x-1,y+1,tp[rp].dist+14,1,rp,x1,y1); if(can_move(md,x,y,x-1,y ,flag)) e+=add_path(heap,tp,x-1,y ,tp[rp].dist+10,2,rp,x1,y1); if(can_move(md,x,y,x-1,y-1,flag)) e+=add_path(heap,tp,x-1,y-1,tp[rp].dist+14,3,rp,x1,y1); if(can_move(md,x,y,x ,y-1,flag)) e+=add_path(heap,tp,x ,y-1,tp[rp].dist+10,4,rp,x1,y1); tp[rp].flag=1; if(e || heap[0]>=MAX_HEAP-5) return -1; } return -1; }
/*========================================== * path探索 (x0,y0)->(x1,y1) *------------------------------------------ */ int path_search_real(struct walkpath_data *wpd,int m,int x0,int y0,int x1,int y1,int easy,cell_t flag) { int x, y, i = 0; int dx, dy; struct map_data *md = &map[m]; if(!map[m].gat) return -1; // path_search2() の場合map_getcellp() の返り値は常に0 if(x0 < 0 || x0 >= md->xs || y0 < 0 || y0 >= md->ys || map_getcellp(md,x0,y0,flag)) return -1; if(x1 < 0 || x1 >= md->xs || y1 < 0 || y1 >= md->ys || map_getcellp(md,x1,y1,flag)) return -1; // easy // この内部では、0 <= x+dx < sx, 0 <= y+dy < sy は保証されている dx = (x1 - x0 < 0) ? -1 : 1; dy = (y1 - y0 < 0) ? -1 : 1; x = x0; y = y0; while(x != x1 || y != y1) { if(i >= MAX_WALKPATH) return -1; if(x != x1 && y != y1) { if(map_getcellp(md,x+dx,y ,flag)) break; if(map_getcellp(md,x ,y+dy,flag)) break; if(map_getcellp(md,x+dx,y+dy,flag)) break; x += dx; y += dy; if(wpd) wpd->path[i++] = walk_choice[-dy+1][dx+1]; } else if(x != x1) { if(map_getcellp(md,x+dx,y,flag)) break; x += dx; if(wpd) wpd->path[i++] = walk_choice[1][dx+1]; } else { // y!=y1 if(map_getcellp(md,x,y+dy,flag)) break; y += dy; if(wpd) wpd->path[i++] = walk_choice[-dy+1][1]; } if(x == x1 && y == y1) { if(wpd) { wpd->path_len = i; wpd->path_pos = 0; } return 0; } } if(!easy) { int xs, ys, rp; int len, j; int heap[MAX_HEAP+1]; struct tmp_path tp[MAX_WALKPATH * MAX_WALKPATH]; memset(tp, 0, sizeof(tp)); i = calc_index(x0,y0); tp[i].x = x0; tp[i].y = y0; tp[i].dist = 0; tp[i].before = 0; tp[i].cost = calc_cost(&tp[i],x1,y1); tp[i].flag = 0; heap[0] = 0; push_heap_path(heap,tp,calc_index(x0,y0)); // あらかじめ1減算しておく xs = md->xs - 1; ys = md->ys - 1; while(1) { int e = 0, f = 0; int dist, cost; int dc[4] = { 0, 0, 0, 0 }; if(heap[0] == 0) return -1; rp = pop_heap_path(heap,tp); x = tp[rp].x; y = tp[rp].y; if(x == x1 && y == y1) break; dist = tp[rp].dist + 10; cost = tp[rp].cost; // dc[0] : y++ の時のコスト増分 // dc[1] : x-- の時のコスト増分 // dc[2] : y-- の時のコスト増分 // dc[3] : x++ の時のコスト増分 if(y < ys && !map_getcellp(md,x ,y+1,flag)) { f |= 1; dc[0] = (y >= y1 ? 20 : 0); e += add_path(heap,tp,x ,y+1,dist,rp,cost+dc[0]); // (x, y+1) } if(x > 0 && !map_getcellp(md,x-1,y ,flag)) { f |= 2; dc[1] = (x <= x1 ? 20 : 0); e += add_path(heap,tp,x-1,y ,dist,rp,cost+dc[1]); // (x-1, y ) } if(y > 0 && !map_getcellp(md,x ,y-1,flag)) { f |= 4; dc[2] = (y <= y1 ? 20 : 0); e += add_path(heap,tp,x ,y-1,dist,rp,cost+dc[2]); // (x , y-1) } if(x < xs && !map_getcellp(md,x+1,y ,flag)) { f |= 8; dc[3] = (x >= x1 ? 20 : 0); e += add_path(heap,tp,x+1,y ,dist,rp,cost+dc[3]); // (x+1, y ) } if( (f & (2+1)) == (2+1) && !map_getcellp(md,x-1,y+1,flag)) e += add_path(heap,tp,x-1,y+1,dist+4,rp,cost+dc[1]+dc[0]-6); // (x-1, y+1) if( (f & (2+4)) == (2+4) && !map_getcellp(md,x-1,y-1,flag)) e += add_path(heap,tp,x-1,y-1,dist+4,rp,cost+dc[1]+dc[2]-6); // (x-1, y-1) if( (f & (8+4)) == (8+4) && !map_getcellp(md,x+1,y-1,flag)) e += add_path(heap,tp,x+1,y-1,dist+4,rp,cost+dc[3]+dc[2]-6); // (x+1, y-1) if( (f & (8+1)) == (8+1) && !map_getcellp(md,x+1,y+1,flag)) e += add_path(heap,tp,x+1,y+1,dist+4,rp,cost+dc[3]+dc[0]-6); // (x+1, y+1) tp[rp].flag = 1; if(e || heap[0] >= MAX_HEAP - 5) return -1; } for(len = 0, i = rp; len < MAX_WALKPATH && i != calc_index(x0,y0); i = tp[i].before, len++); if(len >= MAX_WALKPATH) return -1; if(wpd == NULL) return 0; wpd->path_len = len; wpd->path_pos = 0; for(i = rp, j = len-1; j >= 0; i = tp[i].before, j--) { int tx = tp[i].x - tp[tp[i].before].x; int ty = tp[i].y - tp[tp[i].before].y; wpd->path[j] = walk_choice[-ty+1][tx+1]; } #if 0 // test { x = x0; y = y0; for(i = 0; i < wpd->path_len; i++) { x += dirx[ wpd->path[i] ]; y += diry[ wpd->path[i] ]; if( map_getcellp(md,x,y,flag) ) { printf("path_search_real: cannot move(%d, %d)\n", x, y); return -1; } } if( x != x1 || y != y1 ) { printf("path_search_real: dest position is wrong. ok:(%d, %d) ng:(%d,%d)\n", x1, y1, x, y); return -1; } } #endif return 0; } return -1; }