seqan::String<int> computeScore(TText const & text, TPattern const & pattern) { seqan::String<int> score; seqan::resize(score, seqan::length(text), 0); for (unsigned i = 0; i < seqan::length(text) - seqan::length(pattern) + 1; ++i) score[i] = computeLocalScore(infix(text, i, i + seqan::length(pattern)), pattern); return score; }
void updateWrongs(puzzle p, int **cur_sol, int *wrongs, int *wsize_ptr, int i) { int off_i[4]={1, -1, -p.w_size, p.w_size}; int k, ls, j; for(k=0; k<4; k++){ // for each neighbor(i): j=i+off_i[k]; if(j>=0 && j<p.n){ ls = computeLocalScore(p, cur_sol, cur_sol[j][0],j, cur_sol[j][1]); if(ls==MAX_LOCAL_SCORE){ removeWrong(p, cur_sol, wrongs, wsize_ptr, j); } else { addWrong(p, cur_sol, wrongs, wsize_ptr, j); } } } return; }
/* adaptiveSearch return n:number of wrong pieces left */ int adaptiveSearch(puzzle p, int **cur_sol) { int* wrongs; //array of wrong pieces wrongs = (int *) malloc(p.n*sizeof(int)); int n, found=1, new_score, score, i, j, tmp, rot, max, max_rot, old, index, jndex; //compute wrong pieces' array and actual score score=computeScore(p, cur_sol, wrongs, &n); if (n==0){ //previous heuristics has already found optimum. return(0); } while(found){ found=0; #ifndef WRONGS n=p.n; #endif for(i=0; i<n && !found;i++){ /*try rotating the piece in place */ index=i; #ifdef WRONGS index=wrongs[i]; #endif max_rot=-1; old=max=computeLocalScore(p, cur_sol, cur_sol[index][0], index, cur_sol[index][1]); for(rot=0;rot<4;rot++){ tmp=computeLocalScore(p, cur_sol, cur_sol[index][0], index, rot); if(tmp>max){ max=tmp; max_rot=rot; } } if(max_rot>=0){ cur_sol[index][1]=max_rot; score+=max-old; //TODO: update wrongs found=1; } for(j=i+1;j<n && !found;j++){ jndex=j; #ifdef WRONGS jndex=wrongs[j]; #endif //swap one to one between 2 wrong pieces new_score=trySwapPieces(p, cur_sol, score, index, jndex, wrongs,&n ); if(new_score>score){ found=1; score=new_score; } //else try other 2 pieces } } } free(wrongs); return(0); }
/*trySwapPieces * compute the score the puzzle WOULD have, if swap occured * p:puzzle * i, j: pieces to be swap * returns: new total score with the swap * */ int trySwapPieces(puzzle p,int **cur_sol,int score, int i, int j, int *wrongs, int *wsize_ptr){ //newscores=oldscores-computeLocalScore(....,cur_sol, i)-computeLocalScore(.....,cur_sol, j) //.... +computeLocalScore(...., swapped_sol, i)+computeLocalScore(....,swapped_sol, j); int rot, tmp, old_i, old_j, old_rot_i, old_rot_j, k, maxi=0, maxj=0, max_rot_i, max_rot_j, found, w, skip=0; int scoreold=score; //store actual pieces and rotations: old_i=cur_sol[i][0]; old_j=cur_sol[j][0]; old_rot_i=cur_sol[i][1]; old_rot_j=cur_sol[j][1]; score-=computeLocalScore(p, cur_sol, cur_sol[i][0], i, cur_sol[i][1]); score-=computeLocalScore(p, cur_sol, cur_sol[j][0], j, cur_sol[j][1]); if(isNeighbor(p, i, j)){ /* try rotating the two pieces in place */ score+=checkEdge(p, cur_sol, i, j); // score for common edge was removed twice, so re-add once for(cur_sol[i][1]=0;cur_sol[i][1]<4;cur_sol[i][1]++){ //rotate i for(cur_sol[j][1]=0;cur_sol[j][1]<4;cur_sol[j][1]++){ //rotate j k=computeLocalScore(p, cur_sol, old_i, i, cur_sol[i][1]); //score from i tmp=computeLocalScore(p, cur_sol, old_j, j, cur_sol[j][1]); //score from j if(tmp+k>maxi+maxj){ maxi=k; maxj=tmp; max_rot_i=cur_sol[i][1]; max_rot_j=cur_sol[j][1]; } } } score+=maxi+maxj; // this adds one point for each "good" edge, so the common edge has double score //update solution cur_sol[i][1]=max_rot_i; cur_sol[j][1]=max_rot_j; score-=checkEdge(p, cur_sol, i, j); //score for common edge has been added twice, then subtract once if (score>scoreold){ skip=1; //-> don't try swapping; maybe next time... } else { //restore cur_sol[i][1]=old_rot_i; cur_sol[j][1]=old_rot_j; score-=maxi+maxj; } if(!skip){ /* swap the pieces (if leads to better score) */ cur_sol[i][0]=old_j; //move j-->i cur_sol[j][0]=old_i; //move i-->j for(cur_sol[i][1]=0;cur_sol[i][1]<4;cur_sol[i][1]++){ //rotate i for(cur_sol[j][1]=0;cur_sol[j][1]<4;cur_sol[j][1]++){ //rotate j k=computeLocalScore(p, cur_sol, old_j, i, cur_sol[i][1]); //score from i tmp=computeLocalScore(p, cur_sol, old_i, j, cur_sol[j][1]); //score from j if(tmp+k>maxi+maxj){ maxi=k; maxj=tmp; max_rot_i=cur_sol[i][1]; max_rot_j=cur_sol[j][1]; } } } score+=maxi+maxj; // this adds one point for each "good" edge, so the common edge has double score score-=checkEdge(p, cur_sol, i, j); //score for common edge has been added twice, then subtract once if (score>scoreold){ //update solution cur_sol[i][1]=max_rot_i; cur_sol[j][1]=max_rot_j; } else { //restore old values: cur_sol[i][0]=old_i; cur_sol[i][1]=old_rot_i; cur_sol[j][0]=old_j; cur_sol[j][1]=old_rot_j; score=scoreold; } } } else { for(rot=0;rot<4;rot++){ tmp=computeLocalScore(p, cur_sol, old_i, j, rot); if(tmp>maxi){ maxi=tmp; max_rot_i=rot; } } score+=maxi; maxj=0; for(rot=0;rot<4;rot++){ tmp=computeLocalScore(p, cur_sol, old_j, i, rot); if(tmp>maxj){ maxj=tmp; max_rot_j=rot; } } score+=maxj; if(score>scoreold){ cur_sol[j][0]=old_i; cur_sol[j][1]=max_rot_i; cur_sol[i][0]=old_j; cur_sol[i][1]=max_rot_j; }else{ return(scoreold); } } /* update wrongs vector */ #ifdef WRONGS if(maxi==MAX_LOCAL_SCORE){ removeWrong(p, cur_sol, wrongs, wsize_ptr, i); } // update neighbors of i updateWrongs(p, cur_sol, wrongs, wsize_ptr, i); if(maxj==MAX_LOCAL_SCORE){ removeWrong(p, cur_sol, wrongs, wsize_ptr, i); } // update neighbors of j updateWrongs(p, cur_sol, wrongs, wsize_ptr, i); #endif return(score); }