2011|08|
2013|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|05|06|07|08|09|10|11|12|
2016|01|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|

2017-07-03 「上司の帰宅が遅れると、部下の帰宅も遅れる」の仮説検証プログラム

/*
  g++ -g seat4.cpp -o seat4
*/
 
/*
  「上司の帰宅が遅れると、部下の帰宅も遅れる」の仮説検証プログラム
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
 
// 共通関数
double max(double a){
  return a;
}
 
double max(double a, double b){
  if (a > b) 
    return a;
  else 
    return b;
};
 
double max(double a, double b, double c ){
  return max(max(a,b), max(b,c)); 
};
 
double max(double a, double b, double c, double d ){
  return max(max(a,b,c), d); 
};
 
double min(double a){
  return a;
}
 
double min(double a, double b){
  if (b > a) 
    return a;
  else 
    return b;
};
 
double min(double a, double b, double c ){
  return min(min(a,b), min(b,c)); 
};
 
double min(double a, double b, double c, double d ){
  return min(min(a,b,c), d); 
};
 
 
// ファジィ表現
typedef enum scale {LESSLESS, LESS, ZERO, MORE, MOREMORE} SCALE;
 
// 前件部メンバーシップ関数(山3つ)クラス
class condition_MF3
{
private:
  double center;
  double width;
  SCALE express;
  
public:
  condition_MF3(double _center, double _witdth, SCALE _express){
    center = _center;
    width = _witdth;
    express = _express;
    
    // 使用できないファジィ表現を使った場合は止める        
    if ((express == LESSLESS) || (express == MOREMORE)){
      printf("wrong expression used \n");
      exit(0);
    }
    
  };
  double func(double _x);
};
 
double condition_MF3::func(double _x)
{
  // x,yは、メンバーシップ関数上の座標を示す
  double x = _x;
  double y = 0.0; // yの値は、必ず0以上1以下になる
  
  if (express == LESS){
    if (x <= center - width){
      y = 1.0;
    }
    else if (x <= center){
      y = - 1.0 / width * (x - center);
    }
    else{
      y = 0.0;
    }
  }
  else if (express == ZERO){
    if (x <= center - width){
      y = 0.0;
    }
    else if (x <= center){
      y = 1.0 / width * (x - center) + 1.0;
    }
    else if (x <= center + width){
      y = -1.0 / width * (x - center) + 1.0;
    }
    else{
      y = 0.0;
    }
  }
  else if (express == MORE){
    if (x <= center){
      y = 0.0;
    }
    else if (x <= center + width){
      y = 1.0 / width * (x - center);
    }
    else{
      y = 1.0;
    }
  }
  else {
    printf("wrong expression\n");
    exit(1);
  }
  
  return y;
};
 
// 前件部メンバーシップ関数(山5つ)クラス
class condition_MF5
{
private:
  double center;
  double width;
  SCALE express;
  
public:
  condition_MF5(double _center, double _witdth, SCALE _express){
    center = _center;
    width = _witdth;
    express = _express;
  };
  double func(double _x);
};
 
 
double condition_MF5::func(double _x)
{
  // x,yは、メンバーシップ関数上の座標を示す
  double x = _x;
  double y = 0.0; // yの値は、必ず0以上1以下になる
  
  if (express == LESSLESS){
    if (x <= center - 2.0 * width){
      y = 1.0;
    }
    else if (x <= center - width){
      y = - 1.0 / width * (x - (center - 2.0 * width)) + 1.0;
    }
    else{
      y = 0.0;
    }
  }
  else if (express == LESS){
    if (x <= center - 2.0 * width){
      y = 0.0;
    }
    else if (x <= center - width){
      y = 1.0 / width * (x - (center - width)) + 1.0;
    }
    else if (x <= center){
      y = -1.0 / width * (x - (center - width)) + 1.0; 
    }
    else{
      y = 0.0;
    }
  }
  else if (express == ZERO){
    if (x <= center - width){
      y = 0.0;
    }
    else if (x <= center){
      y = 1.0 / width * (x - center) + 1.0;
    }
    else if (x <= center + width){
      y = -1.0 / width * (x - center) + 1.0;
    }
    else{
      y = 0.0;
    }
  }
  else if (express == MORE){
    if (x <= center){
      y = 0.0;
    }
    else if (x <= center + width){
      y = 1.0 / width * (x - (center + width)) + 1.0;
    }
    else if (x <= center + 2.0 * width){
      y = -1.0 / width * (x - (center + width)) + 1.0; 
    }
    else{
      y = 0.0;
    }
  }
  else if (express == MOREMORE){
    if (x <= center + width){
      y = 0.0;
    }
    else if (x <= center + 2.0 * width){
      y = 1.0 / width * (x - (center + 2.0 * width)) + 1.0;
    }
    else{
      y = 1.0;
    }
  }
  
  return y;
};
 
// 後件部メンバーシップ関数(山3つ)クラス  
class action_MF3
{
private:
  double center;
  double width;
  SCALE express;
  
  double x;
  double y;
  
public:
  action_MF3(double _center, double _witdth, SCALE _express){
    
    y = 0.0; // yの値は、必ず0以上1以下になる
    
    center = _center;
    width = _witdth;
    express = _express;
    
    if (express == LESS){
      x = center - width;
    }
    else if (express == ZERO){
      x = center;
    }
    else if (express == MORE){
      x = center + width;
    }
    else{
      printf("wrong scale expression\n");
      exit(0);
    }
  };
 
  // Y座標の値を最大値で更新する  
  void func_Max(double b){
    y = max(b, y);
  };
  
  // Y座標の値をリセット(y=0)する
  void func_Reset(){
    y = 0.0;
  };
  
  // X座標を返す
  double func_X(void){
    return x;
  };
  
  // (最大値で更新された、最後の)Y座標を返す
  double func_Y(){
    return y;
  };
 
};
 
// 後件部メンバーシップ関数(山5つ)クラス  
class action_MF5
{
private:
  double center;
  double width;
  SCALE express;
  
  double x;
  double y;
  
public:
  action_MF5(double _center, double _witdth, SCALE _express){
    y = 0.0; // yの値は、必ず0以上1以下になる
    
    center = _center;
    width = _witdth;
    express = _express;
    
    if (express == LESSLESS){
      x = center - 2.0 * width;
    }
    else if (express == LESS){
      x = center - width;
    }
    else if (express == ZERO){
      x = center;
    }
    else if (express == MORE){
      x = center + width;
    }
    else if (express == MOREMORE){
      x = center + 2.0 * width;
    }
    else{
      printf("wrong scale expression\n");
      exit(-1); // 強制終了
    }
  };
  
  // Y座標の値を最大値で更新する  
  void func_Max(double b){
    y = max(b, y);
  };
  
  // Y座標の値をリセット(y=0)する
  void func_Reset(){
    y = 0.0;
  };
  
  // X座標を返す
  double func_X(void){
    return x;
  };
  
  // (最大値で更新された、最後の)Y座標を返す
  double func_Y(){
    return y;
  };
  
};
 
typedef enum post{
  HEAD = 1,  // 部長
  CHIEF = 2, // 課長
  STAFF = 3  // 平社員
} POST;
 
typedef struct person{
  int absences;  // 0:帰宅、 1:残業
  char name[10];
  int section;
  int number;
  POST post;
  double p_x;
  double p_y;
  double expected_return_time;  // 17.5(17:30)から、21.0(21:00)までの時間)
  double going_home_ratio;
} PERSON;
 
const int SECTION = 6;
const int MEMBER = 8;
const int ALL_PERSON_COUNTER = 49; // 6つの課、それぞれ8人と部長
 
PERSON person[] = {
 
  {1,"部長",-1,-1, HEAD,   0.0,             0.0},
 
  {1,"社員", 0, 0, STAFF,  3.5 + 0.0 + 0.0, -4.4 + 0.0 + 0.0},
  {1,"社員", 0, 1, STAFF,  3.5 + 0.0 + 1.2, -4.4 + 0.0 + 0.0},
  {1,"社員", 0, 2, STAFF,  3.5 + 0.0 + 2.4, -4.4 + 0.0 + 0.0},
  {1,"社員", 0, 3, STAFF,  3.5 + 0.0 + 3.6, -4.4 + 0.0 + 0.0},
  {1,"課長", 0, 4, CHIEF,  3.5 + 0.0 + 0.0, -4.4 + 0.0 + 2.0},
  {1,"社員", 0, 5, STAFF,  3.5 + 0.0 + 1.2, -4.4 + 0.0 + 2.0},
  {1,"社員", 0, 6, STAFF,  3.5 + 0.0 + 2.4, -4.4 + 0.0 + 2.0},
  {1,"社員", 0, 7, STAFF,  3.5 + 0.0 + 3.6, -4.4 + 0.0 + 2.0},
 
  {1,"社員", 1, 0, STAFF,  3.5 + 4.8 + 0.0, -4.4 + 0.0 + 0.0},
  {1,"社員", 1, 1, STAFF,  3.5 + 4.8 + 1.2, -4.4 + 0.0 + 0.0},
  {1,"社員", 1, 2, STAFF,  3.5 + 4.8 + 2.4, -4.4 + 0.0 + 0.0},
  {1,"課長", 1, 3, CHIEF,  3.5 + 4.8 + 3.6, -4.4 + 0.0 + 0.0},
  {1,"社員", 1, 4, STAFF,  3.5 + 4.8 + 0.0, -4.4 + 0.0 + 2.0},
  {1,"社員", 1, 5, STAFF,  3.5 + 4.8 + 1.2, -4.4 + 0.0 + 2.0},
  {1,"社員", 1, 6, STAFF,  3.5 + 4.8 + 2.4, -4.4 + 0.0 + 2.0},
  {1,"社員", 1, 7, STAFF,  3.5 + 4.8 + 3.6, -4.4 + 0.0 + 2.0},
 
  {1,"社員", 2, 0, STAFF,  3.5 + 0.0 + 0.0, -4.4 + 3.4 + 0.0},
  {1,"社員", 2, 1, STAFF,  3.5 + 0.0 + 1.2, -4.4 + 3.4 + 0.0},
  {1,"課長", 2, 2, CHIEF,  3.5 + 0.0 + 2.4, -4.4 + 3.4 + 0.0},
  {1,"社員", 2, 3, STAFF,  3.5 + 0.0 + 3.6, -4.4 + 3.4 + 0.0},
  {1,"社員", 2, 4, STAFF,  3.5 + 0.0 + 0.0, -4.4 + 3.4 + 2.0},
  {1,"社員", 2, 5, STAFF,  3.5 + 0.0 + 1.2, -4.4 + 3.4 + 2.0},
  {1,"社員", 2, 6, STAFF,  3.5 + 0.0 + 2.4, -4.4 + 3.4 + 2.0},
  {1,"社員", 2, 7, STAFF,  3.5 + 0.0 + 3.6, -4.4 + 3.4 + 2.0},
 
  {1,"社員", 3, 0, STAFF,  3.5 + 4.8 + 0.0, -4.4 + 3.4 + 0.0},
  {1,"社員", 3, 1, STAFF,  3.5 + 4.8 + 1.2, -4.4 + 3.4 + 0.0},
  {1,"社員", 3, 2, STAFF,  3.5 + 4.8 + 2.4, -4.4 + 3.4 + 0.0},
  {1,"社員", 3, 3, STAFF,  3.5 + 4.8 + 3.6, -4.4 + 3.4 + 0.0},
  {1,"社員", 3, 4, STAFF,  3.5 + 4.8 + 0.0, -4.4 + 3.4 + 2.0},
  {1,"社員", 3, 5, STAFF,  3.5 + 4.8 + 1.2, -4.4 + 3.4 + 2.0},
  {1,"課長", 3, 6, CHIEF,  3.5 + 4.8 + 2.4, -4.4 + 3.4 + 2.0},
  {1,"社員", 3, 7, STAFF,  3.5 + 4.8 + 3.6, -4.4 + 3.4 + 2.0},
 
  {1,"課長", 4, 0, CHIEF,  3.5 + 0.0 + 0.0, -4.4 + 6.8 + 0.0},
  {1,"社員", 4, 1, STAFF,  3.5 + 0.0 + 1.2, -4.4 + 6.8 + 0.0},
  {1,"社員", 4, 2, STAFF,  3.5 + 0.0 + 2.4, -4.4 + 6.8 + 0.0},
  {1,"社員", 4, 3, STAFF,  3.5 + 0.0 + 3.6, -4.4 + 6.8 + 0.0},
  {1,"社員", 4, 4, STAFF,  3.5 + 0.0 + 0.0, -4.4 + 6.8 + 2.0},
  {1,"社員", 4, 5, STAFF,  3.5 + 0.0 + 1.2, -4.4 + 6.8 + 2.0},
  {1,"社員", 4, 6, STAFF,  3.5 + 0.0 + 2.4, -4.4 + 6.8 + 2.0},
  {1,"社員", 4, 7, STAFF,  3.5 + 0.0 + 3.6, -4.4 + 6.8 + 2.0},
 
  {1,"社員", 5, 0, STAFF,  3.5 + 4.8 + 0.0, -4.4 + 6.8 + 0.0},
  {1,"社員", 5, 1, STAFF,  3.5 + 4.8 + 1.2, -4.4 + 6.8 + 0.0},
  {1,"社員", 5, 2, STAFF,  3.5 + 4.8 + 2.4, -4.4 + 6.8 + 0.0},
  {1,"社員", 5, 3, STAFF,  3.5 + 4.8 + 3.6, -4.4 + 6.8 + 0.0},
  {1,"課長", 5, 4, CHIEF,  3.5 + 4.8 + 0.0, -4.4 + 6.8 + 2.0},
  {1,"社員", 5, 5, STAFF,  3.5 + 4.8 + 1.2, -4.4 + 6.8 + 2.0},
  {1,"社員", 5, 6, STAFF,  3.5 + 4.8 + 2.4, -4.4 + 6.8 + 2.0},
  {1,"社員", 5, 7, STAFF,  3.5 + 4.8 + 3.6, -4.4 + 6.8 + 2.0},
};
 
double distance(PERSON* person1, PERSON* person2)
{
  double d = 0.0;
  
  d  = pow((person1->p_x - person2->p_x),2.0);
  d += pow((person1->p_y - person2->p_y),2.0);
  d = sqrt(d);
 
  if ((person1->absences == 0) || (person2->absences == 0) )
    d = 99999.9; // どちらかが不在であれば、非常に大きい距離になる
 
  return d;
}
 
int main()
{
  PERSON* cheif[SECTION+1]; 
 
  // 初期状態 (最初は個人の帰宅時間は、乱数で設定)
  for (int i = 0; i < ALL_PERSON_COUNTER; i++){
    // 各個人の帰宅時間を設定
    person[i].expected_return_time = 17.5 + (21.0 -17.5) * rand()/ (1.0 + RAND_MAX);
    //person[i].expected_return_time = 18.5;
 
    // 各課の課長を選定(後で探すのが面倒なので)
    if (person[i].post == CHIEF){
      cheif[person[i].section] = &person[i];
    }
  }
 
  person[0].expected_return_time = 22.0;
 
  /*
  for (int i = 0; i < ALL_PERSON_COUNTER; i++){
    printf("%d, expected_return_time = %f\n",i, person[i].expected_return_time);
    printf("%d, expected_return_time = %d\n",i, person[i].absences);
  }
  */
 
  // 残業時間
  condition_MF3 OverTime_Short(1.0, 1.0, LESS); // 1時間
  condition_MF3 OverTime_Middle(1.0, 1.0, ZERO); // 2時間
  condition_MF3 OverTime_Long(1.0, 1.0, MORE); // 3時間
 
  // 部長からの距離
  condition_MF5 DistanceFrom_HEAD_NearNear(5.0, 5.0, LESSLESS); // 5メートル
  condition_MF5 DistanceFrom_HEAD_Near(5.0, 5.0, LESS); // 10メートル
  condition_MF5 DistanceFrom_HEAD_Middle(5.0, 5.0, ZERO); // 15メートル
  condition_MF5 DistanceFrom_HEAD_Far(5.0, 5.0, MORE); // 20メートル
  condition_MF5 DistanceFrom_HEAD_FarFar(5.0, 5.0, MOREMORE); // 25メートル
 
  // 課長からの距離
  condition_MF5 DistanceFrom_CHIEF_NearNear(1.0, 1.0, LESSLESS); // 1メートル
  condition_MF5 DistanceFrom_CHIEF_Near(1.0, 1.0, LESS); // 2メートル
  condition_MF5 DistanceFrom_CHIEF_Middle(1.0, 1.0, ZERO); // 3メートル
  condition_MF5 DistanceFrom_CHIEF_Far(1.0, 1.0, MORE); // 4メートル
  condition_MF5 DistanceFrom_CHIEF_FarFar(1.0, 1.0, MOREMORE); // 5メートル
 
  // 残っている課の人数
  condition_MF3 Staying_COUNT_Less(2, 2, LESS); // 2人
  condition_MF3 Staying_COUNT_Middle(2, 2, ZERO); // 4人
  condition_MF3 Staying_COUNT_Many(2, 2, MORE); // 6人
 
  // 帰宅度数
  action_MF3 GoingHome_Hard(0.5, 0.5, LESS);// 帰宅度数 0.0 → 帰宅できない
  action_MF3 GoingHome_Middle(0.5, 0.5, ZERO);// 帰宅度数 0.5 → 迷う
  action_MF3 GoingHome_Easy(0.5, 0.5, MORE);// 帰宅度数 1.0 → 帰宅できる
 
  double present_time =17.5;
 
  while (present_time < 24.0){
    present_time += 0.1; // 一番後ろで加算すると忘れそうなので
    //  printf("present_time = %f\n",  present_time);
 
    // 部の中の課の全体状況の把握
 
    if (person[0].expected_return_time < present_time){  // 部長は特別あつかい
      person[0].absences = 0;
    }
 
    int staying_count[SECTION] ={}; // 各課(Section)で残っている人数を格納(最初はゼロリセット)
    
    int staying_all = 0;
 
    for (int i = 0; i < ALL_PERSON_COUNTER; i++){
      if (person[i].absences == 1){
        staying_count[person[i].section] += 1;  // (Section)に一人追加
        staying_all += 1;
      }
    }
 
    printf("%f,%d,%d,%d,%d,%d,%d,%d\n", 
           present_time, 
           staying_count[0],
           staying_count[1],
           staying_count[2],
           staying_count[3],
           staying_count[4],
           staying_count[5],
           staying_all);
    
    for (int i = 1; i < ALL_PERSON_COUNTER; i++){ // person[0]の部長は神様→誰からも影響を受けない(とする)
 
#if 1
      if (person[i].absences == 0) // 帰った人間はどーでも良い
        continue;
 
      if (person[i].expected_return_time > present_time) // 仕事中は帰らない
        continue;
#endif
 
      if (person[i].post == STAFF){ // (ヒラ)社員の場合の付加条件
        /*
          ルール3
          課長が残っている場合、課長から1.5m以内のメンバは、帰宅度数0.0
          課長から3.0m以内のメンバは、帰宅度数0.5
          課長から4.5m以内のメンバは、帰宅度数0.7
        */
        
        double dis = distance(cheif[person[i].section], &person[i]);
 
        ///////////////
        double r11 = min(DistanceFrom_CHIEF_NearNear.func(dis), 
                         OverTime_Short.func(person[i].expected_return_time - present_time));
        GoingHome_Hard.func_Max(r11);
 
        double r12 = min(DistanceFrom_CHIEF_Near.func(dis), 
                         OverTime_Short.func(person[i].expected_return_time - present_time));
        GoingHome_Hard.func_Max(r12);
 
        double r13 = min(DistanceFrom_CHIEF_Middle.func(dis), 
                         OverTime_Short.func(person[i].expected_return_time - present_time));
        GoingHome_Hard.func_Max(r13);
 
        double r14 = min(DistanceFrom_CHIEF_Far.func(dis), 
                         OverTime_Short.func(person[i].expected_return_time - present_time));
        GoingHome_Middle.func_Max(r14);
 
        double r15 = min(DistanceFrom_CHIEF_FarFar.func(dis), 
                         OverTime_Short.func(person[i].expected_return_time - present_time));
        GoingHome_Easy.func_Max(r15);
        ///////////////
 
        ///////////////
        double r21 = min(DistanceFrom_CHIEF_NearNear.func(dis), 
                         OverTime_Middle.func(person[i].expected_return_time - present_time));
        GoingHome_Hard.func_Max(r21);
 
        double r22 = min(DistanceFrom_CHIEF_Near.func(dis), 
                         OverTime_Middle.func(person[i].expected_return_time - present_time));
        GoingHome_Hard.func_Max(r22);
 
        double r23 = min(DistanceFrom_CHIEF_Middle.func(dis), 
                         OverTime_Middle.func(person[i].expected_return_time - present_time));
        GoingHome_Middle.func_Max(r23);
 
        double r24 = min(DistanceFrom_CHIEF_Far.func(dis), 
                         OverTime_Middle.func(person[i].expected_return_time - present_time));
        GoingHome_Easy.func_Max(r24);
 
        double r25 = min(DistanceFrom_HEAD_FarFar.func(dis), 
                         OverTime_Middle.func(person[i].expected_return_time - present_time));
        GoingHome_Easy.func_Max(r25);
        ///////////////
 
        ///////////////
        double r31 = min(DistanceFrom_CHIEF_NearNear.func(dis), 
                         OverTime_Long.func(person[i].expected_return_time - present_time));
        GoingHome_Hard.func_Max(r31);
 
        double r32 = min(DistanceFrom_CHIEF_Near.func(dis), 
                         OverTime_Long.func(person[i].expected_return_time - present_time));
        GoingHome_Middle.func_Max(r32);
 
        double r33 = min(DistanceFrom_CHIEF_Middle.func(dis), 
                         OverTime_Long.func(person[i].expected_return_time - present_time));
        GoingHome_Easy.func_Max(r33);
 
        double r34 = min(DistanceFrom_CHIEF_Far.func(dis), 
                         OverTime_Long.func(person[i].expected_return_time - present_time));
        GoingHome_Easy.func_Max(r34);
 
        double r35 = min(DistanceFrom_CHIEF_FarFar.func(dis), 
                         OverTime_Long.func(person[i].expected_return_time - present_time));
        GoingHome_Easy.func_Max(r34);
        ///////////////
      }
 
 
      if (person[i].post == CHIEF){ // 課長の場合の付加条件
        /*
          ルール2
          部長が残っている場合、部長から5m以内の課長は、帰宅度数0.0
          5m~10m以内の課長は、帰宅度数0.5
          10m以上の課長は、帰宅度数1.0
        */
        
        double dis = distance(&person[0], &person[i]);
        
        ///////////////
        double r11 = min(DistanceFrom_HEAD_NearNear.func(dis), 
                         OverTime_Short.func(person[i].expected_return_time - present_time));
        GoingHome_Hard.func_Max(r11);
 
        double r12 = min(DistanceFrom_HEAD_Near.func(dis), 
                         OverTime_Short.func(person[i].expected_return_time - present_time));
        GoingHome_Hard.func_Max(r12);
 
        double r13 = min(DistanceFrom_HEAD_Middle.func(dis), 
                         OverTime_Short.func(person[i].expected_return_time - present_time));
        GoingHome_Hard.func_Max(r13);
 
        double r14 = min(DistanceFrom_HEAD_Far.func(dis), 
                         OverTime_Short.func(person[i].expected_return_time - present_time));
        GoingHome_Middle.func_Max(r14);
 
        double r15 = min(DistanceFrom_HEAD_FarFar.func(dis), 
                         OverTime_Short.func(person[i].expected_return_time - present_time));
        GoingHome_Easy.func_Max(r15);
        ///////////////
 
        ///////////////
        double r21 = min(DistanceFrom_HEAD_NearNear.func(dis), 
                         OverTime_Middle.func(person[i].expected_return_time - present_time));
        GoingHome_Hard.func_Max(r21);
 
        double r22 = min(DistanceFrom_HEAD_Near.func(dis), 
                         OverTime_Middle.func(person[i].expected_return_time - present_time));
        GoingHome_Hard.func_Max(r22);
 
        double r23 = min(DistanceFrom_HEAD_Middle.func(dis), 
                         OverTime_Middle.func(person[i].expected_return_time - present_time));
        GoingHome_Middle.func_Max(r23);
 
        double r24 = min(DistanceFrom_HEAD_Far.func(dis), 
                         OverTime_Middle.func(person[i].expected_return_time - present_time));
        GoingHome_Easy.func_Max(r24);
 
        double r25 = min(DistanceFrom_HEAD_FarFar.func(dis), 
                         OverTime_Middle.func(person[i].expected_return_time - present_time));
        GoingHome_Easy.func_Max(r25);
        ///////////////
 
        ///////////////
        double r31 = min(DistanceFrom_HEAD_NearNear.func(dis), 
                         OverTime_Long.func(person[i].expected_return_time - present_time));
        GoingHome_Hard.func_Max(r31);
 
        double r32 = min(DistanceFrom_HEAD_Near.func(dis), 
                         OverTime_Long.func(person[i].expected_return_time - present_time));
        GoingHome_Middle.func_Max(r32);
 
        double r33 = min(DistanceFrom_HEAD_Middle.func(dis), 
                         OverTime_Long.func(person[i].expected_return_time - present_time));
        GoingHome_Easy.func_Max(r33);
 
        double r34 = min(DistanceFrom_HEAD_Far.func(dis), 
                         OverTime_Long.func(person[i].expected_return_time - present_time));
        GoingHome_Easy.func_Max(r34);
 
        double r35 = min(DistanceFrom_HEAD_FarFar.func(dis), 
                         OverTime_Long.func(person[i].expected_return_time - present_time));
        GoingHome_Easy.func_Max(r34);
        ///////////////
      }
      
 
#if 0     
      /*
        ルール4
        同じ課のメンバのの人数が、6人以上残っている場合は、帰宅度数0.3
                              4人残っている場合は、帰宅度数0.6
                              2人以下の場合は、帰宅度数1.0
      */
 
      int num = staying_count[person[i].section];
      double r41 = min(Staying_COUNT_Less.func((double)num));
      GoingHome_Easy.func_Max(r41);
      
      double r42 = min(Staying_COUNT_Middle.func((double)num));
      GoingHome_Middle.func_Max(r42);
      
      double r43 = min(Staying_COUNT_Many.func((double)num));
      GoingHome_Hard.func_Max(r43);
 
#endif
 
      /*
        ルールに振れない場合は、min-max重心法の分母がゼロになり、
        ゼロ割が発生する場合がある為、それを回避する
      */
      double denominator =  // 分母
        GoingHome_Easy.func_Y() + 
        GoingHome_Middle.func_Y() +
        GoingHome_Hard.func_Y();
 
      double numerator =  // 分子   
        GoingHome_Easy.func_X() * GoingHome_Easy.func_Y() + 
        GoingHome_Middle.func_X() * GoingHome_Middle.func_Y() +
        GoingHome_Hard.func_X() * GoingHome_Hard.func_Y();
 
      // 推論結果 (分母がゼロの場合は、推論結果は前回と同値とする)
      if ( denominator != 0.0){
        person[i].going_home_ratio =  numerator / denominator ;
 
        /*
        if ((present_time >= 18.5) && (present_time < 18.52)){
          printf("%d: person[i].going_home_ratio=%f\n",i, person[i].going_home_ratio);
        }
        */
 
      }      
 
      if (person[i].going_home_ratio > 0.75){
        person[i].absences = 0;  // 0:帰宅、 1:残業        
      }
 
      // 後件部メンバーシップ関数のリセット(ループさせる時は必ずリセットする)
      GoingHome_Easy.func_Reset();
      GoingHome_Middle.func_Reset();
      GoingHome_Hard.func_Reset();
    }
  }
 
  /*
  for (int i = 0; i < ALL_PERSON_COUNTER; i++){
    printf("%d, absences = %d\n",i, person[i].absences);
  }
  */
  
  return 0;
}