next up previous contents
Next: A.5 その他の関数用ソースファイル (srh2_mf.c) Up: 付 録A サーチアクセスプログラム Previous: A.3 コールバック関数用ソースファイル (srh_cb.c)

A.4 サーチアクセス関数用ソースファイル (srh2_srh.c)

 

サーチアクセスに関する関数についてのソースファイルである。

#include <math.h>

#include "srh2_ms.h"
#include "srh2_sms.h"

/* パターンの要素 */
#define B 1 /* 黒 */
#define W 0 /* 白 */

#define PATTERN     4 /* 記憶するパターン数 */

#define fout(x) (1/(1+ exp(-(x/0.01)))) /* シグモイド関数 */
 
extern double drand48();/* 乱数関数 */

int fail;/* それぞれの検索パターンについて数えて
            一番早く失敗したのが何回目の初期パターンかを表す */

int search;/* 何番目の検索パターンを検索しているかを示す */

int kai;/* 何番目の初期パターンで検索しているかを示す */
int kai_max;/* 離散的時間最大値
               (この時間までに想起できなかったら失敗とみなす) */
int shoki_n;/* 検索回数 */

/* シナプス前抑制変数・定数 */
static double z;/* 入力 */
static double rsnp;/* 出力 */
static double rcha;/* 出力最小値(カオス状態) */
static double gs;/* しきい値 */

/* カオスニューロン定数 */
static double alp;/* 不応性に関する比例定数 */
static double km;/* 相互結合入力に関する記憶の減衰定数 */
static double kr;/* 不応性に関する減衰定数 */
static double gaib;/* しきい値定数 */

static double eps;/* シグモイド関数の温度の比例定数 */

double sei_hei;/* 想起成功率 */
double t_hei;/* 平均想起時間 */

