⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spy.c

📁 sp组合优化算法的一个改进算法
💻 C
字号:
/*    Copyright 2004 Demian Battaglia, Alfredo Braunstein, Michal Kolar,    Michele Leone, Marc Mezard, Martin Weigt and Riccardo Zecchina    This file is part of SPY (Survey Propagation with finite Y).    SPY is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    SPY is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with SP; if not, write to the Free Software    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*/#include <stdlib.h>#include <stdio.h>#include <math.h>#include <string.h>#include <time.h>#include <unistd.h>#include "random.h"#include "formula.h"#include "spy.h"#include "bk.h"//global system vars & structuresstruct vstruct *v = NULL;           //all per var informationstruct clausestruct *clause = NULL; //all per clause informationdouble *magn = NULL;                //spin magnetization list                                     //(for fixing ordering)int *perm = NULL;                   //permutation, for update orderingint M = 0;                          //number of clausesint N = 0;                          //number of variablesint maxlit = 0;                     //maximum clause sizeint freespin;                       //number of unfixed variablesdouble epsilon = EPSILONDEF;        //convergence criterionint maxconn = 0;                    //maximum connectivitydouble y = 2;                      //the temperature 20 = infinityint update_rate = UPDATE_RATE;      //update rate for Y-updatingdouble *hsurvey_store, *oldhsurvey_store; //for compute_fielddouble r = 0.0;                     //fraction of backtrack movesFILE *out_file;//auxiliary varsint *list = NULL;double *prod = NULL;//flags & optionsdouble percent = 0;int fixperstep = 1;int ndanger = 0;int generate = 0;int verbose = 0;int fields = 0;int etas = 0;int stop = 0;FILE *replay = NULL;char *load = NULL;int iterations = ITERATIONS;int K = 3;int ygraph = 0;           //evolving optimal pseudo-temperatureint ave_field = 0;        //computing integrated h-pdf's or average fieldsextern double expym;int main(int argc, char ** argv){  int oldfreespin;    //open output file  if ((out_file = fopen(OUT_FILE, "w")) == NULL) {    fprintf(stderr, "Cannot open output file\n");    exit(-1);  }  //parse command line and set the verbosity of output messages  parsecommandline(argc, argv);  set_verbosity();  //read or generate a formula  if (generate) {    randomformula(K);  } else if (load) {    readvarformula(load);  } else {    fprintf(out_file, "Error:\n"	              "you must specify some formula (-l or -n & -a)\n");    return 0;  }    //define fixperstep if based on percent  if (percent)    fixperstep = N * percent / 100.0;    //allocate mem for dynamics  initmem();    //write the formula  writeformula(fopen(FORMULA, "w+"));  expy(y);    //Compute the exponentials of pseudotemperature     //pick an initial starting point for the dynamics  randomize_eta();    //converge and fix fixperstep spins at a time  fprintf(stderr, "\nSPY Running, the program stores all data to output %s.\n",	  ( !replay ? "file" : "and replay files" ) );  while (converge_crossroads()) {    oldfreespin = freespin;        //decide to backtrack or not     to_b_or_not_to_b();        if (fields) print_fields();    if (etas) print_eta();    if (stop) return 0;        if (!freespin) {      close_computation();      fprintf(out_file, "Finished.\n");      fclose(out_file);      return 0;    }  }  fclose(out_file);  return -1;}void set_verbosity(void)      //Set appropriately the verbosity level{  if (verbose >= 2)    if (!replay) replay = fopen(REPLAY,"w+");  if (verbose >= 3)    fields = 1;  if (verbose >= 4)    etas = 1;  return;}int parsecommandline(int argc, char **argv)     //get command line parameters{  double alpha = 0;  char c;  generate = 0;  usrand(1);    while ((c = getopt(argc, argv, "HB:k:N:M:Rn:m:a:s:hf:vy:Yu:%:e:l:FE/i:")) != -1) {    switch (c) {    case 'H':      ave_field = 1;      break;    case 'B':      r = atof(optarg);      break;    case 'l':      load = optarg;      break;    case 'R':      replay = fopen(REPLAY,"w+");      break;    case 'N':    case 'n':      N = atoi(optarg);      break;    case 'M':    case 'm':      M = atoi(optarg);      break;    case 'a':      alpha = atof(optarg);      break;    case 'e':      epsilon = atof(optarg);      break;    case 's':      usrand(atoi(optarg));      srand(atoi(optarg));      break;    case '/':      stop = 1;      break;    case 'k':    case 'K':      K = atoi(optarg);      break;    case 'v':      verbose++;      break;    case 'F':      fields = 1;      break;    case 'E':      etas = 1;      break;    case 'f':      fixperstep = atoi(optarg);      break;    case '%':      percent = atof(optarg);      break;    case 'i':      iterations = atoi(optarg);      break;    case 'y':                         //finite pseudo-temperature      y = atof(optarg);      fprintf(out_file, "--------------------------------------------------------\n");      fprintf(out_file, "Using finite inverse pseudo-temperature y = %1.2f.\n", y);      fprintf(out_file, "--------------------------------------------------------\n");      fprintf(out_file, "\n\n");      break;    case 'Y':      ygraph = 1;      fprintf(out_file, "-------------------------------------------------\n");      fprintf(out_file, "Using optimized finite inverse pseudo-temperature\n");      fprintf(out_file, "-------------------------------------------------\n");           break;    case 'u':      update_rate = atoi(optarg);      break;    case 'h':    case '?':    default :      fprintf(stderr, "%s [options]\n"	      "\n"	      "  FORMULA\n"	      "\t-n <numvars>\n"	      "\t-m <numclauses>\n"	      "\t-a <alpha>\n"	      "\t-l <filename>\t reads formula from file\n"	      "  SOLVING\n"	      "\t-B <rate> \t backtrack with rate <rate>\n"	      "\t-f <fixes>\t per step\n"	      "\t-%% <fixes>\t per step (%%)\n"	      "\t-e <error>\t criterion for convergence\n"	      "\t-i <iter>\t maximum number of iterations until convergence\n"	      "\t-y <y>\t\t set the inverse pseudo-temperature to y\n"              "\t-Y \t\t run with runtime optimized pseudo-temperature\n"	      "\t-u <u>\t\t the update rate for Y is set to <u>\n"	      "\t-H \t\t rank the variables according to the average local field value\n"	      "  STATS\n"	      "\t-R \t\t replay file\n"	      "\t-F \t\t print fields\n"	      "\t-E \t\t print u-surveys\n"	      "\t-v \t\t increase verbosity (0 to 4)\n"	      "  MISC\n"	      "\t-s <seed>\t (0 = use time, default = 1)\n"	      "\t-/\t\t stop after first convergence\n"	      "\t-h\t\t this help\n\nMore help in README file.\n",argv[0]);      exit(-1);    }  }	  if (load && !N && !M && !alpha) {    generate = 0;  } else if (N && alpha && !M) {    M = N * alpha;    generate = 1;  } else if (M && alpha && !N) {    N = M / alpha;    generate = 1;  } else if (M && N && alpha == 0) {    generate = 1;  } else {    fprintf(stderr, "Error:\n"	    "you have to specify exactly TWO of -n,-m and -a,\n"	    "or -l FILE (and then a formula is read from FILE)\n"            "Parameter -h calls help.\n");    exit(-1);  }  return 0;}int order(void const *a, void const *b)     //order relation for qsort, uses ranking in magn[]{  double aux;  aux = magn[*((int *)b)] - magn[*((int *)a)];  return aux < 0 ? -1 : (aux > 0 ? 1 : 0);}double index_biased(struct weightstruct H)     //most biased ranking{  return fabs(H.p - H.m);}double index_pap(struct weightstruct H)     //most biased with some fuss{  return fabs(H.p - H.m) + randreal() * 0.1;}double index_para(struct weightstruct H)     //least paramagnetic ranking{  return H.z;}double index_frozen(struct weightstruct H)     //most paramagnetic ranking{  return -H.z;}double index_best(struct weightstruct H)     //min(H.p,H.m) ranking{  return -(H.p > H.m ? H.m : H.p);}int to_b_or_not_to_b(void)     //Does backtracking or decimation{    if (randreal() < r) {    build_list(1, index_biased); //index_biased is not used, actually    unfix_chunk(fixperstep);  } else {    build_list(0, index_biased);    fix_chunk(fixperstep);   }  return 0;}int build_list(int backtrack, double (* index)(struct weightstruct))     //build an ordered list with order *index which is one of index_?{  int var, totsites;  struct weightstruct H;  double summag;  double maxmag;  summag = 0;  totsites = 0;    if (backtrack) {    for (var = 1; var <= N; var++) if (v[var].clauselist) if (v[var].spin != 0) {      if (ave_field)	H = compute_field(-var, 1);   //compute local fields      else	H = compute_field(var, 1);      list[totsites++] = var;      magn[var] = ((double) v[var].spin) * (H.p - H.m); // bactrack indexing    }                                // do not care about paramagnetic spins  } else {    for (var = 1; var <= N; var++) if (v[var].clauselist) if (v[var].spin == 0) {          if (ave_field)	H = compute_field(-var, 1);   //compute local fields      else	H = compute_field(var, 1);      list[totsites++] = var;      magn[var] = (*index)(H);      maxmag = H.p > H.m ? H.p : H.m;      summag += maxmag;    }  }    qsort(list, totsites, sizeof(int), &order);    if (!backtrack) if ((summag / totsites) < PARAMAGNET) {    fprintf(out_file, "Paramagnetic state\n");    fflush(out_file);    writesolution(fopen(SOLUTION, "w+"));    close_computation();    fclose(out_file);    exit(0);  }  return 0;}void randomize_eta()     //pick initial random values{  int i,j;     for(i = 0; i < M; i++)    for(j = 0; j < clause[i].lits; j++) {      clause[i].literal[j].eta = (clause[i].type == 1) ? 1 : randreal();    }}void initmem()     //allocate mem (can be called more than once){  free(perm);  free(list);  free(magn);  perm = calloc(M, sizeof(int));  list = calloc(N + 1, sizeof(int));  magn = calloc(N + 1, sizeof(double));  if (!perm || !list || !magn || !div) {    fprintf(out_file, "Not enough memory for internal structures\n");    fclose(out_file);    exit(-1);  }  hsurvey_stores(maxconn); //allocate memory for h-surveys}void print_fields()     //print all H (non-cavity) fields{  int var;  struct weightstruct H;  for (var = 1; var <= N; var++) if (v[var].clauselist) {     H = compute_field(var, 1);    fprintf(out_file, "H(%i)={%f, %f, %f}\n", var, H.p ,H.z, H.m);  }}void print_eta()     //print all etas{  int c,l;  for(c = 0; c < M; c++) {    for(l = 0; l < clause[c].lits; l++) {      fprintf(out_file, "eta(%i, %i) = %f\n", c, l, clause[c].literal[l].eta);    }  }}int unfix_chunk(int quant)     //unfix quant spins at a time, taken from list[]{  struct weightstruct H;  int i = 0;    while ((N - freespin) && quant--) {    while (v[list[i]].spin == 0)      i++;    if (ave_field)      H = compute_field(-list[i], 1);    else      H = compute_field(list[i], 1);    if (replay) {      if (ave_field)	fprintf(replay, ">> Unfix %i\t\t\tH = %1.3f\t\t[%i free variables]\n", 		list[i], -H.p + H.m, freespin + 1);      else	fprintf(replay, ">> Unfix %i\t\t\tH = {%1.3f,%1.3f,%1.3f}\t\t[%i free variables]\n", 		list[i], H.p, H.z, H.m, freespin + 1);      fflush(replay);    }    if (verbose) {      fprintf(out_file, "[%i free variables]\n", freespin + 1);      fflush(out_file);    }    fix(list[i], 0);    }  return quant;}int fix_chunk(int quant)     //fix quant spins at a time, taken from list[]{  int i = 0;  struct weightstruct H;    while (freespin && quant--) {    while(v[list[i]].spin)      i++;    if (ave_field)      H = compute_field(-list[i], 1);    else      H = compute_field(list[i], 1);    if(replay) {      if (ave_field)	fprintf(replay,">> Fix %i ---> %s\t\tH = %1.3f\t\t[%i free variables]\n", 		list[i], H.p > H.m ? "-" : "+", -H.p + H.m, freespin - 1);      else	fprintf(replay,">> Fix %i ---> %s\t\tH = {%1.3f, %1.3f, %1.3f}\t\t[%i free variables]\n", 		list[i], H.p > H.m ? "-" : "+", H.p, H.z, H.m, freespin - 1);      fflush(replay);    }    if (verbose) {      fprintf(out_file, "[%i free variables]\n", freespin - 1);      fflush(out_file);    }    if (fix(list[i], H.p > H.m ? -1 : 1)) {        fprintf(out_file, "Bug... trying to fix an already fixed spin!\n");      fclose(out_file);      exit(-1);    }  }  return quant;}int converge_crossroads()     //a router{  static int schedule = 0;  if (ygraph) {    if (schedule % (2 * update_rate) == 0) {      backup();    }    if (schedule % update_rate == 0) {	      graph_free_energy();	expy(y);    }    schedule++;  }  return converge(1);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -