WSTester updated to work plus hopefully all the other changes that need to go into...
[jabaws.git] / binaries / src / ViennaRNA / Kinfold / nachbar.c
diff --git a/binaries/src/ViennaRNA/Kinfold/nachbar.c b/binaries/src/ViennaRNA/Kinfold/nachbar.c
new file mode 100644 (file)
index 0000000..fdde369
--- /dev/null
@@ -0,0 +1,440 @@
+/*
+  Last changed Time-stamp: <2011-03-10 18:02:10 ivo>
+  c  Christoph Flamm and Ivo L Hofacker
+  {xtof,ivo}@tbi.univie.ac.at
+  Kinfold: $Name:  $
+  $Id: nachbar.c,v 1.8 2008/06/03 21:55:11 ivo Exp $
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include "globals.h"
+#include "assert.h"
+#include "fold_vars.h"
+#include "energy_const.h"
+#include "utils.h"
+#include "cache_util.h"
+#include "baum.h"
+
+static char UNUSED rcsid[]="$Id: nachbar.c,v 1.8 2008/06/03 21:55:11 ivo Exp $";
+
+/* arrays */
+static short *neighbor_list=NULL;
+static float *bmf=NULL; /* boltzmann weight of structure */
+static const char *costring(const char *str);
+
+/* globals for laplace stuff */
+static double L = 0.0;
+static double D = 0.0;
+static double sumT = 0.0;
+static double sumK = 0.0;
+static double sumKK = 0.0;
+static double sumD = 0.0;
+static double *energies=NULL; /* energies of neighbors */
+
+/* variables */
+/*  static double highestE = -1000.0; */
+/*  static double OhighestE = -1000.0; */
+/*  static char *highestS, *OhighestS; */
+static int lmin = 1;
+static int top = 0;
+static int is_from_cache = 0;
+/*  static double meanE = 0.0; */
+static double totalflux = 0.0;
+static double Zeit = 0.0;
+static double zeitInc = 0.0;
+static double _RT = 0.6;
+
+/* public functiones */
+void ini_nbList(int chords);
+void update_nbList(int i, int j, int iE);
+int sel_nb(void);
+void clean_up_nbList(void);
+extern void update_tree(int i, int j);
+
+/* privat functiones */
+static void reset_nbList(void);
+static void grow_chain(void);
+static FILE *logFP=NULL;
+
+/**/
+void ini_nbList(int chords) {
+  char logFN[256];
+
+  _RT = (((temperature + K0) * GASCONST) / 1000.0);
+  if (neighbor_list!=NULL) return;
+  /*
+    list for move coding
+    make room for 2*chords neighbors (safe bet)
+  */
+  if (chords == 0) chords = 1;
+  neighbor_list = (short *)calloc(4*chords, sizeof(short));
+  assert(neighbor_list != NULL);
+  /*
+    list for Boltzmann-factors
+  */
+  bmf = (float *)calloc(2*chords, sizeof(double));
+  assert(bmf != NULL);
+
+  /* list of neighbor energies */
+  energies = (double*)calloc(2*chords, sizeof(double));
+  assert(energies != NULL);
+  
+  /* open log-file */
+  logFP = fopen(strcat(strcpy(logFN, GAV.BaseName), ".log"), "a+");
+  assert(logFP != NULL);
+
+  /* log initial condition */
+  log_prog_params(logFP);
+  log_start_stop(logFP);
+}
+
+/**/
+void update_nbList(int i, int j, int iE) {
+  double E, dE, p;
+
+  E = (double)iE/100.;
+  neighbor_list[2*top] = (short )i;
+  neighbor_list[2*top+1] = (short )j;
+  
+  /* compute rates and some statistics */
+  /*    meanE += E; */
+  dE = E-GSV.currE;
+
+  /* laplace stuff */
+  energies[top] = E;
+  L += GSV.currE-E;
+  D++;
+  /* fprintf(stderr, ">>%g %g<<\n", L, D); */
+  
+  if( GTV.mc ) {
+    /* metropolis rule */
+    if (dE < 0) p = 1;
+    else p = exp(-(dE / _RT*GSV.phi));
+  }
+  else  /* kawasaki rule */
+    p = exp(-0.5 * (dE / _RT*GSV.phi));
+
+  totalflux += p;
+  bmf[top++] = (float )p;
+  if (dE < 0) lmin = 0;
+  if ((dE == 0) && (lmin==1)) lmin = 2;
+}
+
+/**/
+void get_from_cache(cache_entry *c) {
+  top = c->top;
+  totalflux = c->flux;
+  GSV.currE = c->energy;
+  lmin = c->lmin;
+  memcpy(neighbor_list, c->neighbors, 2*top*sizeof(short));
+  memcpy(bmf, c->rates, top*sizeof(float));
+  memcpy(energies, c->energies, top*sizeof(double));
+  is_from_cache = 1;
+}
+
+/**/
+void put_in_cache(void) {
+  cache_entry *c;
+
+  if ((c = (cache_entry *) malloc(sizeof(cache_entry)))==NULL) {
+    fprintf(stderr, "out of memory\n"); exit(255);
+  }
+/*    c->structure = strdup(GAV.currform); */
+  c->structure = (char *) calloc(GSV.len+1, sizeof(char));
+  strcpy(c->structure, GAV.currform);
+  c->neighbors = (short *) malloc(top*2*sizeof(short));
+  memcpy(c->neighbors,neighbor_list,top*2*sizeof(short));
+  c->rates = (float *) malloc(top*sizeof(float));
+  memcpy(c->rates, bmf, top*sizeof(float));
+  c->energies = (double*)malloc(top*sizeof(double));
+  memcpy(c->energies, energies, top*sizeof(double));
+  c->top = top;
+  c->lmin = lmin;
+  c->flux = totalflux;
+  c->energy = GSV.currE;
+  write_cache(c);
+}
+
+/*============*/
+
+int sel_nb(void) {
+
+  char trans, **s;
+  int next, i;
+  double pegel = 0.0, schwelle = 0.0, zufall = 0.0;
+  int found_stop=0;
+
+  /* before we select a move, store current conformation in cache */
+  /* ... unless it just came from there */
+  if ( !is_from_cache ) put_in_cache();
+  else
+    /* laplace stuff */
+    for (i=0; i<top; i++) {
+      L += (GSV.currE - energies[i]);
+      D++;
+    }
+  is_from_cache = 0;
+
+  /* draw 2 different a random number */
+  schwelle = urn();
+  while ( zufall==0 ) zufall = urn();
+
+  /* advance internal clock */
+  if (totalflux>0)
+    zeitInc = (log(1. / zufall) / totalflux);
+  else {
+    if (GSV.grow>0) zeitInc=GSV.grow;
+    else zeitInc = GSV.time;
+  }
+
+  Zeit += zeitInc;
+
+  /* laplace stuff */
+  sumK  += L*zeitInc;
+  sumKK += L*L*zeitInc;
+  sumD  += D*zeitInc;
+  
+  if (GSV.grow>0 && GSV.len < strlen(GAV.farbe_full)) grow_chain();
+
+  /* meanE /= (double)top; */
+
+  /* normalize boltzmann weights */
+  schwelle *=totalflux;
+
+  /* and choose a neighbour structure next */
+  for (next = 0; next < top; next++) {
+    pegel += bmf[next];
+    if (pegel > schwelle) break;
+  }
+
+  /* in case of rounding errors */
+  if (next==top) next=top-1;
+
+  /*
+    process termination contitiones
+  */
+  /* is current structure identical to a stop structure ?*/
+  for (found_stop = 0, s = GAV.stopform; *s; s++) {
+    if (strcmp(*s, GAV.currform) == 0) {
+      found_stop = (s - GAV.stopform) + 1;
+      break;
+    }
+  }
+
+  if ( ((found_stop > 0) && (GTV.fpt == 1)) || (Zeit > GSV.time) ) {
+    /* met condition to stop simulation */
+
+    /* laplace stuff */
+    double K, KK, N, sigma;
+    K = sumK/Zeit;
+    KK = sumKK/Zeit;
+    N = sumD/Zeit;
+    /* graph Laplacian is - Laplace-Beltrami operator */
+    sigma = -1.0*sqrt((KK-K*K)/N)/(K/N);
+    
+    /* this goes to stdout */
+    if ( !GTV.silent ) {
+      printf("%s %6.2f %10.3f", costring(GAV.currform), GSV.currE, Zeit);
+
+      /* laplace stuff*/
+      if (GTV.phi) printf(" %8.3f %8.3f %3g", zeitInc, L, D); 
+
+      if (GTV.verbose) printf(" %4d _ %d", top, lmin);
+      if (found_stop) printf(" X%d\n", found_stop);/* found a stop structure */
+      else printf(" O\n"); /* time for simulation is exceeded */
+
+      /* laplace stuff */
+      if (GTV.phi) printf("Curvature fluctuation sigma = %7.5f\n", sigma);
+
+      fflush(stdout);
+    }
+
+    /* this goes to log */
+    /* comment log steps of simulation as well !!! %6.2f  round */
+    if ( found_stop ) {
+      fprintf(logFP," X%02d %12.3f", found_stop, Zeit);
+
+      /* laplace stuff */
+      if (GTV.phi) fprintf(logFP, " %3g %7.5f", GSV.phi, sigma);
+
+      fprintf(logFP,"\n");
+    }
+    else {
+      fprintf(logFP," O   %12.3f", Zeit);
+
+      /* laplace stuff */
+      if (GTV.phi) fprintf(logFP, " %3g %7.5f", GSV.phi, sigma);      
+
+      fprintf(logFP," %d %s\n", lmin, costring(GAV.currform));
+    }
+    GAV.subi[0] = xsubi[0];
+    GAV.subi[1] = xsubi[1];
+    GAV.subi[2] = xsubi[2];
+    fprintf(logFP, "(%5hu %5hu %5hu)", GAV.subi[0], GAV.subi[1], GAV.subi[2]);
+    fflush(logFP);
+    
+    Zeit = 0.0;
+
+    /* reset laplace stuff for next trajectory */
+    sumT = 0.0;
+    sumK = 0.0;
+    sumKK = 0.0;
+    sumD = 0.0;
+    L = 0.0;
+    D = 0.0;
+    
+    /*  highestE = OhighestE = -1000.0; */
+    reset_nbList();
+    costring(NULL);
+    return(1);
+  }
+  else {
+    /* continue simulation */
+    int flag = 0;
+    if( (!GTV.silent) && (GSV.currE <= GSV.stopE+GSV.cut) ) {
+
+      if (!GTV.lmin || (lmin==1 && strcmp(GAV.prevform, GAV.currform) != 0)) {
+       char format[64];
+       flag = 1;
+       sprintf(format, "%%-%ds %%6.2f %%10.3f", strlen(GAV.farbe_full)+1);
+       printf(format, costring(GAV.currform), GSV.currE, Zeit);
+      }
+
+      /* laplace stuff */
+      if (GTV.phi) {
+       printf(" %8.3f %8.3f %3g", zeitInc, L, D);
+       L = D = 0.0; /* reset L and D for next structure */
+      }
+
+      if ( flag && GTV.verbose ) {
+       int ii, jj;
+       if (next<0) trans='g'; /* growth */
+       else {
+         ii = neighbor_list[2*next];
+         jj = neighbor_list[2*next+1];
+         if (abs(ii) < GSV.len) {
+           if ((ii > 0) && (jj > 0)) trans = 'i';
+           else if ((ii < 0) && (jj < 0)) trans = 'd';
+           else if ((ii > 0) && (jj < 0)) trans = 's';
+           else trans = 'S';
+         } else {
+           if ((ii > 0) && (jj > 0)) trans = 'I';
+           else trans = 'D';
+         }
+       }
+       printf(" %4d %c %d", top, trans, lmin);
+      }
+      if (flag) printf("\n");
+    }
+  }
+
+
+  /* store last lmin seen, so we can avoid printing the same lmin twice */
+  if (lmin==1)
+    strcpy(GAV.prevform, GAV.currform);
+
+#if 0
+  if (lmin==1) {
+    /* went back to previous lmin */
+    if (strcmp(GAV.prevform, GAV.currform) == 0) {
+      if (OhighestE < highestE) {
+       highestE = OhighestE;  /* delete loop */
+       strcpy(highestS, OhighestS);
+      }
+    } else {
+      strcpy(GAV.prevform, GAV.currform);
+      OhighestE = 10000.;
+    }
+  }
+
+  if ( strcmp(GAV.currform, GAV.startform)==0 ) {
+    OhighestE = highestE = -1000.;
+    highestS[0] = 0;
+  }
+
+  /* log highes energy */
+  if (GSV.currE > highestE) {
+    OhighestE = highestE;
+    highestE = GSV.currE;
+    strcpy(OhighestS, highestS);
+    strcpy(highestS, GAV.currform);
+  }
+#endif
+
+  if (next>=0) update_tree(neighbor_list[2*next], neighbor_list[2*next+1]);
+  else {
+    clean_up_rl(); ini_or_reset_rl();
+  }
+
+  reset_nbList();
+  return(0);
+}
+
+/*==========================*/
+static void reset_nbList(void) {
+
+  top = 0;
+  totalflux = 0.0;
+  /*    meanE = 0.0; */
+  lmin = 1;
+}
+
+/*======================*/
+void clean_up_nbList(void){
+
+  free(neighbor_list);
+  free(bmf);
+  free(energies);
+  fprintf(logFP,"\n");
+  fclose(logFP);
+}
+
+/*======================*/
+static void grow_chain(void){
+  int newl;
+  /* note Zeit=0 corresponds to chain length GSV.glen */
+  if (Zeit<(GSV.len+1-GSV.glen) * GSV.grow) return;
+  newl = GSV.len+1;
+  Zeit = (newl-GSV.glen) * GSV.grow;
+  top=0; /* prevent structure move in sel_nb */
+
+  if (GSV.len<newl) {
+    strncpy(GAV.farbe, GAV.farbe_full, newl);
+    GAV.farbe[newl] = '\0';
+    strcpy(GAV.startform, GAV.currform);
+    strcat(GAV.startform, ".");
+
+    GSV.len = newl;
+  }
+}
+
+static const char *costring(const char *str) {
+  static char* buffer=NULL;
+  static int size=0;
+  int n;
+  if (str==NULL) {
+    if (buffer) {
+      /* make it possible to free buffer */
+      free(buffer);
+      size = 0; buffer = NULL;
+    }
+    return NULL;
+  }
+  n=strlen(str);
+  if (n>=size) {
+    size = n+2;
+    buffer = realloc(buffer, size);
+  }
+  if ((cut_point>0)&&(cut_point<=n)) {
+    strncpy(buffer, str, cut_point-1);
+    buffer[cut_point-1] = '&';
+    strncpy(buffer+cut_point, str+cut_point-1, n-cut_point+1);
+    buffer[n+1] = '\0';
+  } else {
+    strncpy(buffer, str, n+1);
+  }
+  return buffer;
+}