search_main()
{
  FILE *file_write(int *,int);
  /* Result File または,Passage File の書き込み設定 */

  int i,j;
  int fw;/* Result File, Passage File 書き込み失敗判定フラグ */
  int keika_ari;/* Passage File 出力判定フラグ */
  FL_OBJECT *ob;/* 検索中に入力があったオブジェクトのポインタ */

  int levo[U],levn[U];/* 量子化値 */
  int times;/* 同パターン連続想起回数 */
  int hi;/* 同パターン連続想起判定フラグ */

  long shoki;/* 乱数初期化 */

  /* カオスニューロン出力・内部状態 */
  double x[U];/* 出力パターン */
  double m[U];/* 相互結合に関する内部状態 */
  double n[U];/* 不応性に関する内部状態 */

  /* 自己相関学習変数・定数 */
  double sok;/* 結合荷重比例定数 */
  double w[U][U];/* シナプス結合荷重 */
  int out_in[PATTERN][U];/* 学習パターン */

  int nai_s_s[PATTERN][SRH_MAX];/* 検索パターンと初期パターンの相関内積 */

  FILE *fp;/* Pattern File */
  FILE *fd;/* Result File */
  FILE *fk;/* Passage File */

  const char *pfn;/* Pattern File のファイル名 */

  /* 各定数設定 */
  sok = fl_get_counter_value(sok_o);
  alp = fl_get_counter_value(alp_o);
  eps = 0.015;
  gaib = 2.0;
  rcha = 0.4;
  km = fl_get_counter_value(km_o);
  kr = fl_get_counter_value(kr_o);
  gs = fl_get_counter_value(gs_o);
  shoki_n = (int)fl_get_counter_value(sn);
  shoki = (long)fl_get_counter_value(pn);
  kai_max = (int)fl_get_counter_value(mt);

  sei_hei=0.0;
  t_hei=0.0;
  fail=-1;

  keika_ari = fl_get_button(po);

  /* Pattern File 読み込み設定 */
  pfn = fl_get_input(fl);
  if((fp = fopen(pfn,"r")) == NULL){
    /* 読み込みに失敗した場合
       (ファイルがないか読み込み禁止になっている場合) */
    fl_set_object_lcol(str,FL_BLACK);
    fl_activate_object(str);
    fl_show_alert("Sorry","Can't find or read Pattern File!!",pfn,0);
    goto fail_p;
  }
  /* Passage Output ボタンが ON(黄)の場合 */
  if(keika_ari){
    /* Passage File 書き込み設定 */
    fk=file_write(&fw,0);
    if(fw)
      /* 書き込み失敗の場合 */
      goto fail_k;
  }
  /* Result File 書き込み設定 */
  fd=file_write(&fw,1);
  if(fw)
    goto fail_d;

  /* 各定数のファイル出力 */
  fprintf(fd,"km\t%1.3lf\nkr\t%1.3lf\ng\t%1.3lf\n",km,kr,gs);
  fprintf(fd,"so\t%1.3lf\nm\t%d\nalp\t%2.2lf\n\n",sok,kai_max,alp);

  /* パターンの取り込み */
  if(torikomi(shoki,out_in,fp,fd,pfn))
    /* 失敗の場合 */
    goto fail_d;

  /* 自己相関学習 */
  soukan(sok,w,out_in);

  /* 各学習パターンごとに検索 */
  for(search = 0; search < PATTERN; search++){

    /* 何番目の学習パターンかをファイル出力 */
    fprintf(fd,"\npt%d\n",search);

    /* 初期値パターン設定 */
    srand48(shoki);

    /* 各パターンにつき shoki_n 回検索する */
    for(j = 0; j < shoki_n ; j++){

      /* 初期設定・内積計算 */
      shoki_p(j,x,m,n,out_in,nai_s_s);

      /* 想起されるまでニューロンの出力を計算を繰り返す
         kai_max 回繰り返しても想起されなかった場合は計算を終了する */
      for(kai = 0; kai < kai_max ; kai++){

        /* ボタン等の入力を調べる */
        if((ob=fl_check_forms())==ps){
        pas:
          /* PAUSE ボタンを押した場合 */
          while((ob=fl_do_forms())!=ps)
            if(ob==stp)
              /* STOP ボタンを押した場合 */
              goto stop;
        }
        else
          /* STOP ボタンを押した場合 */
          if(ob==stp)
          stop:
            /* 本当に検索を中止していいかどうかを選択 */
            if(fl_show_question("Do you really want to STOP?","","")){
              /* Yes を選択した場合 */
              fl_set_object_lcol(str,FL_BLACK);
              fl_activate_object(str);
              goto fail_d;
            }
            else
              if(fl_get_button(ps))
                /* PAUSE ボタンが ON の状態の場合 */
                goto pas;
        
        /* 量子化(終了判定比較等に用いる) */
        ryoushika(levo,x);
        /* カオスニューロンの入力と出力の比較(検索終了判定) */
        hi=hikaku(levo,levn);
        if (hi == 0 && kai != 0)
          times++;/* 同じ場合 */
        else 
          times=0;/* 異なる場合 */
        /* 出力を新たに入力とする */
        for(i=0; i<U; i++)
          levn[i] = levo[i];

        /* 出力パターンと検索パターンとの距離計算と,
           シナプス前抑制関数の出力計算 */
        kyori(x,out_in);

        /* Passage Output ボタンが ON の場合 Passage File へ出力 */
        if(keika_ari)
          keika(levo,times,hi,kai,fk);

        /* 何らかのパターンが想起されたとみなし終了 */
        if(times == SOUKITIME)
          break;
        
        /* カオスニューロンの出力計算 */
        neuro(x,m,n,w);

      }

      /* 想起に成功したかどうかの判定・ファイル出力 */
      jikosouki(j,levo,out_in,fd);
    }
    fprintf(fd,"\n");
  }
  /* 初期パターンと学習パターンとの相関内積の出力 */
  for(i=0; i<PATTERN; i++){
    /* 何番目の学習パターンとの相関内積かを出力 */
    fprintf(fd,"\nnp%d\n",i);
    for(j=0; j<shoki_n; j++){
      fprintf(fd,"%5d",nai_s_s[i][j]);
      if(j%10 == 9)
        fprintf(fd,"\n");
    }
    fprintf(fd,"\n");
  }

  /* 失敗がなかった場合 Failure ランプに青を点灯 */
  if(fail==-1) fl_set_object_color(f_sg,FL_BLUE,FL_COL1);

  /* 想起平均時間の計算 */
  if(sei_hei!=0)
    t_hei/=sei_hei;
  else t_hei=-1.0;/* 一度も成功しなかった場合 -1 とする */
  /* 想起成功率の計算 */
  sei_hei/=PATTERN*shoki_n;
  /* 計算結果をファイル出力 */
  fprintf(fd,"seikou\t%lf\n",sei_hei);
  fprintf(fd,"time\t%lf\n",t_hei);

  /* 各ファイルを閉じる */
 fail_d:
  fclose(fd);
 fail_k:
  if(keika_ari)
    fclose(fk);
 fail_p:
  fclose(fp);
}

