/* Last changed Time-stamp: <2008-10-09 16:23:36 ivo> */ #include #include #include #include #include "findpath.h" #include "fold.h" #include "fold_vars.h" #include "utils.h" #include "pair_mat.h" static char rcsid[] = "$Id: findpath.c,v 1.2 2008/10/09 15:42:45 ivo Exp $"; extern int energy_of_struct_pt (char *string, short * ptable, short *s, short *s1); static int energy_of_move(short *pt, short *s, short *s1, int m1, int m2); typedef struct move { int i; /* i,j>0 insert; i,j<0 delete */ int j; int when; /* 0 if still available, else resulting distance from start */ int E; } move_t; typedef struct intermediate { short *pt; /* pair table */ int Sen; /* saddle energy so far */ int curr_en; /* current energy */ move_t *moves; /* remaining moves to target */ } intermediate_t; static int *pair_table_to_loop_index (short *pt); static move_t* copy_moves(move_t *mvs); static int compare_ptable(const void *A, const void *B); static int compare_energy(const void *A, const void *B); static int compare_moves_when(const void *A, const void *B); static void free_intermediate(intermediate_t *i); static char *seq; static short *S, *S1; static int BP_dist; static move_t *path; static int path_fwd; /* 1: struc1->struc2, else struc2 -> struc1 */ static int try_moves(intermediate_t c, int maxE, intermediate_t *next, int dist) { int *loopidx, len, num_next=0, en, oldE; move_t *mv; short *pt; len = c.pt[0]; loopidx = pair_table_to_loop_index(c.pt); oldE = c.Sen; for (mv=c.moves; mv->i!=0; mv++) { int i,j; if (mv->when>0) continue; i = mv->i; j = mv->j; pt = (short *) space(sizeof(short)*(len+1)); memcpy(pt, c.pt,(len+1)*sizeof(short)); if (j<0) { /*it's a delete move */ pt[-i]=0; pt[-j]=0; } else { /* insert move */ if ((loopidx[i] == loopidx[j]) && /* i and j belong to same loop */ (pt[i] == 0) && (pt[j]==0) /* ... and are unpaired */ ) { pt[i]=j; pt[j]=i; } else { free(pt); continue; /* llegal move, try next; */ } } #ifdef LOOP_EN en = c.curr_en + energy_of_move(c.pt, S, S1, i, j); #else en = energy_of_struct_pt(seq, pt, S, S1); #endif if (enoldE)?en:oldE; next[num_next].curr_en = en; next[num_next].pt = pt; mv->when=dist; mv->E = en; next[num_next++].moves = copy_moves(c.moves); mv->when=0; } else free(pt); } free(loopidx); return num_next; } static int find_path_once(char *struc1, char *struc2, int maxE, int maxl) { short *pt1, *pt2; move_t *mlist; int i, len, d, dist=0, result; intermediate_t *current, *next; pt1 = make_pair_table(struc1); pt2 = make_pair_table(struc2); len = (int) strlen(struc1); mlist = (move_t *) space(sizeof(move_t)*len); /* bp_dist < n */ for (i=1; i<=len; i++) { if (pt1[i] != pt2[i]) { if (ipt != NULL; cc++) free_intermediate(cc); current[0].Sen=INT_MAX; break; } /* remove duplicates via sort|uniq if this becomes a bottleneck we can use a hash instead */ qsort(next, num_next, sizeof(intermediate_t),compare_ptable); for (u=0,c=1; cpt != NULL; cc++) free_intermediate(cc); for (u=0; umax) maxl=max; saddleE = find_path_once(struc1, struc2, maxE, maxl); if (saddleE pt[i])) { /* ) */ --hx; if (hx>0) l = loop[stack[hx-1]]; /* index of enclosing loop */ else l=0; /* external loop has index 0 */ if (hx<0) { nrerror("unbalanced brackets in make_pair_table"); } } } loop[0] = nl; free(stack); #ifdef _DEBUG_LOOPIDX fprintf(stderr,"begin loop index\n"); fprintf(stderr, "....,....1....,....2....,....3....,....4" "....,....5....,....6....,....7....,....8\n"); print_structure(pt, loop[0]); for (i=1; i<=length; i++) fprintf(stderr,"%2d ", loop[i]); fprintf(stderr,"\n"); fprintf(stderr, "end loop index\n"); fflush(stderr); #endif return (loop); } static void free_intermediate(intermediate_t *i) { free(i->pt); free(i->moves); i->pt = NULL; i->moves = NULL; i->Sen = INT_MAX; } static int compare_ptable(const void *A, const void *B) { intermediate_t *a, *b; int c; a = (intermediate_t *) A; b = (intermediate_t *) B; c = memcmp(a->pt, b->pt, a->pt[0]*sizeof(short)); if (c!=0) return c; if ((a->Sen - b->Sen) != 0) return (a->Sen - b->Sen); return (a->curr_en - b->curr_en); } static int compare_energy(const void *A, const void *B) { intermediate_t *a, *b; a = (intermediate_t *) A; b = (intermediate_t *) B; if ((a->Sen - b->Sen) != 0) return (a->Sen - b->Sen); return (a->curr_en - b->curr_en); } static int compare_moves_when(const void *A, const void *B) { move_t *a, *b; a = (move_t *) A; b = (move_t *) B; return(a->when - b->when); } static move_t* copy_moves(move_t *mvs) { move_t *new; new = (move_t *) space(sizeof(move_t)*(BP_dist+1)); memcpy(new,mvs,sizeof(move_t)*(BP_dist+1)); return new; } static int energy_of_move(short *pt, short *s, short *s1, int m1, int m2) { int en_post, en_pre, i,j,k,l, len; len = pt[0]; k = (m1>0)?m1:-m1; l = (m2>0)?m2:-m2; /* first find the enclosing pair ij) j=pt[j]; /* skip substructure */ else { fprintf(stderr, "%d %d %d %d ", m1, m2, j, pt[j]); nrerror("illegal move or broken pair table in energy_of_move()"); } } i = (j<=len) ? pt[j] : 0; en_pre = loop_energy(pt, s, s1, i); en_post = 0; if (m1<0) { /*it's a delete move */ en_pre += loop_energy(pt, s, s1, k); pt[k]=0; pt[l]=0; } else { /* insert move */ pt[k]=l; pt[l]=k; en_post += loop_energy(pt, s, s1, k); } en_post += loop_energy(pt, s, s1, i); /* restore pair table */ if (m1<0) { pt[k]=l; pt[l]=k; } else { pt[k]=0; pt[l]=0; } return (en_post - en_pre); } #ifdef TEST_FINDPATH int main(int argc, char *argv[]) { char *seq, *s1, *s2; int E, maxkeep=10; int verbose=0, i; path_t *route, *r; for (i=1; is; r++) { printf("%s %6.2f - %6.2f\n", r->s, energy_of_struct(seq,r->s), r->en); free(r->s); } } free(route); free(seq); free(s1); free(s2); return(EXIT_SUCCESS); } #endif