#include<iostream.h>
#include<iomanip.h>
#include<stdlib.h>
#include<stdio.h>
#include<time.h>
#include<math.h>
#define L 10    /*输入层单元数*/ 
#define M 10    /*隐含层单元数*/
#define N 10    /*输出层单元数*/
#define NUM 10  /*学习次数*/
/*
int i;          /*输入层第i个单元*/
/*
int j;          /*输入层第j个单元*/
/*
int k;          /*输入层第k个单元*/
int num;          /*当前输入训练序号*/
int t;          /*输入矫正数据序号*/
int m;          /*隐含层第m个单元*/
int n;          /*隐含层第m个单元*/
double wait[L]; /*待测数据*/
double e=0.5;   /*误差限*/
double alpha=1.5;
double beta=0.34;
double mid_E[M];
double out_D[N];           /*输出层校正误差*/
double jihuo_mid_S[M];     /*隐含层单元激活值*/
double jihuo_mid_f[M];     /*隐含层激活函数*/
double jihuo_out_S[N];     /*输出层单元激活值*/
double jihuo_out_f[N];     /*输出层激活函数*/
double mid_fa_data[M],out_fa_data[N];  /*中间、输出层阀值*/
double U[L][M];            /*输入到中间层权值*/
double V[M][N];            /*中间到输出层权值*/
double stdty_data[NUM][L]; /*训练数据*/
double teach_data[NUM][L];      /*校正数据*/
FILE *fp_s;                /*训练数据文件指针*/
FILE *fp_t;                /*校正数据文件指针*/

////////////////////////////////
///////程序权值阀值初始化///////
////////////////////////////////
initial()
{   
    int i,j,k;
    srand(time(NULL));                     /*随机函数种子*/
    for(j=0;j<M;j++)
    {
        mid_fa_data[j]=1.0;                /*中间层阀值初始化*/
        for(i=0;i<L;i++)
            U[i][j]=(float)(((rand()/32767.0)*2-1)/2.0);   /*初始化-0.5~0.5 之间的输入层到隐含层之间的权值*/
        for(k=0;k<N;k++)
        {
            out_fa_data[k]=1.0;            /*输出层阀值初始化*/
            V[j][k]=(float)(((rand()/32767.0)*2-1)/2.0);   /*初始化-0.5~0.5 之间的隐含层到输出层之间的权值*/
        }
    }
    //输出部分//
    printf("\n中间阀值:\n");
    for(j=0;j<M;j++)  
        printf("%f ",mid_fa_data[j]);
    printf("\n输出阀值:\n");
    for(k=0;k<N;k++)
        printf("%f ",out_fa_data[k]);
    printf("\n输入至中间层权值:\n ");
    for(i=0;i<L;i++)
        for(j=0;j<M;j++)
            printf("%f ",U[i][j]);
    printf("\n中间至输出层权值:\n ");
    for(j=0;j<M;j++)
        for(k=0;k<N;k++)
            printf("%f ",V[j][k]);
return 1;
};

