2017,江端さんの技術メモ

/* 
   gcc -g ql_test.cpp -o ql_test
 
   強化学習(Q-Learning)を理解する為に、中学→高校→大学の学歴を使ってみた
 
*/
 
#include <stdio.h>
#include <stdlib.h>
 
typedef enum period{
  BIRTH = 0, JUNIOR_HIGH = 1, HIGH = 2, COLLEGE = 3, SUPER_COLLEGE = 4
}PERIOD;
 
typedef struct state{
  struct state* future_state[2]; // 未来へのパス(取り敢えず2つほど)
  PERIOD period;
  int q;
}STATE;
 
 
STATE* change_state(STATE* p_state)
{
  if ((double)rand()/RAND_MAX < 0.3){  // ε:0.3
	if ((double)rand()/RAND_MAX < 0.5){ // 半々
	  return p_state->future_state[0];
	}
	else{
	  return p_state->future_state[1];
	}
  }
  else {
	if (p_state->future_state[0]->q > p_state->future_state[1]->q){
	  return p_state->future_state[0];
	}
	else{
	  return p_state->future_state[1];
	}
  }
}
	
void  q_renewal(STATE* p_state)
{
  int dummy_q;
 
  if (p_state->period  == SUPER_COLLEGE){
	p_state->q += 0.1 * (1000- p_state->q); // α:0.1 報酬の源泉:年収1000万円
  }
  else if (p_state->period !=  COLLEGE){
	if (p_state->future_state[0]->q > p_state->future_state[1]->q){
	  dummy_q = p_state->future_state[0]->q;
	}
	else {
	  dummy_q = p_state->future_state[1]->q;
	}
	p_state->q += 0.1 * (0.9 * dummy_q - p_state->q); // α:0.1 γ:0.9
  }
 
  return;
}
	
void q_display(STATE* p_state)
{
  for (int i =0; i < 15 ; i++){
	printf("%d,", p_state->q);
	p_state++;
  }
  printf("\n");
  return;
}
 
 
 
int main()
{
  srand(13);
 
 
  // 初期設定
  //STATE* state;
  STATE state[15];
 
  state[0].period = BIRTH;
  state[0].future_state[0] = &(state[1]);
  state[0].future_state[1] = &(state[2]);
 
  state[1].period = JUNIOR_HIGH;
  state[1].future_state[0] = &(state[3]);
  state[1].future_state[1] = &(state[4]);
 
  state[2].period = JUNIOR_HIGH;
  state[2].future_state[0] = &(state[5]);
  state[2].future_state[1] = &(state[6]);
 
  state[3].period = HIGH;
  state[3].future_state[0] = &(state[7]);
  state[3].future_state[1] = &(state[8]);
 
  state[4].period = HIGH;
  state[4].future_state[0] = &(state[9]);
  state[4].future_state[1] = &(state[10]);
 
  state[5].period = HIGH;
  state[5].future_state[0] = &(state[11]);
  state[5].future_state[1] = &(state[12]);
 
  state[6].period = HIGH;
  state[6].future_state[0] = &(state[13]);
  state[6].future_state[1] = &(state[14]);
 
  state[7].period = COLLEGE;
  state[8].period = COLLEGE;
  state[9].period = COLLEGE;
  state[10].period = SUPER_COLLEGE;
  state[11].period = COLLEGE;
  state[12].period = COLLEGE;
  state[13].period = COLLEGE;
  state[14].period = COLLEGE;
  
  for (int i = 0; i < 15; i++){
	state[i].q = (int)rand() % 100;
  }
 
  printf("誕生,A中学,B中学,C高校,D高校,E高校,F高校,G大学,H大学,I大学,J大学,K大学,L大学,M大学,N大学\n");

  STATE* s = state;
  //q_display(s);
  q_display(state);
 
  for (int i = 0; i < 1000; i++){  // 300:学習回数
	STATE* s = state; // 初期値に戻しているだけ
	
	do{ 
	  s = change_state(s);
	  q_renewal(s);
	}while( (s->period != COLLEGE) && (s->period != SUPER_COLLEGE));

	q_display(state);

  }
 
  printf("\n[after]\n");
  //q_display(s);
  q_display(state);
 
}

2017,江端さんの技術メモ

/*
  gcc -g second_job.cpp -o second_job
 

  考え方
  
  (1)8時間労働、8時間睡眠、8時間余暇を基本として考える。
  (2)8時間余暇の中には、通勤時間1.5時間 食事時間1.5時間が含まれるものとする
  (3)とすれば、残りの余暇5時間をどのような使い方をするのかが問題となる。
  
  (4)十分な余暇は、基本的に正業のパフォーマンスを上げるものであるとする。
  (4)余暇を使った副業は、収入になるものとする

*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct person {
  double first_business_hour;
  double sleep_hour;
  double commute_time;
  double meal_time;

  double max_remain_time;
  double second_business_hour;
  double final_remain_time;

  double fb_fee;
  double sb_fee;
  
  double fatigue_func;
  double cost;

  struct person *prev;  /* 前の構造体を示すポインタ */
  struct person *next;  /* 次の構造体を示すポインタ */
} PERSON;


double min(double a, double b)
{
  if (a > b)
	return b;
  else
	return a;
}

double diff(double a, double b)
{
  if (a > b)
	return a - b;
  else
	return 0;
}