/* 自己相関学習 */
soukan(double sok, double w[][U], int out_in[][U])
{
  int i,j,k;
  double out_in_z_h;/* 全学習パターンの要素平均 */

  /* 全学習パターンの要素平均の計算 */
  out_in_z_h = 0.0;
  for(j = 0; j < U; j++)
    for(i = 0; i < PATTERN; i++)
      out_in_z_h += (double)out_in[i][j];
  out_in_z_h /= U*PATTERN;
  
  /* 自己相関学習によりシナプス結合荷重を求める
    (全学習パターンの要素平均を考慮) */
  for(i = 0; i < PATTERN; i++)
    for(j = 0; j < U; j++)
      for(k = 0; k < U; k++){
        if(i==0) w[j][k]=0.0;
        w[j][k] += sok * 4 *((double)out_in[i][j] - out_in_z_h) *
          ((double)out_in[i][k] - out_in_z_h);
      }
}

/* 初期設定・内積計算 */
shoki_p(int j, double x[], double m[], double n[], int out_in[][U],
        int nai_s_s[][SRH_MAX])
{
  register int i;

  nai_s_s[search][j] = 0;
  for(i = 0; i < U; i++){
    /* 初期パターンの設定 */
    if(drand48() < 0.5)
      x[i] = W;
    else
      x[i] = B;
    /* 初期パターンと検索パターンとの相関内積 */
    if((double)out_in[search][i] == x[i])
      nai_s_s[search][j]++;
    else
      nai_s_s[search][j]--;
    /* 内部状態の初期設定 */
    m[i] = n[i] = 0;
  }
}

/* 量子化 */
ryoushika(int levo[], double x[])
{
  register int i;

  for(i = 0; i < U; i++)
    if(x[i] < 0.1)
      levo[i] = 0;
    else
      if(x[i] < 0.25)
        levo[i] = 1;
      else
        if(x[i] < 0.5)
          levo[i] = 2;
        else
          if(x[i] < 0.75)
            levo[i] = 3;
          else
            if(x[i] < 0.90)
              levo[i] = 4;
            else
              levo[i] = 5;
}

/* カオスニューロンの入力と出力が等しいかどうかを量子化値を用いて比較 */
int hikaku(int levo[], int levn[])
{
  register int i;
  
  for(i = 0; i < U; i++)
    if(levo[i] != levn[i])
      return 1;
  return 0;
}

/* カオスニューロンの出力計算 */
neuro(double x[],double m[], double n[], double w[][U])
{
  register int i,j;
  register double kas;

  for(i=0; i<U; i++){
    kas = 0.0;
    for(j = 0; j < U; j++)
      kas += (w[i][j] * x[j]);    
    m[i] = rsnp * kas + km * m[i];
    n[i] = -alp * x[i] + kr * n[i] + gaib;
    x[i] = fout((m[i] + n[i]) / eps);
  }
}

/* Pattern File からのデータの取り込み,Result File へデータ出力 */
int torikomi(long shoki, int out_in[][U], FILE *fp, FILE *fd,
             const char *pfn)
{
  int i,j,naiseki,nyuu;

  for(i=0; i<PATTERN; i++){
    /* 何番目のパターンかを表示 */
    fprintf(fd,"p%d\n",i);
    for(j=0; j<U; j++){
      /* Pattern File からパターンの要素を順に入力 */
      if((nyuu=fscanf(fp,"%d",&out_in[i][j]))==0 || nyuu==EOF){
        /* Pattern File のデータ形式が正しくない場合 */
        fl_set_object_lcol(str,FL_BLACK);
        fl_activate_object(str);
        fl_show_alert("Sorry","Bad Format File!",pfn,0);
        return -1;
      }
      /* Result File へパターンの要素を順に出力 */
      fprintf(fd,"%d ",out_in[i][j]);
      if(j%10 == 9)
        fprintf(fd,"\n");
    }
    fprintf(fd,"\n");
  }
  j = 1;
  /* 相関内積のデータ数の計算 */
  for(i=1; i<PATTERN; i++)
    j *= i;
  for(i=0; i<j; i++){
    /* Pattern File から相関内積値を順に出力 */
    if((nyuu=fscanf(fp,"%d",&naiseki)) == 0 || nyuu == EOF){
      /* Pattern File のデータ形式が正しくない場合 */
      fl_set_object_lcol(str,FL_BLACK);
      fl_activate_object(str);
      if(nyuu)
        /* Pattern File に相関内積値がない場合 */
        fl_show_alert("Sorry","No Inner Product!",pfn,0);
      else
        /* Pattern File に数字以外の文字が含まれている場合 */
        fl_show_alert("Sorry","Bad Format File!",pfn,0);
      return -1;
    }
    /* まだ内積値を Result File に出力していない場合,内積値を示す n を出力 */
    if(i==0) fprintf(fd,"n");
    /* Pattern File に内積値を出力 */
    fprintf(fd,"\t%3d ",naiseki);
  }
  /* Result File に Pattern Number (s), Search Number (sn) を出力 */
  fprintf(fd,"\n\ns\t%lu\nsn\t%3d\n\n",shoki,shoki_n);
  return 0;
}

