BOLTZMAN.C
上传用户:hbxdlj
上传日期:2022-07-27
资源大小:8k
文件大小:9k
开发平台:

Visual C++

  1. /******************************************************************************
  2.                       ==========================================
  3.         Network:      Boltzmann Machine with Simulated Annealing
  4.                       ==========================================
  5.         Application:  Optimization
  6.                       Traveling Salesman Problem
  7.         Author:       Karsten Kutza
  8.         Date:         21.2.96
  9.         Reference:    D.H. Ackley, G.E. Hinton, T.J. Sejnowski
  10.                       A Learning Algorithm for Boltzmann Machines
  11.                       Cognitive Science, 9, pp. 147-169, 1985
  12.  ******************************************************************************/
  13. /******************************************************************************
  14.                             D E C L A R A T I O N S
  15.  ******************************************************************************/
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. #include <math.h>
  19. typedef int           BOOL;
  20. typedef int           INT;
  21. typedef double        REAL;
  22. #define FALSE         0
  23. #define TRUE          1
  24. #define NOT           !
  25. #define AND           &&
  26. #define OR            ||
  27. #define PI            (2*asin(1))
  28. #define sqr(x)        ((x)*(x))
  29. typedef struct {                     /* A NET:                                */
  30.         INT           Units;         /* - number of units in this net         */
  31.         BOOL*         Output;        /* - output of ith unit                  */
  32.         INT*          On;            /* - counting on states in equilibrium   */
  33.         INT*          Off;           /* - counting off states in equilibrium  */
  34.         REAL*         Threshold;     /* - threshold of ith unit               */
  35.         REAL**        Weight;        /* - connection weights to ith unit      */
  36.         REAL          Temperature;   /* - actual temperature                  */
  37. } NET;
  38. /******************************************************************************
  39.         R A N D O M S   D R A W N   F R O M   D I S T R I B U T I O N S
  40.  ******************************************************************************/
  41. void InitializeRandoms()
  42. {
  43.   srand(4711);
  44. }
  45. BOOL RandomEqualBOOL()
  46. {
  47.   return rand() % 2;
  48. }
  49. INT RandomEqualINT(INT Low, INT High)
  50. {
  51.   return rand() % (High-Low+1) + Low;
  52. }      
  53. REAL RandomEqualREAL(REAL Low, REAL High)
  54. {
  55.   return ((REAL) rand() / RAND_MAX) * (High-Low) + Low;
  56. }      
  57. /******************************************************************************
  58.                A P P L I C A T I O N - S P E C I F I C   C O D E
  59.  ******************************************************************************/
  60. #define NUM_CITIES    10
  61. #define N             (NUM_CITIES * NUM_CITIES)
  62. REAL                  Gamma;
  63. REAL                  Distance[NUM_CITIES][NUM_CITIES];
  64. FILE*                 f;
  65. void InitializeApplication(NET* Net)
  66. {
  67.   INT  n1,n2;
  68.   REAL x1,x2,y1,y2;
  69.   REAL Alpha1, Alpha2;
  70.   Gamma = 7;
  71.   for (n1=0; n1<NUM_CITIES; n1++) {
  72.     for (n2=0; n2<NUM_CITIES; n2++) {
  73.       Alpha1 = ((REAL) n1 / NUM_CITIES) * 2 * PI;
  74.       Alpha2 = ((REAL) n2 / NUM_CITIES) * 2 * PI;
  75.       x1 = cos(Alpha1);
  76.       y1 = sin(Alpha1);
  77.       x2 = cos(Alpha2);
  78.       y2 = sin(Alpha2);
  79.       Distance[n1][n2] = sqrt(sqr(x1-x2) + sqr(y1-y2));
  80.     }
  81.   }
  82.   f = fopen("BOLTZMAN.txt", "w");
  83.   fprintf(f, "Temperature    Valid    Length    Tournn");
  84. }
  85. void CalculateWeights(NET* Net)
  86. {
  87.   INT  n1,n2,n3,n4;
  88.   INT  i,j;
  89.   INT  Pred_n3, Succ_n3;
  90.   REAL Weight;
  91.   for (n1=0; n1<NUM_CITIES; n1++) {
  92.     for (n2=0; n2<NUM_CITIES; n2++) {
  93.       i = n1*NUM_CITIES+n2;
  94.       for (n3=0; n3<NUM_CITIES; n3++) {
  95.         for (n4=0; n4<NUM_CITIES; n4++) {
  96.           j = n3*NUM_CITIES+n4;
  97.           Weight = 0;
  98.           if (i!=j) {
  99.             Pred_n3 = (n3==0 ? NUM_CITIES-1 : n3-1);
  100.             Succ_n3 = (n3==NUM_CITIES-1 ? 0 : n3+1);
  101.             if ((n1==n3) OR (n2==n4))
  102.               Weight = -Gamma;
  103.             else if ((n1 == Pred_n3) OR (n1 == Succ_n3))
  104.               Weight = -Distance[n2][n4];
  105.           }
  106.           Net->Weight[i][j] = Weight;
  107.         }
  108.       }
  109.       Net->Threshold[i] = -Gamma/2;
  110.     }
  111.   }
  112. }
  113. BOOL ValidTour(NET* Net)
  114. {
  115.   INT n1,n2;
  116.   INT Cities, Stops;
  117.   for (n1=0; n1<NUM_CITIES; n1++) {
  118.     Cities = 0;
  119.     Stops  = 0;
  120.     for (n2=0; n2<NUM_CITIES; n2++) {
  121.       if (Net->Output[n1*NUM_CITIES+n2]) {
  122.         if (++Cities > 1) 
  123.           return FALSE;
  124.       }
  125.       if (Net->Output[n2*NUM_CITIES+n1]) {
  126.         if (++Stops > 1) 
  127.           return FALSE;
  128.       }
  129.     }
  130.     if ((Cities != 1) OR (Stops != 1))
  131.       return FALSE;
  132.   }
  133.   return TRUE;
  134. }
  135. REAL LengthOfTour(NET* Net)
  136. {
  137.   INT  n1,n2,n3;
  138.   REAL Length;
  139.   Length = 0;
  140.   for (n1=0; n1<NUM_CITIES; n1++) {
  141.     for (n2=0; n2<NUM_CITIES; n2++) {
  142.       if (Net->Output[((n1) % NUM_CITIES)*NUM_CITIES+n2])
  143.         break;
  144.     }
  145.     for (n3=0; n3<NUM_CITIES; n3++) {
  146.       if (Net->Output[((n1+1) % NUM_CITIES)*NUM_CITIES+n3])
  147.         break;
  148.     }
  149.     Length += Distance[n2][n3];
  150.   }
  151.   return Length;
  152. }
  153. void WriteTour(NET* Net)
  154. {
  155.   INT  n1,n2;
  156.   BOOL First;
  157.   if (ValidTour(Net))
  158.     fprintf(f, "%11.6f      yes    %6.3f    ", Net->Temperature, LengthOfTour(Net));
  159.   else
  160.     fprintf(f, "%11.6f       no              ", Net->Temperature);
  161.   for (n1=0; n1<NUM_CITIES; n1++) {
  162.     First = TRUE;
  163.     fprintf(f, "[");
  164.     for (n2=0; n2<NUM_CITIES; n2++) {
  165.       if (Net->Output[n1*NUM_CITIES+n2]) {
  166.         if (First) {
  167.           First = FALSE;
  168.           fprintf(f, "%d", n2);
  169.         }
  170.         else {
  171.           fprintf(f, ", %d", n2);
  172.         }
  173.       }
  174.     }
  175.     fprintf(f, "]");
  176.     if (n1 != NUM_CITIES-1) {
  177.       fprintf(f, " -> ");
  178.     }
  179.   }
  180.   fprintf(f, "n");
  181. }
  182. void FinalizeApplication(NET* Net)
  183. {
  184.   fclose(f);
  185. }
  186. /******************************************************************************
  187.                           I N I T I A L I Z A T I O N
  188.  ******************************************************************************/
  189. void GenerateNetwork(NET* Net)
  190. {
  191.   INT i;
  192.   Net->Units     = N;
  193.   Net->Output    = (BOOL*)  calloc(N, sizeof(BOOL));
  194.   Net->On        = (INT*)   calloc(N, sizeof(INT));
  195.   Net->Off       = (INT*)   calloc(N, sizeof(INT));
  196.   Net->Threshold = (REAL*)  calloc(N, sizeof(REAL));
  197.   Net->Weight    = (REAL**) calloc(N, sizeof(REAL*));
  198.   for (i=0; i<N; i++) {
  199.     Net->Weight[i] = (REAL*) calloc(N, sizeof(REAL));
  200.   }
  201. }
  202. void SetRandom(NET* Net)
  203. {
  204.   INT i;
  205.    
  206.   for (i=0; i<Net->Units; i++) {
  207.     Net->Output[i] = RandomEqualBOOL();
  208.   }
  209. }
  210. /******************************************************************************
  211.                      P R O P A G A T I N G   S I G N A L S
  212.  ******************************************************************************/
  213. void PropagateUnit(NET* Net, INT i)
  214. {
  215.   INT  j;
  216.   REAL Sum, Probability;
  217.   Sum = 0;
  218.   for (j=0; j<Net->Units; j++) {
  219.     Sum += Net->Weight[i][j] * Net->Output[j];
  220.   }
  221.   Sum -= Net->Threshold[i];
  222.   Probability = 1 / (1 + exp(-Sum / Net->Temperature));
  223.   if (RandomEqualREAL(0, 1) <= Probability)
  224.     Net->Output[i] = TRUE;
  225.   else
  226.     Net->Output[i] = FALSE;
  227. }
  228. /******************************************************************************
  229.                       S I M U L A T I N G   T H E   N E T
  230.  ******************************************************************************/
  231. void BringToThermalEquilibrium(NET* Net)
  232. {
  233.   INT n,i;
  234.   for (i=0; i<Net->Units; i++) {
  235.     Net->On[i]  = 0;
  236.     Net->Off[i] = 0;
  237.   }
  238.   for (n=0; n<1000*Net->Units; n++) {
  239.     PropagateUnit(Net, i = RandomEqualINT(0, Net->Units-1));
  240.   }
  241.   for (n=0; n<100*Net->Units; n++) {
  242.     PropagateUnit(Net, i = RandomEqualINT(0, Net->Units-1));
  243.     if (Net->Output[i])
  244.       Net->On[i]++;
  245.     else
  246.       Net->Off[i]++;
  247.   }
  248.   for (i=0; i<Net->Units; i++) {
  249.     Net->Output[i] = Net->On[i] > Net->Off[i];
  250.   }
  251. }
  252. void Anneal(NET* Net)
  253. {
  254.   Net->Temperature = 100;
  255.   do {
  256.     BringToThermalEquilibrium(Net);
  257.     WriteTour(Net);
  258.     Net->Temperature *= 0.99;
  259.   } while (NOT ValidTour(Net));
  260. }
  261. /******************************************************************************
  262.                                     M A I N
  263.  ******************************************************************************/
  264. void main()
  265. {
  266.   NET Net;
  267.   InitializeRandoms();
  268.   GenerateNetwork(&Net);
  269.   InitializeApplication(&Net);
  270.   CalculateWeights(&Net);
  271.   SetRandom(&Net);
  272.   Anneal(&Net);
  273.   FinalizeApplication(&Net);
  274. }