double fatigue_func(double time)
{
  if (time < 1.0){
	return 0.5;
  }
  else if ((time >= 1.0) && (time < 3.0)){
	return (1.0 - 0.5)/(3.0 - 1.0) * (time - 1.0) + 0.5;
  }
  else {
	return 1.0;
  }
}

const double First_Business_hourly_fees = 2000;
const double First_Business_extra_fees = First_Business_hourly_fees * 1.25;
const double Second_Business_hourly_fees = 1000;


int main()
{
  srand(13);

  PERSON* first_p_person= (PERSON*)malloc(sizeof(PERSON));
  PERSON* last_p_person= (PERSON*)malloc(sizeof(PERSON));

  PERSON*  p_prev_person = first_p_person;

  for (int i = 0; i < 100; i++){
	
	PERSON* p_person= (PERSON*)malloc(sizeof(PERSON));
	memset(p_person, 0, sizeof(PERSON));


	//////// ポインタの貼り替え //////////
	p_prev_person->next = p_person;
	p_person->next = last_p_person;
	p_person->prev = p_prev_person;
	p_prev_person = p_person;
	//////////////////////////////////////

	p_person->first_business_hour = 8.0 + 2.0 * (double)rand()/RAND_MAX;    // 8~10時間

	p_person->first_business_hour = 8.0;    // 8~10時間

	p_person->sleep_hour = 7.0 + 1.0 * (1.0 - 2.0 * (double)rand()/RAND_MAX); // 6~8時間
	p_person->commute_time = 1.0 + 0.5 * (1.0 - 2.0 * (double)rand()/RAND_MAX); // 0.5~1.5時間
	p_person->meal_time = 1.0 + 0.5 * (1.0 - 2.0 * (double)rand()/RAND_MAX);  // 0.5~1.5時間
	
	p_person->max_remain_time = 
	  24.0 - 
	  p_person->first_business_hour -
	  p_person->sleep_hour - 
	  p_person->commute_time - 
	  p_person->meal_time;    // 最悪でも3時間の、最良で9時間の余暇時間ができる

#if 1
	p_person->second_business_hour = p_person->max_remain_time * (double)rand()/RAND_MAX; //余暇の時間を適当に振る
#else
	p_person->second_business_hour = 0;
#endif

	p_person->final_remain_time = p_person->max_remain_time - p_person->second_business_hour;
	
	p_person->fb_fee = 
	  min(p_person->first_business_hour, 8.0) * First_Business_hourly_fees +
	  diff(p_person->first_business_hour, 8.0) * First_Business_extra_fees;
	
	p_person->sb_fee = p_person->second_business_hour * Second_Business_hourly_fees;
	p_person->fatigue_func = fatigue_func(p_person->final_remain_time);

	p_person->cost =	
	  p_person->fb_fee * p_person->fatigue_func + p_person->sb_fee;
  
	//printf("%d:cost = %f\n", i, p_person->cost);

  }


  double total_cost = 0.0;
  
  PERSON* p_person = first_p_person->next;

  printf("本業時間,睡眠時間,通勤時間,食事時間,余暇時間,副業時間,残余暇時間,RATIO,収入\n");

  while(p_person->next != last_p_person){
	total_cost += p_person->cost;
	
	printf("%f,%f,%f,%f,%f,%f,%f,%f,%f\n",
		   p_person->first_business_hour,
		   p_person->sleep_hour,
		   p_person->commute_time,
		   p_person->meal_time,
		   p_person->max_remain_time,
		   p_person->second_business_hour,
		   p_person->final_remain_time,
		   p_person->fatigue_func,
		   p_person->cost
		   );
	
	p_person = p_person->next;

  }
  
  printf("total cost = %f\n", total_cost);  


}

2017,江端さんの技術メモ

/*
  gcc -g hiseiki3.cpp -o hiseiki3
*/

/*
  まず「基本形」を崩す

  非正規社員投入の方針は、
  (1)潜在的な市場が増加中なら投入
  (2)赤字に転じたら、直ちに非正規社員を全員解雇
  という極めて単純なもの
  
  に、

  非正規社員を保護する
  最低3年間は解雇できないもの、としてみる


*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h> 



typedef struct person{
  int age;  // 20歳~60歳 のいずれか
  int position;  // 1:正規社員 0:非正規社員
  double productivity;  // 生産力 正規社員の場合 

  ///////////
  struct person *prev;  /* 前の構造体を示すポインタ */
  struct person *next;  /* 次の構造体を示すポインタ */ 

} PERSON;


typedef struct company{
  int payroll;
  double productivity;  // 会社としての生産力の合計   
} COMPANY;


PERSON *p_first_person, *p_last_person;   //社員リスト(あえてグローバルで保持)

// 社員用リストの先頭と終端を作成するルーチン
/*
  リストの先頭と終端をはグローバルでも良いのであるが、
  一応、メインルーチンの方で、陽に定義できるように、
  ここでは、返り値としている
*/

double min(double a, double b){
    if (b > a) 
        return a;
    else 
        return b;
};

double juglar_cycles(int year)
{
  // 10年で変動するsin周期
  // ベースとするのは2017年とする(単なる仮説)
  
  int x = (year -7) % 10;
  double y = sin( (double)x /10.0 * 2 * 3.141592654);

  return y;
}
  

