#include #include #include #include #include #include "utility.h"
#define MAXNERVE 10 //最大神经元数 #define MAXSTATE 1024 #define E0 0.2356
int quick = 1; double W[MAXNERVE][MAXNERVE]; //权值 double w[MAXNERVE]; //阈值 int output[MAXNERVE]; //输出 0/1 double H[MAXNERVE]; //神经元内部状态 double counter[MAXSTATE]; //状态计数/每种状态的实际概率 double *P; //每种状态的理论概率 double *E; //每种状态的能量
int NUM_NERVE; //实际神经元数量 int NUM_STATE; //状态数量 double INITIAL_TMP; //初始温度 double FINAL_TMP; //最终温度
char *paramfile = "1.PARAM"; //参数文件 char *resultfile = "1.RESULT";
void load_param(); //从文件加载参数(神经元数量、初始温度、最终温度) void initialize(); //初始化 void init_weight(); //初始化权值、阈值 void compute_energy(); //计算各个状态能量 void compute_P(); //计算理论概率 void process(); //处理过程 double compute_Hi(int i); //求神经元i的内部状态 void print_all(); //打印输出 void display_theory(FILE *fp); //显示不同状态的能量和理论概率 void dtob(int *o, int o_num, int i); //十进制转二进制 int btod(int *o, int o_num); //二进制转十进制 /******************************************************************** 程序入口 ********************************************************************/ int main(int argc, char **args) { if(argc == 3){ paramfile = args[1]; quick = args[2][0] - '0'; } load_param(); initialize(); process(); print_all(); return(1); }
/******************************************************************** 从文件加载参数(神经元数量、初始温度、最终温度) ********************************************************************/ void load_param() { FILE *fp = fopen(paramfile, "r"); if(fp == NULL){ printf("\n不能打开参数文件: %s\n", paramfile); exit(0); } fscanf(fp, "%d", &NUM_NERVE); fscanf(fp, "%lf", &INITIAL_TMP); fscanf(fp, "%lf", &FINAL_TMP); fclose(fp); if(NUM_NERVE > MAXNERVE){ printf("\n神经元最大不能超过10个\n"); exit(0); } }
/******************************************************************** 初始化 ********************************************************************/ void initialize() { NUM_STATE = 2 << (NUM_NERVE-1); if((P = (double *)malloc(sizeof(double) * NUM_STATE)) == NULL){ printf("\n分配理论概率失败\n"); exit(0); } if((E = (double *)malloc(sizeof(double) * NUM_STATE)) == NULL){ printf("\n分配能量失败\n"); exit(0); } init_weight(); compute_P(); } /******************************************************************** 初始化权值、阈值 ********************************************************************/ void init_weight() { int i, j; for(i = 0;i < NUM_NERVE;i++){ for(j = 0;j < i + 1;j++) W[i][j] = W[j][i] = gen_random(); w[i] = gen_random(); } for(i = 0;i < NUM_STATE;i++){ counter[i] = 0; } }
/******************************************************************** 计算理论概率 ********************************************************************/ void compute_P() { int i; double tmp = 0; compute_energy(); for(i = 0;i < NUM_STATE;i++){ tmp += exp(-E[i]/INITIAL_TMP); } for(i = 0;i < NUM_STATE;i++){ P[i] = exp(-E[i]/INITIAL_TMP)/tmp; }
} /******************************************************************** 计算各个状态能量 ********************************************************************/ void compute_energy() { int i, j, k; double tmp1 = 0, tmp2 = 0; for(k = 0;k < NUM_STATE;k++){ tmp1 = 0; tmp2 = 0; dtob(output, NUM_NERVE, k); for(i = 0;i < NUM_NERVE;i++){ for(j = 0;j < NUM_NERVE;j++){ if(j == i) continue; tmp1 += W[i][j]*output[i]*output[j]; } tmp1 -= w[i]*output[i]; } E[k] = -0.5*tmp1; } } /******************************************************************** 处理过程 ********************************************************************/ void process() { double temperature = INITIAL_TMP, tmp; int i, rand_nerve, t = 0; dtob(output, NUM_NERVE, random(NUM_STATE)); while(temperature > FINAL_TMP){ rand_nerve = random(NUM_NERVE); H[rand_nerve] = compute_Hi(rand_nerve); if(H[rand_nerve] > 0) output[rand_nerve] = 1; else if(H[rand_nerve] < 0){ tmp = 1/(1 + exp(-H[rand_nerve]/temperature)); if(tmp > E0) output[rand_nerve] = 1; } printf(""); i = btod(output, NUM_NERVE); counter[i] += 1; if(quick == 1) temperature = INITIAL_TMP/(t + 1 + 1); else temperature = INITIAL_TMP/log(t + 1); t++; printf("\n第%d次退火,当前温度为%lf\n", t, temperature); } for(i = 0;i < NUM_STATE;i++){ printf("counter[%d] = %ld\n", i, counter[i]); counter[i] /= t; } }
/******************************************************************** 求神经元i的内部状态 ********************************************************************/ double compute_Hi(int i) { int j; double tmp = 0; for(j = 0;j < NUM_NERVE;j++) if(j == i) continue; tmp += W[i][j]*output[j]; tmp -= w[i]; return tmp; }
/******************************************************************** 打印输出 ********************************************************************/ void print_all() { FILE *fp = fopen(resultfile, "w"); if(fp == NULL){ printf("\n不能打开结果文件: %s\n", resultfile); exit(0); } printf("\n权值"); fprintf(fp, "\n权值"); print_two(fp, (double **)W, NUM_NERVE, NUM_NERVE, MAXNERVE, MAXNERVE); printf("\n阈值"); fprintf(fp, "\n阈值"); print_one(fp, w, NUM_NERVE); display_theory(fp); fclose(fp); } /******************************************************************** 十进制转二进制 ********************************************************************/ void dtob(int *o, int o_num, int i) { int j; for(j = 0;j < o_num;j++){ o[j] = (i >> j) & 0x00000001; } } /******************************************************************** 二进制转十进制 ********************************************************************/ int btod(int *o, int o_num) { int i = 0, j; for(j = 0;j < o_num;j++){ i += (o[j] << j); } return i; } /******************************************************************** 显示不同状态的能量和理论概率 ********************************************************************/ void display_theory(FILE *fp) { int k; if(fp == NULL){ printf("\n没有结果文件: %s\n", resultfile); return; } printf("\n不同状态的能量、理论概率、实际概率\n"); fprintf(fp, "\n不同状态的能量、理论概率、实际概率\n"); printf("*********************************************************\n"); fprintf(fp, "*********************************************************\n"); printf("状态\t 能量 \t理论概率 \t实际概率\n"); fprintf(fp, "状态\t能量\t理论概率\t实际概率\n"); for(k = 0;k < NUM_STATE;k++){ printf("%d\t%lf\t%lf\t%lf\n", k, E[k], P[k], counter[k]); fprintf(fp, "%d\t%lf\t%lf\t%lf\n", k, E[k], P[k], counter[k]); } printf("********************************************************\n"); fprintf(fp, "********************************************************\n"); }
|