WSTester updated to work plus hopefully all the other changes that need to go into...
[jabaws.git] / binaries / src / ViennaRNA / lib / move_set.c
diff --git a/binaries/src/ViennaRNA/lib/move_set.c b/binaries/src/ViennaRNA/lib/move_set.c
new file mode 100644 (file)
index 0000000..8c2c339
--- /dev/null
@@ -0,0 +1,984 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <limits.h>
+#include <time.h>
+
+#include "fold.h"
+
+#include "move_set.h"
+
+/* maximum degeneracy value - if degeneracy is greater than this, program segfaults*/
+#define MAX_DEGEN 100
+#define MINGAP 3
+
+
+#define space(a) malloc(a)
+
+#define bool int
+#define true 1
+#define false 0
+
+int compare(short *lhs, short *rhs)
+{
+
+  /* printf("%d ", (int)lhs[0]); */
+
+  int i=1;
+  char l=0,r=0;
+  while (i<=lhs[0]) {
+    l = (lhs[i]==0?'.':(lhs[i]<lhs[lhs[i]]?'(':')'));
+    r = (rhs[i]==0?'.':(rhs[i]<rhs[rhs[i]]?'(':')'));
+    if (l != r) break;
+    i++;
+  }
+
+  return (i<=lhs[0] && l>r);
+}
+
+int find_min(short *arr[MAX_DEGEN], int begin, int end) {
+  short *min = arr[begin];
+  short min_num = begin;
+  int i;
+
+  for (i=begin+1; i<end; i++) {
+    if (compare(arr[i], min)) {
+      min = arr[i];
+      min_num = i;
+    }
+  }
+  return min_num;
+}
+
+int equals(const short *first, const short *second)
+{
+  int i=1;
+  while (i<=first[0] && first[i]==second[i]) {
+    i++;
+  }
+  if (i>first[0]) return 1;
+  else return 0;
+}
+
+void copy_arr(short *dest, short *src)
+{
+  if (!src || !dest) {
+    fprintf(stderr, "Empty pointer in copying\n");
+    return;
+  }
+  memcpy(dest, src, sizeof(short)*(src[0]+1));
+}
+
+short *allocopy(short *src)
+{
+  short *res = (short*) space(sizeof(short)*(src[0]+1));
+  copy_arr(res, src);
+  return res;
+}
+
+/* ############################## DECLARATION #####################################*/
+/* private functions & declarations*/
+
+static int cnt_move = 0;
+int count_move() {return cnt_move;}
+
+/*check if base is lone*/
+int lone_base(short *pt, int i);
+
+/* can move be done on this structure? (move is in the Enc)*/
+int check_insert(struct_en *str, int i, int j);
+
+/* internal struct with moves, sequence, degeneracy and options*/
+typedef struct _Encoded {
+  /* sequence*/
+  short *s0;
+  short *s1;
+
+  char  *seq;
+
+  /* moves*/
+  int   bp_left;
+  int   bp_right;
+  int   bp_left2;   /* if noLP is enabled (and for shift moves)*/
+  int   bp_right2;
+
+  /* options*/
+  int noLP;
+  int verbose_lvl;
+  int first;
+  int shift;
+
+  /* degeneracy*/
+  int begin_unpr;
+  int begin_pr;
+  int end_unpr;
+  int end_pr;
+  short *processed[MAX_DEGEN];
+  short *unprocessed[MAX_DEGEN];
+  int current_en;
+
+  /* moves in random (needs to be freed afterwards)*/
+  int *moves_from;
+  int *moves_to;
+  int num_moves;
+
+  /* function for flooding */
+  int (*funct) (struct_en*, struct_en*);
+
+
+} Encoded;
+
+/* frees all things allocated by degeneracy...*/
+void free_degen(Encoded *Enc)
+{
+  int i;
+  for (i=Enc->begin_unpr; i<Enc->end_unpr; i++) {
+    if (Enc->unprocessed[i]) {
+      free(Enc->unprocessed[i]);
+      Enc->unprocessed[i]=NULL;
+    }
+  }
+  for (i=Enc->begin_pr; i<Enc->end_pr; i++) {
+    if (Enc->processed[i]) {
+      free(Enc->processed[i]);
+      Enc->processed[i]=NULL;
+    }
+  }
+  Enc->begin_pr=0;
+  Enc->begin_unpr=0;
+  Enc->end_pr=0;
+  Enc->end_unpr=0;
+}
+
+/* ############################## IMPLEMENTATION #####################################*/
+
+/* reads a line no matter how long*/
+char* my_getline(FILE *fp)
+{
+  char s[512], *line, *cp;
+  line = NULL;
+  do {
+    if(fgets(s, 512, fp) == NULL) break;
+    cp = strchr(s, '\n');
+    if(cp != NULL) *cp = '\0';
+    if(line == NULL) line = (char *) calloc(strlen(s) + 1, sizeof(char));
+    else line = (char *) realloc(line, strlen(s) + strlen(line) + 1);
+    strcat (line, s);
+  } while (cp == NULL);
+  return (line);
+}
+
+inline void do_move(short *pt, int bp_left, int bp_right)
+{
+  /* delete*/
+  if (bp_left<0) {
+    pt[-bp_left]=0;
+    pt[-bp_right]=0;
+  } else { /* insert*/
+    pt[bp_left]=bp_right;
+    pt[bp_right]=bp_left;
+  }
+}
+
+/* done with all structures along the way to deepest*/
+int update_deepest(Encoded *Enc, struct_en *str, struct_en *min)
+{
+  /* apply move + get its energy*/
+  int tmp_en;
+  tmp_en = str->energy + energy_of_move_pt(str->structure, Enc->s0, Enc->s1, Enc->bp_left, Enc->bp_right);
+  do_move(str->structure, Enc->bp_left, Enc->bp_right);
+  if (Enc->bp_left2 != 0) {
+    tmp_en += energy_of_move_pt(str->structure, Enc->s0, Enc->s1, Enc->bp_left2, Enc->bp_right2);
+    do_move(str->structure, Enc->bp_left2, Enc->bp_right2);
+  }
+  int last_en = str->energy;
+  str->energy = tmp_en;
+
+
+  /* use f_point if we have it */
+  if (Enc->funct) {
+    int end = Enc->funct(str, min);
+
+    /*  undo moves */
+    if (Enc->bp_left2!=0) do_move(str->structure, -Enc->bp_left2, -Enc->bp_right2);
+    do_move(str->structure, -Enc->bp_left, -Enc->bp_right);
+    str->energy = last_en;
+    Enc->bp_left=0;
+    Enc->bp_right=0;
+    Enc->bp_left2=0;
+    Enc->bp_right2=0;
+
+    return (end?1:0);
+  }
+
+  if (Enc->verbose_lvl>1) { fprintf(stderr, "  "); print_str(stderr, str->structure); fprintf(stderr, " %d\n", tmp_en); }
+
+  /* better deepest*/
+  if (tmp_en < min->energy) {
+    min->energy = tmp_en;
+    copy_arr(min->structure, str->structure);
+
+    /* delete degeneracy*/
+    free_degen(Enc);
+
+    /* undo moves*/
+    if (Enc->bp_left2!=0) do_move(str->structure, -Enc->bp_left2, -Enc->bp_right2);
+    do_move(str->structure, -Enc->bp_left, -Enc->bp_right);
+    str->energy = last_en;
+    Enc->bp_left=0;
+    Enc->bp_right=0;
+    Enc->bp_left2=0;
+    Enc->bp_right2=0;
+    return 1;
+  }
+
+  /* degeneracy*/
+  if ((str->energy == min->energy) && (Enc->current_en == min->energy)) {
+    int found = 0;
+    int i;
+    for (i=Enc->begin_pr; i<Enc->end_pr; i++) {
+      if (equals(Enc->processed[i], str->structure)) {
+        found = 1;
+        break;
+      }
+    }
+    for (i=Enc->begin_unpr; !found && i<Enc->end_pr; i++) {
+      if (equals(Enc->unprocessed[i], str->structure)) {
+        found = 1;
+        break;
+      }
+    }
+
+    if (!found) {
+      Enc->unprocessed[Enc->end_unpr]=allocopy(str->structure);
+      Enc->end_unpr++;
+    }
+  }
+
+  /* undo moves*/
+  if (Enc->bp_left2!=0) do_move(str->structure, -Enc->bp_left2, -Enc->bp_right2);
+  do_move(str->structure, -Enc->bp_left, -Enc->bp_right);
+  str->energy = last_en;
+  Enc->bp_left=0;
+  Enc->bp_right=0;
+  Enc->bp_left2=0;
+  Enc->bp_right2=0;
+  return 0;
+}
+
+
+/* deletions move set*/
+int deletions(Encoded *Enc, struct_en *str, struct_en *minim)
+{
+  int cnt = 0;
+  short *pt = str->structure;
+  int len = pt[0];
+  int i;
+
+  for (i=1; i<=len; i++) {
+    if (pt[i]>pt[pt[i]]) {  /* '('*/
+      Enc->bp_left=-i;
+      Enc->bp_right=-pt[i];
+
+      /*if nolp enabled, make (maybe) 2nd delete*/
+      if (Enc->noLP) {
+        int lone = -1;
+        if (lone_base(pt, i-1)) lone=i-1;
+        else if (lone_base(pt, i+1)) lone=i+1;
+        else if (lone_base(pt, pt[i]-1)) lone=pt[i]-1;
+        else if (lone_base(pt, pt[i]+1)) lone=pt[i]+1;
+
+        /* check*/
+        if (lone != -1 && (pt[lone]==0 || pt[pt[lone]]==0)) {
+          fprintf(stderr, "WARNING: pt[%d(or %d)]!=\'.\'", lone, pt[lone]);
+        }
+
+        if (lone != -1) {
+          Enc->bp_left2=-lone-1;
+          Enc->bp_right2=-pt[lone]-1;
+        }
+        if (!lone_base(pt, pt[lone]-1) && !lone_base(pt, pt[lone]+1)) {
+          cnt += update_deepest(Enc, str, minim);
+          /* in case useFirst is on and structure is found, end*/
+          if (Enc->first && cnt > 0) return cnt;
+        }
+      } else {  /* nolp not enabled*/
+        cnt += update_deepest(Enc, str, minim);
+        /* in case useFirst is on and structure is found, end*/
+        if (Enc->first && cnt > 0) return cnt;
+      }
+    }
+  }
+  return cnt;
+}
+
+  /* compatible base pair?*/
+inline bool compat(char a, char b) {
+  if (a=='A' && b=='U') return true;
+  if (a=='C' && b=='G') return true;
+  if (a=='G' && b=='U') return true;
+  if (a=='U' && b=='A') return true;
+  if (a=='G' && b=='C') return true;
+  if (a=='U' && b=='G') return true;
+  /* and with T's*/
+  if (a=='A' && b=='T') return true;
+  if (a=='T' && b=='A') return true;
+  if (a=='G' && b=='T') return true;
+  if (a=='T' && b=='G') return true;
+  return false;
+}
+
+/* try insert base pair (i,j)*/
+inline bool try_insert(const short *pt, const char *seq, int i, int j)
+{
+  if (i<=0 || j<=0 || i>pt[0] || j>pt[0]) return false;
+  return (j-i>MINGAP && pt[j]==0 && pt[i]==0 && compat(seq[i-1], seq[j-1]));
+}
+
+/*  try insert base pair (i,j) */
+inline bool try_insert_seq(const char *seq, int i, int j)
+{
+  if (i<=0 || j<=0) return false;
+  return (j-i>MINGAP && compat(seq[i-1], seq[j-1]));
+}
+
+/* insertions move set*/
+int insertions(Encoded *Enc, struct_en *str, struct_en *minim)
+{
+  int cnt = 0;
+  short *pt = str->structure;
+  int len = pt[0];
+  int i,j;
+
+  for (i=1; i<=len; i++) {
+    if (pt[i]==0) {
+      for (j=i+1; j<=len; j++) {
+        /* end if found closing bracket*/
+        if (pt[j]!=0 && pt[j]<j) break;  /*')'*/
+        if (pt[j]!=0 && pt[j]>j) {       /*'('*/
+          j = pt[j];
+          continue;
+        }
+        /* if conditions are met, do insert*/
+        if (try_insert(pt, Enc->seq, i, j)) {
+          Enc->bp_left=i;
+          Enc->bp_right=j;
+
+          if (Enc->noLP) {
+            /* if lone bases occur, try inserting one another base*/
+            if (lone_base(pt, i) || lone_base(pt, j)) {
+              /* inside*/
+              if (try_insert(pt, Enc->seq, i+1, j-1)) {
+                Enc->bp_left2=i+1;
+                Enc->bp_right2=j-1;
+                cnt += update_deepest(Enc, str, minim);
+                /* in case useFirst is on and structure is found, end*/
+                if (Enc->first && cnt > 0) return cnt;
+              } else  /*outside*/
+              if (try_insert(pt, Enc->seq, i-1, j+1)) {
+                Enc->bp_left2=i-1;
+                Enc->bp_right2=j+1;
+                cnt += update_deepest(Enc, str, minim);
+                /* in case useFirst is on and structure is found, end*/
+                if (Enc->first && cnt > 0) return cnt;
+              }
+            } else {
+              cnt += update_deepest(Enc, str, minim);
+              /* in case useFirst is on and structure is found, end*/
+              if (Enc->first && cnt > 0) return cnt;
+            }
+          } else {
+            cnt += update_deepest(Enc, str, minim);
+            /* in case useFirst is on and structure is found, end*/
+            if (Enc->first && cnt > 0) return cnt;
+          }
+        }
+      }
+    }
+  }
+  return cnt;
+}
+
+/*shift move set*/
+int shifts(Encoded *Enc, struct_en *str, struct_en *minim)
+{
+  int cnt = 0;
+  int brack_num = 0;
+  short *pt = str->structure;
+  int len = pt[0];
+  int i, k;
+
+  for (i=1; i<=len; i++) {
+    if (pt[i]!=0 && pt[i]>i) {  /*'('*/
+      int j=pt[i];
+
+      /* outer switch left*/
+      if (Enc->verbose_lvl>1) fprintf(stderr, "%2d bracket %2d position, outer switch left\n", brack_num+1, i);
+      for (k=i-1; k>0; k--) {
+        if (pt[k]!=0 && pt[k]>k/*'('*/) break;
+        if (pt[k]!=0 && pt[k]<k/*')'*/) {
+          k = pt[k];
+          continue;
+        }
+        /* checks*/
+        if (pt[k]!=0) {
+          fprintf(stderr, "WARNING: \'%c\'should be \'.\' at pos %d!\n", pt[k], k);
+        }
+
+        /* switch (i,j) to (k,j)*/
+        if (j-k>MINGAP && compat(Enc->seq[k-1], Enc->seq[j-1])) {
+          Enc->bp_left=-i;
+          Enc->bp_right=-j;
+          Enc->bp_left2=k;
+          Enc->bp_right2=j;
+          cnt += update_deepest(Enc, str, minim);
+          /* in case useFirst is on and structure is found, end*/
+          if (Enc->first && cnt > 0) return cnt;
+        }
+
+        /* switch (i,j) to (k,i)*/
+        if (i-k>MINGAP && compat(Enc->seq[i-1], Enc->seq[k-1])) {
+          Enc->bp_left=-i;
+          Enc->bp_right=-j;
+          Enc->bp_left2=k;
+          Enc->bp_right2=i;
+          cnt += update_deepest(Enc, str, minim);
+          /* in case useFirst is on and structure is found, end*/
+          if (Enc->first && cnt > 0) return cnt;
+
+        }
+      }
+
+      /* outer switch right*/
+      if (Enc->verbose_lvl>1) fprintf(stderr, "%2d bracket %2d position, outer switch right\n", brack_num+1, i);
+      for (k=j+1; k<=len; k++) {
+        if (pt[k]!=0 && pt[k]<k/*')'*/) break;
+        if (pt[k]!=0 && pt[k]>k/*'('*/) {
+          k = pt[k];
+          continue;
+        }
+
+        /* check*/
+        if (pt[k]!=0) {
+          fprintf(stderr, "WARNING: \'%c\'should be \'.\' at pos %d!\n", pt[k], k);
+        }
+        /* switch (i,j) to (i,k)*/
+        if (k-i>MINGAP && compat(Enc->seq[i-1], Enc->seq[k-1])) {
+          Enc->bp_left=-i;
+          Enc->bp_right=-j;
+          Enc->bp_left2=i;
+          Enc->bp_right2=k;
+          cnt += update_deepest(Enc, str, minim);
+          /* in case useFirst is on and structure is found, end*/
+          if (Enc->first && cnt > 0) return cnt;
+        }
+        /* switch (i,j) to (j,k)*/
+        if (k-j>MINGAP && compat(Enc->seq[j-1], Enc->seq[k-1])) {
+          Enc->bp_left=-i;
+          Enc->bp_right=-j;
+          Enc->bp_left2=j;
+          Enc->bp_right2=k;
+          cnt += update_deepest(Enc, str, minim);
+          /* in case useFirst is on and structure is found, end*/
+          if (Enc->first && cnt > 0) return cnt;
+        }
+      }
+
+      if (Enc->verbose_lvl>1) fprintf(stderr, "%2d bracket %2d position, inner switch\n", brack_num+1, i);
+      /* inner switch*/
+      for (k=i+1; k<j; k++) {
+        /* jump to end of the sub-bracketing*/
+        if (pt[k]!=0 && pt[k]>k/*'('*/) {
+            k=pt[k];
+            continue;
+        }
+
+        /* left switch (i,j) to (k,j)*/
+        if (j-k>MINGAP && compat(Enc->seq[k-1], Enc->seq[j-1])) {
+          Enc->bp_left=-i;
+          Enc->bp_right=-j;
+          Enc->bp_left2=k;
+          Enc->bp_right2=j;
+          cnt += update_deepest(Enc, str, minim);
+          /* in case useFirst is on and structure is found, end*/
+          if (Enc->first && cnt > 0) return cnt;
+        }
+
+        /* right switch (i,j) to (i,k)*/
+        if (k-i>MINGAP && compat(Enc->seq[i-1], Enc->seq[k-1])) {
+          Enc->bp_left=-i;
+          Enc->bp_right=-j;
+          Enc->bp_left2=i;
+          Enc->bp_right2=k;
+          cnt += update_deepest(Enc, str, minim);
+          /* in case useFirst is on and structure is found, end*/
+          if (Enc->first && cnt > 0) return cnt;
+        }
+      } /* end inner switch for*/
+      brack_num++;
+    } /* end if (pt[i]=='(')*/
+  } /* end for in switches*/
+  return cnt;
+}
+
+/* move to deepest (or first) neighbour*/
+int move_set(Encoded *Enc, struct_en *str)
+{
+  /* count how many times called*/
+  cnt_move++;
+
+  /* count better neighbours*/
+  int cnt = 0;
+
+  /* deepest descent*/
+  struct_en min;
+  min.structure = allocopy(str->structure);
+  min.energy = str->energy;
+  Enc->current_en = str->energy;
+
+  if (Enc->verbose_lvl>0) { fprintf(stderr, "  start of MS:\n  "); print_str(stderr, str->structure); fprintf(stderr, " %d\n\n", str->energy); }
+
+  /* if using first dont do all of them*/
+  bool end = false;
+  /* insertions*/
+  if (!end) cnt += insertions(Enc, str, &min);
+  if (Enc->first && cnt>0) end = true;
+  if (Enc->verbose_lvl>1) fprintf(stderr, "\n");
+
+  /* deletions*/
+  if (!end) cnt += deletions(Enc, str, &min);
+  if (Enc->first && cnt>0) end = true;
+
+  /* shifts (only if enabled + noLP disabled)*/
+  if (!end && Enc->shift && !Enc->noLP) {
+    cnt += shifts(Enc, str, &min);
+    if (Enc->first && cnt>0) end = true;
+  }
+
+  /* if degeneracy occurs, solve it!*/
+  if (!end && (Enc->end_unpr - Enc->begin_unpr)>0) {
+    Enc->processed[Enc->end_pr] = str->structure;
+    Enc->end_pr++;
+    str->structure = Enc->unprocessed[Enc->begin_unpr];
+    Enc->unprocessed[Enc->begin_unpr]=NULL;
+    Enc->begin_unpr++;
+    cnt += move_set(Enc, str);
+  } else {
+    /* write output to str*/
+    copy_arr(str->structure, min.structure);
+    str->energy = min.energy;
+  }
+  /* release minimal*/
+  free(min.structure);
+
+  /* resolve degeneracy in local minima*/
+  if ((Enc->end_pr - Enc->begin_pr)>0) {
+    Enc->processed[Enc->end_pr]=str->structure;
+    Enc->end_pr++;
+
+    int min = find_min(Enc->processed, Enc->begin_pr, Enc->end_pr);
+    short *tmp = Enc->processed[min];
+    Enc->processed[min] = Enc->processed[Enc->begin_pr];
+    Enc->processed[Enc->begin_pr] = tmp;
+    str->structure = Enc->processed[Enc->begin_pr];
+    Enc->begin_pr++;
+    free_degen(Enc);
+  }
+
+  if (Enc->verbose_lvl>1 && !(Enc->first)) { fprintf(stderr, "\n  end of MS:\n  "); print_str(stderr, str->structure); fprintf(stderr, " %d\n\n", str->energy); }
+
+  return cnt;
+}
+
+void construct_moves(Encoded *Enc, short *structure)
+{
+  /* generate all possible moves (less than n^2)*/
+  Enc->num_moves = 0;
+  int i;
+  for (i=1; i<=structure[0]; i++) {
+    if (structure[i]!=0) {
+      if (structure[i]<i) continue;
+      Enc->moves_from[Enc->num_moves]=-i;
+      Enc->moves_to[Enc->num_moves]=-structure[i];
+      Enc->num_moves++;
+      /* fprintf(stderr, "add  d(%d, %d)\n", i, str.structure[i]); */
+    } else {
+      int j;
+      for (j=i+1; j<=structure[0]; j++) {
+        /* fprintf(stderr, "check (%d, %d)\n", i, j); */
+        if (structure[j]==0) {
+          if (try_insert_seq(Enc->seq,i,j)) {
+            Enc->moves_from[Enc->num_moves]=i;
+            Enc->moves_to[Enc->num_moves]=j;
+            Enc->num_moves++;
+            /* fprintf(stderr, "add  i(%d, %d)\n", i, j); */
+            continue;
+          }
+        } else if (structure[j]>j) { /*  '(' */
+          j = structure[j];
+        } else break;
+      }
+    }
+  }
+
+  /* permute them */
+  for (i=0; i<Enc->num_moves-1; i++) {
+    int rnd = rand();
+    rnd = rnd % (Enc->num_moves-i) + i;
+    int swp;
+    swp = Enc->moves_from[i];
+    Enc->moves_from[i]=Enc->moves_from[rnd];
+    Enc->moves_from[rnd]=swp;
+    swp = Enc->moves_to[i];
+    Enc->moves_to[i]=Enc->moves_to[rnd];
+    Enc->moves_to[rnd]=swp;
+  }
+}
+
+int move_rset(Encoded *Enc, struct_en *str)
+{
+  /* count how many times called*/
+  cnt_move++;
+
+  /* count better neighbours*/
+  int cnt = 0;
+
+  /* deepest descent*/
+  struct_en min;
+  min.structure = allocopy(str->structure);
+  min.energy = str->energy;
+  Enc->current_en = str->energy;
+
+  if (Enc->verbose_lvl>0) { fprintf(stderr, "  start of MR:\n  "); print_str(stderr, str->structure); fprintf(stderr, " %d\n\n", str->energy); }
+
+  /*  construct and permute possible moves */
+  construct_moves(Enc, str->structure);
+
+  /* find first lower one*/
+  int i;
+  for (i=0; i<Enc->num_moves; i++) {
+    Enc->bp_left = Enc->moves_from[i];
+    Enc->bp_right = Enc->moves_to[i];
+    cnt = update_deepest(Enc, str, &min);
+    if (cnt) break;
+  }
+
+  /* if degeneracy occurs, solve it!*/
+  if (!cnt && (Enc->end_unpr - Enc->begin_unpr)>0) {
+    Enc->processed[Enc->end_pr] = str->structure;
+    Enc->end_pr++;
+    str->structure = Enc->unprocessed[Enc->begin_unpr];
+    Enc->unprocessed[Enc->begin_unpr]=NULL;
+    Enc->begin_unpr++;
+    cnt += move_rset(Enc, str);
+  } else {
+    /* write output to str*/
+    copy_arr(str->structure, min.structure);
+    str->energy = min.energy;
+  }
+  /* release minimal*/
+  free(min.structure);
+
+  /* resolve degeneracy in local minima*/
+  if ((Enc->end_pr - Enc->begin_pr)>0) {
+    Enc->processed[Enc->end_pr]=str->structure;
+    Enc->end_pr++;
+
+    int min = find_min(Enc->processed, Enc->begin_pr, Enc->end_pr);
+    short *tmp = Enc->processed[min];
+    Enc->processed[min] = Enc->processed[Enc->begin_pr];
+    Enc->processed[Enc->begin_pr] = tmp;
+    str->structure = Enc->processed[Enc->begin_pr];
+    Enc->begin_pr++;
+    free_degen(Enc);
+  }
+
+  return cnt;
+}
+
+/*check if base is lone*/
+int lone_base(short *pt, int i)
+{
+  if (i<=0 || i>pt[0]) return 0;
+  /* is not a base pair*/
+  if (pt[i]==0) return 0;
+
+  /* base is lone:*/
+  if (i-1>0) {
+    /* is base pair and is the same bracket*/
+    if (pt[i-1]!=0 && ((pt[i-1]<pt[pt[i-1]]) == (pt[i]<pt[pt[i]]))) return 0;
+  }
+
+  if (i+1<=pt[0]) {
+    if (pt[i+1]!=0 && ((pt[i-1]<pt[pt[i-1]]) == (pt[i]<pt[pt[i]]))) return 0;
+  }
+
+  return 1;
+}
+
+/* if the structure has lone pairs*/
+int find_lone_pair(short* str)
+{
+  int i;
+  for(i=1; i<str[0]; i++) {
+    if (str[i]==0) continue; /* '.'*/
+
+    if (str[i]>str[str[i]]) {  /* '('*/
+      if (i+1==str[0] || str[i+1]==0 || str[i+1]<str[str[i+1]]) {
+        return i;
+      } else while (i+1!=str[0] && str[i+1]!=0 && str[i+1]>str[str[i+1]]) i++;
+    }
+
+    if (str[i]<str[str[i]]) {  /* ')'*/
+      if (i+1==str[0] || str[i+1]==0 || str[i+1]>str[str[i+1]]) {
+        return i;
+      } else while (i+1!=str[0] && str[i+1]!=0 && str[i+1]<str[str[i+1]]) i++;
+    }
+  }
+
+  return -1;
+}
+
+
+int move_deepest( char *string,
+                  short *ptable,
+                  short *s,
+                  short *s1,
+                  int verbosity_level,
+                  int shifts,
+                  int noLP)
+{
+  cnt_move = 0;
+
+  Encoded enc;
+  enc.seq = string;
+  enc.s0 = s;
+  enc.s1 = s1;
+
+  /* moves*/
+  enc.bp_left=0;
+  enc.bp_right=0;
+  enc.bp_left2=0;
+  enc.bp_right2=0;
+
+  /* options*/
+  enc.noLP=noLP;
+  enc.verbose_lvl=verbosity_level;
+  enc.first=0;
+  enc.shift=shifts;
+
+  /* degeneracy*/
+  enc.begin_unpr=0;
+  enc.begin_pr=0;
+  enc.end_unpr=0;
+  enc.end_pr=0;
+  enc.current_en=0;
+
+  /*  function */
+  enc.funct=NULL;
+
+  int i;
+  for (i=0; i<MAX_DEGEN; i++) enc.processed[i]=enc.unprocessed[i]=NULL;
+
+  struct_en str;
+  str.structure = allocopy(ptable);
+  str.energy = energy_of_structure_pt(enc.seq, str.structure, enc.s0, enc.s1, 0);
+
+  while (move_set(&enc, &str)!=0) {
+    free_degen(&enc);
+  }
+  free_degen(&enc);
+
+  copy_arr(ptable, str.structure);
+  free(str.structure);
+
+  return str.energy;
+}
+
+int move_first(   char *string,
+                  short *ptable,
+                  short *s,
+                  short *s1,
+                  int verbosity_level,
+                  int shifts,
+                  int noLP)
+{
+  cnt_move = 0;
+
+  Encoded enc;
+  enc.seq = string;
+  enc.s0 = s;
+  enc.s1 = s1;
+
+  /* moves*/
+  enc.bp_left=0;
+  enc.bp_right=0;
+  enc.bp_left2=0;
+  enc.bp_right2=0;
+
+  /* options*/
+  enc.noLP=noLP;
+  enc.verbose_lvl=verbosity_level;
+  enc.first=1;
+  enc.shift=shifts;
+
+  /* degeneracy*/
+  enc.begin_unpr=0;
+  enc.begin_pr=0;
+  enc.end_unpr=0;
+  enc.end_pr=0;
+  enc.current_en=0;
+
+  /*  function */
+  enc.funct=NULL;
+
+  int i;
+  for (i=0; i<MAX_DEGEN; i++) enc.processed[i]=enc.unprocessed[i]=NULL;
+
+  struct_en str;
+  str.structure = allocopy(ptable);
+  str.energy = energy_of_structure_pt(enc.seq, str.structure, enc.s0, enc.s1, 0);
+
+  while (move_set(&enc, &str)!=0) {
+    free_degen(&enc);
+  }
+  free_degen(&enc);
+
+  copy_arr(ptable, str.structure);
+  free(str.structure);
+
+  return str.energy;
+}
+
+int move_rand(   char *string,
+                  short *ptable,
+                  short *s,
+                  short *s1,
+                  int verbosity_level)
+{
+  srand(time(NULL));
+
+  cnt_move = 0;
+
+  Encoded enc;
+  enc.seq = string;
+  enc.s0 = s;
+  enc.s1 = s1;
+
+  /* moves*/
+  enc.bp_left=0;
+  enc.bp_right=0;
+  enc.bp_left2=0;
+  enc.bp_right2=0;
+
+  /* options*/
+  enc.noLP=0;
+  enc.verbose_lvl=verbosity_level;
+  enc.first=1;
+  enc.shift=0;
+
+  /* degeneracy*/
+  enc.begin_unpr=0;
+  enc.begin_pr=0;
+  enc.end_unpr=0;
+  enc.end_pr=0;
+  enc.current_en=0;
+
+  /*  function */
+  enc.funct=NULL;
+
+  /*  allocate memory for moves */
+  enc.moves_from = (int*) space(ptable[0]*ptable[0]*sizeof(int));
+  enc.moves_to = (int*) space(ptable[0]*ptable[0]*sizeof(int));
+
+  int i;
+  for (i=0; i<MAX_DEGEN; i++) enc.processed[i]=enc.unprocessed[i]=NULL;
+
+  struct_en str;
+  str.structure = allocopy(ptable);
+  str.energy = energy_of_structure_pt(enc.seq, str.structure, enc.s0, enc.s1, 0);
+
+  while (move_rset(&enc, &str)!=0) {
+    free_degen(&enc);
+  }
+  free_degen(&enc);
+
+  copy_arr(ptable, str.structure);
+  free(str.structure);
+  free(enc.moves_from);
+  free(enc.moves_to);
+
+  return str.energy;
+}
+
+int browse_neighs(   char *string,
+                  short *ptable,
+                  short *s,
+                  short *s1,
+                  int verbosity_level,
+                  int shifts,
+                  int noLP,
+                  int (*funct) (struct_en*, struct_en*))
+{
+  cnt_move = 0;
+
+  Encoded enc;
+  enc.seq = string;
+  enc.s0 = s;
+  enc.s1 = s1;
+
+  /* moves*/
+  enc.bp_left=0;
+  enc.bp_right=0;
+  enc.bp_left2=0;
+  enc.bp_right2=0;
+
+  /* options*/
+  enc.noLP=noLP;
+  enc.verbose_lvl=verbosity_level;
+  enc.first=1;
+  enc.shift=shifts;
+
+  /* degeneracy*/
+  enc.begin_unpr=0;
+  enc.begin_pr=0;
+  enc.end_unpr=0;
+  enc.end_pr=0;
+  enc.current_en=0;
+
+  /*  function */
+  enc.funct=funct;
+
+  int i;
+  for (i=0; i<MAX_DEGEN; i++) enc.processed[i]=enc.unprocessed[i]=NULL;
+
+  struct_en str;
+  str.structure = allocopy(ptable);
+  str.energy = energy_of_structure_pt(enc.seq, str.structure, enc.s0, enc.s1, 0);
+
+  move_set(&enc, &str);
+  free_degen(&enc);
+
+  copy_arr(ptable, str.structure);
+  free(str.structure);
+
+  return str.energy;
+}
+
+/* printf*/
+void print_stren(FILE *out, struct_en *str) {
+  print_str(out, str->structure);
+  fprintf(out, " %6.2f\n", str->energy/100.0);
+}
+
+void print_str(FILE *out, short *str) {
+  int i;
+  for (i=1; i<=str[0]; i++) {
+    if (str[i]==0) fprintf(out, ".");
+    else if (str[i]<i) fprintf(out, ")");
+    else fprintf(out, "(");
+  }
+}
+
+