//////////////////////////////////////////////////
/////////////学习样本、期望输出的读入/////////////
//////////////////////////////////////////////////
get_training_data()
{
    /*下为将训练数据读入*/
    int i,num;
    if((fp_s=fopen("F:\\刘虎\\VC程序\\trainning_data_study.txt","r"))==NULL)
    {
        printf("打开失败,可能是文件不存在。");
        exit(1);
    }
    else
        for(num=0;num<NUM;num++)
            for(i=0;i<L;i++)
                fread(&stdty_data[num][i],sizeof(float),10,fp_s);
    for(num=0;num<NUM;num++)
    {
        printf("第%d次训练数据",num);
    /*下为将校正数据读入*/
    if((fp_t=fopen("F:\\刘虎\\VC程序\\trainning_data_teach.txt","r"))==NULL)
    {
        printf("打开失败,可能是文件不存在。");
        exit(1);
    }
    else
        for(num=0;num<NUM;num++)
            for(i=0;i<L;i++)
                fread(&teach_data[num][i],sizeof(float),10,fp_t);
    return 1;        
};

////////////////////////////////////////
////////计算隐含层各单元输入输出////////
////////////////////////////////////////
mid_io_data(int num)
{
    int i,j;
    double sigma=0.0;         
        for(j=0;j<M;j++)
        {
            for(i=0;i<L;i++)
                sigma+=U[i][j]*stdty_data[num][i];
            jihuo_mid_S[j]=sigma-mid_fa_data[j];
            jihuo_mid_f[j]=2.0/(1.0+exp(-2.0*(jihuo_mid_S[j])))-1.0;  /*隐含层个单元输出*/     
        }
    return 1;
};

////////////////////////////////////////
////////计算输出层各单元输入输出////////
////////////////////////////////////////

out_io_data(int num)
{
    int j,k;    
    double sigma=0.0;
    for(k=0;k<N;k++)
    {
        for(j=0;j<M;j++)
            sigma+=V[j][k]*jihuo_mid_f[j];
        jihuo_out_S[k]=sigma-out_fa_data[k];
        jihuo_out_f[k]=2.0/(1.0+exp(-2.0*(jihuo_out_S[k])))-1.0;  /*输出层个单元输出*/        
    }
    return 1;
};

////////////////////////////////////////
/////////输出层的校正误差子程序/////////
////////////////////////////////////////
Error_out(int num)
{
    int k;
    for(k=0;k<N;k++)
        out_D[k]=(jihuo_out_f[k]-teach_data[num][k])*(1.0-jihuo_out_f[k])*jihuo_out_f[k];
    return 1;
};

////////////////////////////////////////
///////////隐含层各单元误差/////////////
////////////////////////////////////////
Error_mid(int num)
{
    int j,k;    
    double epusel=0.0;
    for(j=0;j<M;j++)
    {
        for(k=0;k<N;k++)
            epusel+=V[j][k]*out_D[k];
        mid_E[j]=(epusel)*jihuo_mid_f[j]*(1.0-jihuo_mid_f[j]);
    }
    return 1;
};

///////////////////////////////////////////////
//输出层与隐含层之间连接权校正量delta_V[j][k]//
/////////输出层阀值校正量delta_seta[k]/////////
///////////////////////////////////////////////

alpha_error(int num)
{
    int j,k;
    double delta_V[M][N];
    double delta_seta[N];
    for(j=0;j<M;j++)
        for(k=0;k<N;k++)
        {
            delta_V[j][k]=alpha*out_D[k]*jihuo_out_f[k];
            delta_seta[k]=alpha*out_D[k];
        }
    return 1;
};

/////////////////////////////////////////
////隐含层至输出层校正量delta_U[i][j]////
/////////////////////////////////////////
beta_error(int num)
{
    int i,j;
    double delta_U[L][M];
    double delta_seta[M];
    for(i=0;i<L;i++)
        for(j=0;j<M;j++)
        {
            delta_U[i][j]=beta*mid_E[j]*stdty_data[num][i];
            delta_seta[j]=beta+mid_E[j];
        }
    return 1;
};

/////////////////////////////////////////
/////////计算输出层总平方差误差//////////
/////////////////////////////////////////
tottle_error(int num)
{
    int k;
    double tottle_error=0.0;
    for(k=0;k<N;k++)
    tottle_error+=(out_D[k]-teach_data[num][k])*(out_D[k]-teach_data[num][k]);
    return 1;
};

/////////////////////////////////////////
/////////主程序//////////
/////////////////////////////////////////
main()
{
    printf("输入层、中间层、输出层各层单元数:%d %d %d \n",L,M,N);
    printf("训练的次数:%d \n",NUM);
    initial();
    get_training_data();
    for(s=0;num<NUM;s++)
    {
        printf("第%d次网络训练。",num);
        mid_io_data(int num);
        out_io_data(int num);
        Error_out(int num);
        Error_mid(int num);
        alpha_error(int num);
        beta_error(int num);
    }
    if(tottle_error<e)
    {
        printf("GOOD");
        for(q=0;q<L;q++)
            scanf("%f",&wait[q]);

        mid_io_data(int num);
        out_io_data(int num);
        Error_out(int num);
        tottle_error(int num);
        if(tottle_error<e)
            printf("质量好,误差为%lf:\n",tottle_error);
        else
            printf("不合格");
    }
    else
        printf("BAD");
}