/* 出力パターンと検索パターンとの距離計算と,シナプス前抑制関数の出力計算 */
kyori(double x[],int out_in[][U])
{
  register int i;
  
  z=0;
  for(i=0; i<U; i++)
    /* パターンの要素ごとの距離の絶対値を加算 */
    z += fabs(x[i] - (double)out_in[search][i]);
  /* 距離計算 */
  z /= U;
  /* 距離からシナプス前抑制関数の出力計算 */
  if(z < gs)
    rsnp = 1;
  else
    rsnp = rcha;
}

/* Passage File への出力 */
keika(int levo[], int times, int hi, FILE *fk)
{
  register int i;

  /* 各変数の出力 */
  fprintf(fk,"t=%d time=%d hi=%d rsnp=%1.3lf z=%1.3lf\n",kai,times,hi,rsnp,z);
  /* 出力パターンの出力 */
  for(i=0; i<U; i++){
    fprintf(fk,"%d ",levo[i]);
    if(i%10 == 9)
      fprintf(fk,"\n");
  }
  fprintf(fk,"\n");
}

/* Result File, Passage File に指定されているファイルを開く時に
   呼び出される関数 */
FILE *file_write(int *fw, int fs)
{
  const char *fname;
  FILE *f;
  char q1[200],q2[200],sys[150],dir[100];
  int i,dirf;

  /* Result File, Passage File のどちらを開くか判定し,fname へ入力 */
  if(fs)
    fname=fl_get_input(rfl);
  else
    fname=fl_get_input(pfl);
  if((f=fopen(fname,"w"))==NULL){
    /* fname のファイルが開けない場合 */
    if(fs)
      sprintf(q1,"I don't write in this Result File!");
    else
      sprintf(q1,"I don't write in this Passage File!");
    sprintf(q2,"Do you want to do 'chmod u+w %s'?",fname);
    /* fname のファイルに書き込み許可を与えるかどうかを選択 */
    if(fl_show_question(q1,fname,q2)){
      fclose(f);
      /* fname のファイルに書き込み許可を与える */
      sprintf(sys,"chmod u+w %s",fname);
      system(sys);
    }
    else
      /* No を選択した場合,検索を終了 */
      goto w_fail;
    if((f=fopen(fname,"w"))==NULL){
      /* まだファイルが開けない場合 */
      /* 指定したファイルがあるディレクトリを調べ,dir へ入力 */
      dirf=0;
      for(i=0; *(fname+i)!='\0'; i++){
        if((dir[i]=*(fname+i))=='/') dirf=i;
      }
      dir[dirf]='\0';
      /* dir に入力されているディレクトリを作るかどうかを選択 */
      sprintf(q1,"Do you want to do 'mkdir %s'?",dir);
      if(fl_show_question("I failed to do 'chmod'!",q1,"")){
        fclose(f);
        /* dir に入力されているディレクトリを作成 */
        sprintf(sys,"mkdir %s",dir);
        system(sys);
      }
      else
        /* No を選択した場合,検索を終了 */
        goto w_fail;
      if((f=fopen(fname,"w"))==NULL){
        /* まだファイルが開けない場合 */
        /* dir に入力されているディレクトリに書き込み・実行許可を
           与えるかどうかを選択 */
        sprintf(q1,"Do you want to do 'chmod u+wx %s'?",dir);
        if(fl_show_question("I failed to do 'mkdir'!",q1,"")){
          fclose(f);
          sprintf(sys,"chmod u+wx %s",dir);
          system(sys);
        }
        else
          /* No を選択した場合,検索を終了 */
          goto w_fail;
        if((f=fopen(fname,"w"))==NULL){
          /* なお,まだファイルが開けない場合,警告を出して終了 */
          fl_show_alert("Sorry","I failed to do 'chmod'!!","",0);
        w_fail:
          /* START ボタンを動作可能にする */
          fl_set_object_lcol(str,FL_BLACK);
          fl_activate_object(str);
          /* ファイルを開けなかったことを示す */
          *fw=1;
          return f;
        }
      }
    }
  }
  /* 正常にファイルを開けたことを示す */
  *fw=0;
  /* 得られたファイルポインタを
     fd (Result File) または fk (Passage File) へ入力 */
    return f;
}



Deguchi Toshinori
1998年03月12日 (木) 16時16分01秒 JST