void init_person_list(PERSON **p_first_person, PERSON **p_last_person)
{
  PERSON *p_top_person = (PERSON *)malloc(sizeof(PERSON));
  if(p_top_person == NULL) {
	printf("メモリが確保できません\n");
	exit(EXIT_FAILURE);
  }
  memset(p_top_person, 0, sizeof(PERSON)); // ゼロクリア


  PERSON *p_tail_person = (PERSON *)malloc(sizeof(PERSON));
  if(p_tail_person == NULL) {
	printf("メモリが確保できません\n");
	exit(EXIT_FAILURE);
  }
  memset(p_tail_person, 0, sizeof(PERSON)); // ゼロクリア

  *p_first_person = p_top_person;
  *p_last_person = p_tail_person;

  (*p_first_person)->prev = NULL;
  (*p_last_person)->next = NULL;
  (*p_first_person)->next = (*p_last_person);
  (*p_last_person)->prev = (*p_first_person);

  return;
}

// 社員オブジェクトを生成して、社員用リストに追加するルーチン
void add_person(PERSON *p_ref_person)
{

  PERSON *new_p_person = (PERSON *)malloc(sizeof(PERSON));
  if(new_p_person == NULL) {
	printf("メモリが確保できません\n");
	exit(EXIT_FAILURE);
  }
  memset(new_p_person, 0, sizeof(PERSON)); // ゼロクリア
  memcpy(new_p_person, p_ref_person, sizeof(PERSON)); // 引数の動的メモリの内容コピー
 
  // personの追加属性記述ここから
 


  // personの追加属性記述ここまで

  PERSON *p_person = p_last_person->prev;

  p_person->next = new_p_person;
  new_p_person->prev = p_person;

  p_last_person->prev = new_p_person;
  new_p_person->next = p_last_person;

  return;
}

void delete_person(PERSON *p_person)  
{
  // ポインタを貼り替えて
  p_person->prev->next = p_person->next;
  p_person->next->prev = p_person->prev;
  
  // そのメモリを解放する
  free(p_person);

  return;

}


int main()
{

  double potential = juglar_cycles(2017) * 1500.0 + 7500.0;
  double border = 7000.0; // 利益のボーダー(固定と考える)

  COMPANY company;
  company.productivity = 7437.500000; // 生産力初期値
  
   // 社員格納用リストの作成
  init_person_list(&p_first_person, &p_last_person); 
  
  //20歳から59歳までの正規社員、各世代100人づつ、合計4000人を作成する
  
  /////// PERSONを作成する ///////
  for (int age = 20; age < 60; age ++){
	for (int i = 0; i < 100; i++){
	  
	  PERSON person;
	  
	  person.age = age;
	  person.position = 1;  // 1:正規社員 0:非正規社員
	  person.productivity = 1.25 + (2.50 -1.25) / 40.0 * ((double)age -20.0); //20歳 1.25 60歳 2.50まで線形変化
	  
	  add_person(&person);
	}
  }
  /////// PERSONを作成する ///////  
 
  double sum_profit = 0;
  
  for ( int year = 2017; year < 2040; year++){
	
	//// 年齢を1歳加算し、定年
	// ===== PERSON ループを回す========
	PERSON* p_person = p_first_person->next;  
	while (p_person != p_last_person){
	  
	  p_person->age += 1;

	  if (p_person->position == 1){ // 正規社員であれば、生産力は年齢とともに高くなる(という仮説)
		p_person->productivity = 1.25 + (2.50 -1.25) / 40.0 * ((double)(p_person->age) -20.0); //20歳 1.25 60歳 2.50まで線形変化
	  }
	  else if (p_person->position == 0){ // 非正規社員であれば、生産力は年齢と関係なく高くならない(という仮説)
		p_person->productivity = 1.0;
	  }
	  
	  if (p_person->age >= 60){ // 60歳になったら定年(正規社員だろうが、非正規社員だろうが) 
		delete_person(p_person);
	  }
	  p_person = p_person->next;
	}
	// ===== PERSON ループを回す(ここまで)========
	
	//// 100人の20歳の新入社員を入社する
	for (int i = 0; i < 100; i++){
	  /////// PERSONを作成する ///////
	  PERSON person;
	  
	  person.age = 20;
	  person.position = 1;  // 1:正規社員 0:非正規社員
	  person.productivity = 1.25 + (2.50 -1.25) / 40.0 * ((double)person.age -20.0); //20歳 1.25 60歳 2.50まで線形変化
	  
	  add_person(&person);
	}

#if 1
	// 昨年の景気ラインと昨年の生産力を比較して、景気ライン > 昨年の生産力 となっていたら、非正規社員を必要分だけ投入する
	int add_person_number;

	if (potential > company.productivity){
	  add_person_number = (int)(potential - company.productivity);
	}
	
	// printf("potential = %f, company.productivity = %f, add_person_number=%d\n",potential, company.productivity, add_person_number);

	for (int i=0; i < add_person_number; i++){
	  PERSON person;

	  person.age = 20; // 若い奴を突っ込むことにする
	  person.position = 0;  // 1:正規社員 0:非正規社員
	  person.productivity = 1.0; // 生産力は"1.0"で固定、かつ年齢とともに成長しない)

	  add_person(&person);
	}

	// 昨年の景気ラインと利益のボーダを比較して 、景気ライン < 利益のボーダ となっていたら、非正規社員を全て即時に解雇する
	
	if (potential - border < 0.0){
	  // ===== PERSON ループを回す========
	  p_person = p_first_person->next;
	  while (p_person != p_last_person){
		
		if (p_person->position == 0){ // 非正規社員
		  if (p_person->age > 25){
			delete_person(p_person);
		  }
		}
		
		p_person = p_person->next;
	  }
	  // ===== PERSON ループを回す(ここまで)========
	}

#endif //0

	potential = juglar_cycles(year) * 1500.0 + 7500.0; // 景気ライン(ジャグラーサイクル)の更新


	/////////// ここから生産力算出ループ

	company.productivity = 0; // 生産力ゼロリセット
	company.payroll = 0 ; // 従業員数ゼロリセット

	// ===== PERSON ループを回す========
	p_person = p_first_person->next;
	while (p_person != p_last_person){
	  
	  company.payroll += 1 ; // 従業員数一人加算
	  company.productivity += p_person->productivity; // 生産力加算
	  
	  p_person = p_person->next;
	}
	// ===== PERSON ループを回す(ここまで)========
	
	//printf("company.payroll = %d\n",company.payroll); // company.payroll = 4000
	//printf("company.productivity = %f\n",company.productivity); // company.productivity = 7437.500000
	
	
	double profit = min(company.productivity, potential) - border;
	sum_profit += profit; 
	
	//printf("year = %d company.productivity = %f potential = %f profit = %f sum_profit=%f payroll=%d\n",year,company.productivity, potential, profit,sum_profit,company.payroll);
	printf("%d,%f,%f,%f,%f,%d\n",year,company.productivity, potential, profit,sum_profit,company.payroll);

	
  } //  for ( int year = 2017; year < 2040; year++){
  
  return 0;
}

2017,江端さんの技術メモ

2/*
  gcc -g birth_digital_native.cpp -o birth_digital_native
*/

/*
  デジタルネイティブ

1992年生まれから人口の100%がディジタルネイティブになったと仮定する。Q:日本のデジタルネイティブの比率は、どう変化していくだろうか
  

*/

#include "stdio.h"

int main(int argc, char* argv[])
{
	double men[101],women[101]; // 年齢別人口 平成22年データ 単位は1000人
	double men_death_rate[101],women_death_rate[101]; // 死亡率 平成22年データ (資料  厚生労働省大臣官房統計情報部人口動態・保健統計課「人口動態統計」)							
	// ファイルデバイスとデータ形式の統一回避する為、データべた書き

	men[ 0]=549   ; men_death_rate[ 0]=2.5/1000.0   ; // 男性0歳人口549千人、死亡率0.25% 2012年生まれ
	men[ 1]=535   ; men_death_rate[ 1]=0.4/1000.0   ; //2011年生まれ
	men[ 2]=535   ; men_death_rate[ 2]=0.2/1000.0   ; //2010年生まれ	
	men[ 3]=550   ; men_death_rate[ 3]=0.2/1000.0   ;	
	men[ 4]=548   ; men_death_rate[ 4]=0.2/1000.0   ;

	men[ 5]=544   ; men_death_rate[ 5]=0.1/1000.0   ;
	men[ 6]=542   ; men_death_rate[ 6]=0.1/1000.0   ;
	men[ 7]=562   ; men_death_rate[ 7]=0.1/1000.0   ;
	men[ 8]=574   ; men_death_rate[ 8]=0.1/1000.0   ;
	men[ 9]=589   ; men_death_rate[ 9]=0.1/1000.0   ; //2003年生まれ	

	men[10]=597   ; men_death_rate[10]=0.1/1000.0   ; //2002年生まれ	
	men[11]=604   ; men_death_rate[11]=0.1/1000.0   ;
	men[12]=604   ; men_death_rate[12]=0.1/1000.0   ;
	men[13]=613   ; men_death_rate[13]=0.1/1000.0   ;
	men[14]=610   ; men_death_rate[14]=0.1/1000.0   ;

	men[15]=607   ; men_death_rate[15]=0.3/1000.0   ;
	men[16]=627   ; men_death_rate[16]=0.3/1000.0   ;
	men[17]=632   ; men_death_rate[17]=0.3/1000.0   ;
	men[18]=621   ; men_death_rate[18]=0.3/1000.0   ; //1990年生まれ (ここまでが、ディタルネイティブ)	
	men[19]=631   ; men_death_rate[19]=0.3/1000.0   ;

	men[20]=623   ; men_death_rate[20]=0.6/1000.0   ; //1992年生まれ	
	men[21]=632   ; men_death_rate[21]=0.6/1000.0   ;
	men[22]=648   ; men_death_rate[22]=0.6/1000.0   ;
	men[23]=668   ; men_death_rate[23]=0.6/1000.0   ;
	men[24]=683   ; men_death_rate[24]=0.6/1000.0   ;

	men[25]=697   ; men_death_rate[25]=0.7/1000.0   ;
	men[26]=723   ; men_death_rate[26]=0.7/1000.0   ;
	men[27]=745   ; men_death_rate[27]=0.7/1000.0   ;
	men[28]=754   ; men_death_rate[28]=0.7/1000.0   ;
	men[29]=754   ; men_death_rate[29]=0.7/1000.0   ;

	men[30]=764   ; men_death_rate[30]=0.8/1000.0   ;
	men[31]=797   ; men_death_rate[31]=0.8/1000.0   ;
	men[32]=818   ; men_death_rate[32]=0.8/1000.0   ;
	men[33]=852   ; men_death_rate[33]=0.8/1000.0   ;
	men[34]=873   ; men_death_rate[34]=0.8/1000.0   ;

	men[35]=917   ; men_death_rate[35]=1.0/1000.0   ;
	men[36]=960   ; men_death_rate[36]=1.0/1000.0   ;
	men[37]=1012  ; men_death_rate[37]=1.0/1000.0   ;
	men[38]=1028  ; men_death_rate[38]=1.0/1000.0   ;
	men[39]=1010  ; men_death_rate[39]=1.0/1000.0   ;

	men[40]=982   ; men_death_rate[40]=1.5/1000.0   ;
	men[41]=954   ; men_death_rate[41]=1.5/1000.0   ;
	men[42]=937   ; men_death_rate[42]=1.5/1000.0   ;
	men[43]=916   ; men_death_rate[43]=1.5/1000.0   ;
	men[44]=915   ; men_death_rate[44]=1.5/1000.0   ;

	men[45]=713   ; men_death_rate[45]=2.4/1000.0   ;
	men[46]=882   ; men_death_rate[46]=2.4/1000.0   ;
	men[47]=826   ; men_death_rate[47]=2.4/1000.0   ;
	men[48]=805   ; men_death_rate[48]=2.4/1000.0   ;
	men[49]=778   ; men_death_rate[49]=2.4/1000.0   ;

	men[50]=765   ; men_death_rate[50]=3.8/1000.0   ;
	men[51]=770   ; men_death_rate[51]=3.8/1000.0   ;
	men[52]=783   ; men_death_rate[52]=3.8/1000.0   ;
	men[53]=761   ; men_death_rate[53]=3.8/1000.0   ;
	men[54]=740   ; men_death_rate[54]=3.8/1000.0   ;

	men[55]=776   ; men_death_rate[55]=6.3/1000.0   ;
	men[56]=803   ; men_death_rate[56]=6.3/1000.0   ;
	men[57]=803   ; men_death_rate[57]=6.3/1000.0   ;
	men[58]=850   ; men_death_rate[58]=6.3/1000.0   ;
	men[59]=896   ; men_death_rate[59]=6.3/1000.0   ;

	men[60]=949   ; men_death_rate[60]=9.3/1000.0   ;
	men[61]=1018  ; men_death_rate[61]=9.3/1000.0   ;
	men[62]=1111  ; men_death_rate[62]=9.3/1000.0   ;
	men[63]=1099  ; men_death_rate[63]=9.3/1000.0   ;
	men[64]=1042  ; men_death_rate[64]=9.3/1000.0   ;

	men[65]=645   ; men_death_rate[65]=14.6/1000.0   ;
	men[66]=684   ; men_death_rate[66]=14.6/1000.0   ;
	men[67]=825   ; men_death_rate[67]=14.6/1000.0   ;
	men[68]=794   ; men_death_rate[68]=14.6/1000.0   ;
	men[69]=809   ; men_death_rate[69]=14.6/1000.0   ;

	men[70]=780   ; men_death_rate[70]=22.7/1000.0   ;
	men[71]=698   ; men_death_rate[71]=22.7/1000.0   ;
	men[72]=599   ; men_death_rate[72]=22.7/1000.0   ;
	men[73]=627   ; men_death_rate[73]=22.7/1000.0   ;
	men[74]=631   ; men_death_rate[74]=22.7/1000.0   ;

	men[75]=616   ; men_death_rate[75]=39.6/1000.0   ;
	men[76]=571   ; men_death_rate[76]=39.6/1000.0   ;
	men[77]=521   ; men_death_rate[77]=39.6/1000.0   ;
	men[78]=501   ; men_death_rate[78]=39.6/1000.0   ;
	men[79]=470   ; men_death_rate[79]=39.6/1000.0   ;

	men[80]=430   ; men_death_rate[80]=70.5/1000.0   ;
	men[81]=385   ; men_death_rate[81]=70.5/1000.0   ;
	men[82]=350   ; men_death_rate[82]=70.5/1000.0   ;
	men[83]=316   ; men_death_rate[83]=70.5/1000.0   ;
	men[84]=281   ; men_death_rate[84]=70.5/1000.0   ;

	men[85]=247   ; men_death_rate[85]=120.3/1000.0   ;
	men[86]=202   ; men_death_rate[86]=120.3/1000.0   ;
	men[87]=158   ; men_death_rate[87]=120.3/1000.0   ;
	men[88]=122   ; men_death_rate[88]=120.3/1000.0   ;
	men[89]=98    ; men_death_rate[89]=120.3/1000.0   ;

	men[90]=78    ; men_death_rate[90]=202.5/1000.0   ;
	men[91]=67    ; men_death_rate[91]=202.5/1000.0   ;
	men[92]=44    ; men_death_rate[92]=202.5/1000.0   ;
	men[93]=36    ; men_death_rate[93]=202.5/1000.0   ;
	men[94]=28    ; men_death_rate[94]=202.5/1000.0   ;

	men[95]=21    ; men_death_rate[95]=318.8/1000.0   ;
	men[96]=15    ; men_death_rate[96]=318.8/1000.0   ;
	men[97]=11    ; men_death_rate[97]=318.8/1000.0   ;
	men[98]=7     ; men_death_rate[98]=318.8/1000.0   ;
	men[99]=5     ; men_death_rate[99]=318.8/1000.0   ;

	women[ 0]=520; women_death_rate[ 0]=2.1/1000.0   ;// 女性0歳人口520千人、死亡率0.21%
	women[ 1]=510; women_death_rate[ 1]=0.4/1000.0   ;
	women[ 2]=511; women_death_rate[ 2]=0.2/1000.0   ;
	women[ 3]=525; women_death_rate[ 3]=0.1/1000.0   ;
	women[ 4]=522; women_death_rate[ 4]=0.1/1000.0   ;

	women[ 5]=518; women_death_rate[ 5]=0.1/1000.0   ;
	women[ 6]=517; women_death_rate[ 6]=0.1/1000.0   ;
	women[ 7]=538; women_death_rate[ 7]=0.1/1000.0   ;
	women[ 8]=545; women_death_rate[ 8]=0.1/1000.0   ;
	women[ 9]=561; women_death_rate[ 9]=0.1/1000.0   ;

	women[10]=568; women_death_rate[10]=0.1/1000.0   ;
	women[11]=573; women_death_rate[11]=0.1/1000.0   ;
	women[12]=576; women_death_rate[12]=0.1/1000.0   ;
	women[13]=585; women_death_rate[13]=0.1/1000.0   ;
	women[14]=583; women_death_rate[14]=0.1/1000.0   ;

	women[15]=578; women_death_rate[15]=0.2/1000.0   ;
	women[16]=595; women_death_rate[16]=0.2/1000.0   ;
	women[17]=597; women_death_rate[17]=0.2/1000.0   ;
	women[18]=589; women_death_rate[18]=0.2/1000.0   ;//1990年生まれ (ここまでが、ディタルネイティブ)	
	women[19]=599; women_death_rate[19]=0.2/1000.0   ;

	women[20]=596; women_death_rate[20]=0.3/1000.0   ;
	women[21]=605; women_death_rate[21]=0.3/1000.0   ;
	women[22]=622; women_death_rate[22]=0.3/1000.0   ;
	women[23]=638; women_death_rate[23]=0.3/1000.0   ;
	women[24]=655; women_death_rate[24]=0.3/1000.0   ;

	women[25]=667; women_death_rate[25]=0.3/1000.0   ;
	women[26]=697; women_death_rate[26]=0.3/1000.0   ;
	women[27]=719; women_death_rate[27]=0.3/1000.0   ;
	women[28]=729; women_death_rate[28]=0.3/1000.0   ;
	women[29]=734; women_death_rate[29]=0.3/1000.0   ;

	women[30]=742; women_death_rate[30]=0.4/1000.0   ;
	women[31]=774; women_death_rate[31]=0.4/1000.0   ;
	women[32]=794; women_death_rate[32]=0.4/1000.0   ;
	women[33]=828; women_death_rate[33]=0.4/1000.0   ;
	women[34]=849; women_death_rate[34]=0.4/1000.0   ;

	women[35]=890; women_death_rate[35]=0.6/1000.0   ;
	women[36]=931; women_death_rate[36]=0.6/1000.0   ;
	women[37]=982; women_death_rate[37]=0.6/1000.0   ;
	women[38]=1001; women_death_rate[38]=0.6/1000.0   ;
	women[39]=981; women_death_rate[39]=0.6/1000.0   ;

	women[40]=958; women_death_rate[40]=0.8/1000.0   ;
	women[41]=931; women_death_rate[41]=0.8/1000.0   ;
	women[42]=920; women_death_rate[42]=0.8/1000.0   ;
	women[43]=902; women_death_rate[43]=0.8/1000.0   ;
	women[44]=898; women_death_rate[44]=0.8/1000.0   ;

	women[45]=705; women_death_rate[45]=1.3/1000.0   ;
	women[46]=872; women_death_rate[46]=1.3/1000.0   ;
	women[47]=815; women_death_rate[47]=1.3/1000.0   ;
	women[48]=798; women_death_rate[48]=1.3/1000.0   ;
	women[49]=772; women_death_rate[49]=1.3/1000.0   ;

	women[50]=760; women_death_rate[50]=1.9/1000.0   ;
	women[51]=768; women_death_rate[51]=1.9/1000.0   ;
	women[52]=783; women_death_rate[52]=1.9/1000.0   ;
	women[53]=765; women_death_rate[53]=1.9/1000.0   ;
	women[54]=744; women_death_rate[54]=1.9/1000.0   ;

	women[55]=783; women_death_rate[55]=2.8/1000.0   ;
	women[56]=810; women_death_rate[56]=2.8/1000.0   ;
	women[57]=813; women_death_rate[57]=2.8/1000.0   ;
	women[58]=868; women_death_rate[58]=2.8/1000.0   ;
	women[59]=918; women_death_rate[59]=2.8/1000.0   ;

	women[60]=975; women_death_rate[60]=3.9/1000.0   ;
	women[61]=1051; women_death_rate[61]=3.9/1000.0   ;
	women[62]=1152; women_death_rate[62]=3.9/1000.0   ;
	women[63]=1146; women_death_rate[63]=3.9/1000.0   ;
	women[64]=1090; women_death_rate[64]=3.9/1000.0   ;

	women[65]=685; women_death_rate[65]=6.0/1000.0   ;
	women[66]=741; women_death_rate[66]=6.0/1000.0   ;
	women[67]=903; women_death_rate[67]=6.0/1000.0   ;
	women[68]=875; women_death_rate[68]=6.0/1000.0   ;
	women[69]=899; women_death_rate[69]=6.0/1000.0   ;

	women[70]=873; women_death_rate[70]=9.8/1000.0   ;
	women[71]=793; women_death_rate[71]=9.8/1000.0   ;
	women[72]=690; women_death_rate[72]=9.8/1000.0   ;
	women[73]=738; women_death_rate[73]=9.8/1000.0   ;
	women[74]=755; women_death_rate[74]=9.8/1000.0   ;

	women[75]=753; women_death_rate[75]=17.9/1000.0   ;
	women[76]=718; women_death_rate[76]=17.9/1000.0   ;
	women[77]=675; women_death_rate[77]=17.9/1000.0   ;
	women[78]=671; women_death_rate[78]=17.9/1000.0   ;
	women[79]=646; women_death_rate[79]=17.9/1000.0   ;

	women[80]=614; women_death_rate[80]=34.3/1000.0   ;
	women[81]=573; women_death_rate[81]=34.3/1000.0   ;
	women[82]=547; women_death_rate[82]=34.3/1000.0   ;
	women[83]=515; women_death_rate[83]=34.3/1000.0   ;
	women[84]=482; women_death_rate[84]=34.3/1000.0   ;

	women[85]=454; women_death_rate[85]=69.1/1000.0   ;
	women[86]=405; women_death_rate[86]=69.1/1000.0   ;
	women[87]=349; women_death_rate[87]=69.1/1000.0   ;
	women[88]=313; women_death_rate[88]=69.1/1000.0   ;
	women[89]=276; women_death_rate[89]=69.1/1000.0   ;

	women[90]=236; women_death_rate[90]=131.2/1000.0   ;
	women[91]=213; women_death_rate[91]=131.2/1000.0   ;
	women[92]=146; women_death_rate[92]=131.2/1000.0   ;
	women[93]=128; women_death_rate[93]=131.2/1000.0   ;
	women[94]=106; women_death_rate[94]=131.2/1000.0   ;

	women[95]=87 ; women_death_rate[95]=238.1/1000.0   ;
	women[96]=63 ; women_death_rate[96]=238.1/1000.0   ;
	women[97]=49 ; women_death_rate[97]=238.1/1000.0   ;
	women[98]=35 ; women_death_rate[98]=238.1/1000.0   ;
	women[99]=25 ; women_death_rate[99]=238.1/1000.0   ;

	for (int year = 2012; year < 2100; year++){ // 2012年から2100年までループ計算
	  
	  double dummy = 0;
	  for(int i = 15; i < 50; i++){  // 特殊出産率の対象 15歳から49歳までの人口加算
		dummy += women[i];
	  }	
	  
	  // 1.4は、特殊出生率 / 35は特殊出生率の対象期間(35年) / 1.05は男性の出生比率
	  double mem_new_birth = dummy * 1.4 / 35.0 * 1.05/(1.05+1.00);
	  double womem_new_birth = dummy * 1.4 / 35.0 * 1.00/(1.05+1.00);	
	  
	  // 1年単位の人口移動 (死亡率も考慮) 
	  for (int k = 99; k >= 0; k--){
		men[k+1] = men[k] * (1.0 - men_death_rate[k]);
		women[k+1] = women[k] * (1.0 - women_death_rate[k]);
		//printf("%d   %f    %f \n", k, men[k], women[k]);					
		
	  }

	  // 新生児の人口を追加
	  men[0] = mem_new_birth;
	  women[0] = womem_new_birth;
	  
	  // 人口総計(年齢99歳まで。100歳以上の人口は無視することにした)
	  double sum_men = 0;
	  double sum_women = 0;
	  
		for (int m = 0; m <= 100; m++){
		  sum_men += men[m];
		  sum_women += women[m];
		}
		
#if 0		
		// ディタルネイティブ人口総計
		double digital_sum_men = 0;
		double digital_sum_women = 0;
		
		int l = year -1990;
		if (l >= 100) l = 100;

		for (int n = 0; n <= l ; n++){
		  digital_sum_men += men[n];
		  digital_sum_women += women[n];
		}
#endif 

#if 0  // ここから江端仮説

		// ディタルネイティブ人口総計
		double digital_sum_men = 0;
		double digital_sum_women = 0;

		// 1970年以後の人は100%デジタルは使えるいう仮説の導入
		
		int l = year -1970;    
		if (l >= 100) l = 100;

		for (int n = 0; n <= l ; n++){
		  digital_sum_men += men[n];
		  digital_sum_women += women[n];
		}

		// 1950-70年にかけてデジタルを使える人は線形に増加した、という仮説の導入
		
		// デジタルネイティブ人口(江端"補正"仮説)
		int p1 = year -1970;  // 例:2020年の時に50歳
		int p2 = year -1950;  // 例:2020年の時に70歳

		for (int i = p1; i < p2 ; i++){  
		  if (i < 100){
			// 例:2020年の時に70歳の人の0%、 60歳の人の50%、50歳の人の100%がデジタルを扱えるとする
			digital_sum_men += men[i] * 1.0 / (double)(p2 - p1) * (double)(p2 - i);
			digital_sum_women += women[i] * 1.0 / (double)(p2 - p1) * (double)(p2 - i);
		  }
		}

#endif 


#if 1
		// 高齢者世代(65歳以上)に特化して計算してみる

		// 人口総計(年齢65歳から99歳まで。100歳以上の人口は無視することにした)
		sum_men = 0;
		sum_women = 0;
		
		for (int m = 65; m <= 100; m++){
		  sum_men += men[m];
		  sum_women += women[m];
		}
		
		// ディタルネイティブ人口総計
		double digital_sum_men = 0;
		double digital_sum_women = 0;

		// 1970年以後の人は100%デジタルは使えるいう仮説の導入
		
		int l = year -1970;    
		if (l >= 100) l = 100;

		for (int n = 65; n <= l ; n++){
		  digital_sum_men += men[n];
		  digital_sum_women += women[n];
		}

		// 1950-70年にかけてデジタルを使える人は線形に増加した、という仮説の導入
		
		// デジタルネイティブ人口(江端"補正"仮説)
		int p1 = year -1970;  // 例:2020年の時に50歳   2017年の時に47歳
		int p2 = year -1950;  // 例:2020年の時に70歳   2017年の時に67歳

		for (int i = p1; i < p2 ; i++){  
		  if ((i >= 65) &&(i < 100)){
			// 例:2020年の時に70歳の人の0%、 60歳の人の50%、50歳の人の100%がデジタルを扱えるとする
			digital_sum_men += men[i] * 1.0 / (double)(p2 - p1) * (double)(p2 - i);
			digital_sum_women += women[i] * 1.0 / (double)(p2 - p1) * (double)(p2 - i);
		  }
		}
#endif

		
		printf("%d,%f,%f,%f\n", year,  sum_men + sum_women, digital_sum_men + digital_sum_women, (digital_sum_men + digital_sum_women)/(sum_men + sum_women) );	
	}
}

2017,江端さんの技術メモ

/*
  g++ -g seat.cpp -o seat
*/

/*
  「上司の帰宅が遅れると、社員の帰宅も遅れる」の仮説検証
*/

#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);

  return d;
}

int main()
{
  PERSON* cheif[SECTION]; 

  // 初期状態 (最初は個人の帰宅時間は、乱数で設定)
  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];
	}
  }

  /*
  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, 2.0, LESS); // 1時間
  condition_MF3 OverTime_Middle(1.0, 2.0, ZERO); // 2時間
  condition_MF3 OverTime_Long(1.0, 2.0, MORE); // 3時間

  // 部長からの距離
  condition_MF3 DistanceFrom_HEAD_Near(7.0, 7.0, LESS); // 7メートル
  condition_MF3 DistanceFrom_HEAD_Middle(7.0, 7.0, ZERO); // 14メートル
  condition_MF3 DistanceFrom_HEAD_Far(7.0, 7.0, MORE); // 21メートル

  // 課長からの距離
  condition_MF3 DistanceFrom_CHIEF_Near(1.5, 1.5, LESS); // 1.5メートル
  condition_MF3 DistanceFrom_CHIEF_Middle(1.5, 1.5, ZERO); // 3.0メートル
  condition_MF3 DistanceFrom_CHIEF_Far(1.5, 1.5, MORE); // 4.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.01; // 一番後ろで加算すると忘れそうなので
	printf("present_time = %f\n",  present_time);

	// 部の中の課の全体状況の把握

	if (person[0].expected_return_time < present_time){  // 部長は特別あつかい
	  person[0].absences = 0;
	}

	int staying_count[SECTION] ={}; // 各課(Section)で残っている人数を格納(最初はゼロリセット)
  
	for (int i = 0; i < ALL_PERSON_COUNTER; i++){
	  if (person[i].absences == 1){
		staying_count[person[i].section] += 1;  // (Section)に一人追加
	  }
	}

	printf("time = %f, %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]);
	
	for (int i = 1; i < ALL_PERSON_COUNTER; i++){ // person[0]の部長は神様→誰からも影響を受けない(とする)

	  /* 
	 [ルール1]
	 全社員は、予定時間の1時間のまでの帰宅度数0.0
	           1時間から2時間までの帰宅度数0.5 
	           2時間以上の帰宅度数1.0 
	  */

	  double r11 = min(OverTime_Short.func(present_time - person[i].expected_return_time));
	  GoingHome_Hard.func_Max(r11);
	  
	  double r12 = min( OverTime_Middle.func(present_time - person[i].expected_return_time));
	  GoingHome_Middle.func_Max(r12);
	  
	  double r13 = min(OverTime_Long.func(present_time - person[i].expected_return_time));
	  GoingHome_Easy.func_Max(r13);


	  if (person[i].post == CHIEF){ // 課長の場合の付加条件
		/*
		  ルール2
		  部長が残っている場合、部長から5m以内の課長は、帰宅度数0.0
		  5m~10m以内の課長は、帰宅度数0.5
		  10m以上の課長は、帰宅度数1.0
		*/
		
		double dis = distance(&person[0], &person[i]);
		
		double r21 = min((double)(person[0].absences), DistanceFrom_HEAD_Near.func(dis));
		GoingHome_Hard.func_Max(r21);
		
		double r22 = min((double)(person[0].absences), DistanceFrom_HEAD_Middle.func(dis));
		GoingHome_Middle.func_Max(r22);
		
		double r23 = min((double)(person[0].absences), DistanceFrom_HEAD_Far.func(dis));
		GoingHome_Easy.func_Max(r23);
		GoingHome_Middle.func_Max(r23);
	  }
	  


	  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 r31 = min((double)(cheif[person[i].section]->absences), DistanceFrom_CHIEF_Near.func(dis));
		GoingHome_Hard.func_Max(r31);
		
		double r32 = min((double)(cheif[person[i].section]->absences), DistanceFrom_CHIEF_Middle.func(dis));
		GoingHome_Middle.func_Max(r32);
		
		double r33 = min((double)(cheif[person[i].section]->absences), DistanceFrom_CHIEF_Far.func(dis));
		GoingHome_Easy.func_Max(r33);
		GoingHome_Middle.func_Max(r33);
	  }

#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 (person[i].going_home_ratio > 0.5){
		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;
}