待ち行列(複雑な例)

<?php

/******************************/
/* 複雑な待ち行列問題         */
/*      coded by Y.Suganuma   */
/******************************/

/**********************/
/* 指数分布乱数の発生 */
/*      m : 平均値    */
/*      rerutn : 乱数 */
/**********************/
function Exp_b($m)
{
	return -$m * log(mt_rand() / mt_getrandmax());
}

/*********************/
/* クラスInletの定義 */
/*********************/
class Inlet {
	public $name;   // 入り口名
	public $out;   // 待ち行列名
	public $out_n;   // 待ち行列番号
	public $arrive_time;   // 客の到着時刻(負:客がない)
	public $a_t;   // = -n : 到着する客の人数を負の値にしたもの
		           // =0 : 指数分布
		           // =1 : 一定時間間隔
	public $mean;   // 到着時間間隔またはその平均
	public $que;   // 客の到着時刻リスト

	/*************************************************************/
	/* コンストラクタ                                            */
	/*      name1 : 入り口名                                     */
	/*      a_t1;   // = -n : 到着する客の人数を負の値にしたもの */
	/*              // =0 : 指数分布                             */
	/*              // =1 : 一定時間間隔                         */
	/*      m_a: 到着時間間隔またはその平均                     */
	/*      que1 : 客の到着時刻リスト                            */
	/*      name2 : 待ち行列名                                   */
	/*************************************************************/
	function Inlet ($name1, $a_t1, $m_a, $que1, $name2)
	{
		$this->name = $name1;
		$this->out  = $name2;
		$this->a_t  = $a_t1;
		$this->mean = $m_a;
		if ($this->a_t == 0)
			$this->arrive_time = Exp_b($this->mean);
		else if ($this->a_t == 1)
			$this->arrive_time = 0;
		else {
			$this->que         = $que1;
			$this->arrive_time = array_shift($this->que);
		}
	}
}

/*********************/
/* クラスQueueの定義 */
/*********************/
class Queue {
	public $name;   // 待ち行列名
	public $nc;   // 待ち行列への到着客数カウンタ
	public $max_q_l;   // 最大待ち行列長
	public $c_ql;   // 待ち行列長にその長さが継続した時間を乗じた値の累計
	public $ql_t;   // 現在の待ち行列長になった時間
	public $max_wt;   // 最大待ち時間
	public $c_wt;   // 待ち時間の累計
	public $n;   // =0 : 入り口から入る
	             // >0 : 複数の窓口から入る(窓口数)
	public $in;   // 入り口名,または,窓口名
	public $in_n;   // 入り口番号,または,窓口番号
	public $m;   // 処理する窓口数
	public $out;   // 窓口名
	public $out_n;   // 窓口番号
	public $que;   // 待ち行列

	/*********************************************/
	/* コンストラクタ                            */
	/*      name1 : 待ち行列名                   */
	/*      n1 : =0 : 入り口から入る             */
	/*           >0 : 複数の窓口から入る(窓口数) */
	/*      in1 : 入り口名,または,窓口名       */
	/*      m1 : 処理する窓口数                  */
	/*      out1 : 窓口名                        */
	/*********************************************/
	function Queue($name1, $n1, $in1, $m1, $out1)
	{
		$this->name    = $name1;
		$this->n       = $n1;
		$this->in      = $in1;
		$this->m       = $m1;
		$this->out     = $out1;
		$this->nc      = 0;
		$this->max_q_l = 0;
		$this->c_ql    = 0.0;
		$this->ql_t    = 0.0;
		$this->max_wt  = 0.0;
		$this->c_wt    = 0.0;
		$this->in_n    = array();
		$this->out_n   = array();
		$this->que     = array();
	}
}

/**********************/
/* クラスEntityの定義 */
/**********************/
class Entity {
	public $name;   // 窓口名
	public $end_time;   // サービス終了時刻(負:何も処理していない)
	public $s_t;   // =0 : 指数分布
	               // =1 : 一定時間
	public $mean;   // 平均サービス時間
	public $busy_t;   // 窓口がふさがった時刻
	public $c_busy;   // 窓口がふさがっている時間の累計
	public $service;   // サービス中の客番号(0のときは無し)
	public $in;   // 待ち行列(入力)の名前
	public $in_n;   // 待ち行列(入力)番号
	public $to;   // =0 : システムの外に出る
	              // =1 : 待ち行列に入る
	public $out;   // 待ち行列(出力)の名前
	public $out_n;   // 待ち行列(出力)番号
	
	/****************************************/
	/* コンストラクタ                       */
	/*      name1 : 窓口名                  */
	/*      s_t1;   // =0 : 指数分布        */
	/*              // =1 : 一定時間        */
	/*      m_s:サービス時間またはその平均 */
	/*      name2 : 待ち行列(入力)の名前    */
	/*      sw : =0 : システムの外に出る    */
	/*           =1 : 待ち行列に入る        */
	/*      name3 : 待ち行列(出力)の名前    */
	/**********************************+++***/
	function Entity($name1, $s_t1, $m_s, $name2, $sw, $name3)
	{
		$this->name = $name1;
		$this->to   = $sw;
		$this->in   = $name2;
		if ($this->to > 0)
			$this->out = $name3;
		$this->end_time = -1.0;
		$this->s_t      = $s_t1;
		$this->mean     = $m_s;
		$this->service  = 0;
		$this->busy_t   = -1.0;
		$this->c_busy   = 0.0;
	}
}

/************************/
/* クラスCustomerの定義 */
/************************/
class Customer
{
	public $time;   // 到着時刻
	public $state1;   // 客の状態1
                      //   =0 : 待ち行列に入っている
                      //   =1 : サービスを受けている
	public $state2;   // 客の状態2(待ち行列番号,または,窓口番号)

	/*********************/
	/* コンストラクタ    */
	/*      s1,s2 : 状態 */
	/*      t : 到着時刻 */
	/*******************************/
	function Customer($s1, $s2, $t)
	{
		$this->time   = $t;
		$this->state1 = $s1;
		$this->state2 = $s2;
	}
}

/**********************/
/* クラスQ_baseの定義 */
/**********************/
class Q_base {
	public $p_time;  // 現在時刻
	public $max_c;   // 最大系内客数
	public $nc;   // システムへの到着客数カウンタ
	public $now_c_t;   // 現在の系内客数になった時間
	public $c_now_c;   // 系内客数にその数が継続した時間を乗じた値の累計
	public $c_sys;   // 滞在時間の累計
	public $max_sys;   // 最大滞在時間
	public $end;   // シミュレーション終了時間
	public $cus;   // 系内にいる客のリスト
	public $inl;   // Inletオブジェクトリスト
	public $que;   // Queueオブジェクトリスト
	public $ent;   // Entityオブジェクトリスト

	/***************************************/
	/* コンストラクタ                      */
	/*      v_i : Inletオブジェクトリスト  */
	/*      v_q : Queueオブジェクトリスト  */
	/*      v_e : Entityオブジェクトリスト */
	/*      e : シミュレーション終了時刻   */
	/***************************************/
	function Q_base($v_i, $v_q, $v_e, $e)
	{
				// 接続関係のチェック
		print("\n");
						// Inlet
		$this->inl = $v_i;
		$this->que = $v_q;
		$this->ent = $v_e;
		for ($i1 = 0; $i1 < count($this->inl)-1; $i1++) {
			for ($i2 = $i1+1; $i2 < count($this->inl); $i2++) {
				if ($this->inl[$i1]->name == $this->inl[$i2]->name)
					exit("***error 同じ名前の入り口があります ".$this->inl[$i1]->name."\n");
			}
		}

		$k;
		for ($i1 = 0; $i1 < count($this->inl); $i1++) {
			$k = -1;
			for ($i2 = 0; $i2 < count($this->que); $i2++) {
				if ($this->inl[$i1]->out == $this->que[$i2]->name) {
					$k = $i2;
					break;
				}
			}
			if ($k >= 0)
				$this->inl[$i1]->out_n = $k;
			else
				exit("***error 入り口から入る待ち行列名が不適当です ".$this->inl[$i1]->out."\n");
		}
						// Queue
		for ($i1 = 0; $i1 < count($this->que)-1; $i1++) {
			for ($i2 = $i1+1; $i2 < count($this->que); $i2++) {
				if ($this->que[$i1]->name == $this->que[$i2]->name)
					exit("***error 同じ名前の待ち行列があります ".$this->que[$i1]->name."\n");
			}
		}

		for ($i1 = 0; $i1 < count($this->que); $i1++) {
			if ($this->que[$i1]->n == 0) {
				$k = -1;
				for ($i2 = 0; $i2 < count($this->inl); $i2++) {
					if ($this->que[$i1]->in[0] == $this->inl[$i2]->name) {
						$k = $i2;
						break;
					}
				}
				if ($k >= 0)
					array_push($this->que[$i1]->in_n, $k);
				else
					exit("***error 待ち行列に入る入り口名が不適当です ".$this->que[$i1]->in[0]."\n");
			}
			else {
				for ($i2 = 0; $i2 < $this->que[$i1]->n; $i2++) {
					$k = -1;
					for ($i3 = 0; $i3 < count($this->ent); $i3++) {
						if ($this->que[$i1]->in[$i2] == $this->ent[$i3]->name) {
							$k = $i3;
							break;
						}
					}
					if ($k >= 0)
						array_push($this->que[$i1]->in_n, $k);
					else
						exit("***error 待ち行列に入る窓口名が不適当です ".$this->que[$i1]->in[$i2]."\n");
				}
			}
			for ($i2 = 0; $i2 < $this->que[$i1]->m; $i2++) {
				$k = -1;
				for ($i3 = 0; $i3 < count($this->ent); $i3++) {
					if ($this->que[$i1]->out[$i2] == $this->ent[$i3]->name) {
						$k = $i3;
						break;
					}
				}
				if ($k >= 0)
					array_push($this->que[$i1]->out_n, $k);
				else
					exit("***error 待ち行列を処理する窓口名が不適当です ".$this->que[$i1]->out[$i2]."\n");
			}
		}
						// Entity
		for ($i1 = 0; $i1 < count($this->ent)-1; $i1++) {
			$k = -1;
			for ($i2 = $i1+1; $i2 < count($this->ent); $i2++) {
				if ($this->ent[$i1]->name == $this->ent[$i2]->name)
					exit("***error 同じ名前の窓口があります ".$this->ent[$i1]->name."\n");
			}
		}

		for ($i1 = 0; $i1 < count($this->ent); $i1++) {
			$k = -1;
			for ($i2 = 0; $i2 < count($this->que); $i2++) {
				if ($this->ent[$i1]->in == $this->que[$i2]->name) {
					$k = $i2;
					break;
				}
			}
			if ($k >= 0)
				$this->ent[$i1]->in_n = $k;
			else
				exit("***error 窓口に入る待ち行列名が不適当です ".$this->ent[$i1]->in."\n");
			if ($this->ent[$i1]->to > 0) {
				$k = -1;
				for ($i2 = 0; $i2 < count($this->que); $i2++) {
					if ($this->ent[$i1]->out == $this->que[$i2]->name) {
						$k = $i2;
						break;
					}
				}
				if ($k >= 0)
					$this->ent[$i1]->out_n = $k;
				else
					exit("***error 窓口の出口にある待ち行列名が不適当です ".$this->ent[$i1]->out."\n");
			}
		}
				// 初期設定
		$this->p_time  = 0.0;
		$this->max_c   = 0;
		$this->nc      = 0;
		$this->now_c_t = 0.0;
		$this->c_now_c = 0.0;
		$this->c_sys   = 0.0;
		$this->max_sys = 0.0;
		$this->end     = $e;
		$this->cus     = array();
				// 乱数の初期設定
		mt_srand();
	}

	/**************/
	/* 全体の制御 */
	/**************/
	function Control()
	{
		$sw    = array(2);
		$sw[0] = 0;
		while ($sw[0] > -2) {
			$this->Next($sw);   // 次の処理の選択
			if ($sw[0] == -1)
				$sw[0] = $this->End_o_s();   // シミュレーションの終了
			else {
				if ($sw[0] == 0)
					$this->Arrive($sw[1]);   // 客の到着処理
				else
					$this->Service($sw[1]);   // サービスの終了
			}
		}
	}
	
	/*********************************************/
	/* 次の処理の決定                            */
	/*      sw[0] : =-1 : シミュレーションの終了 */
	/*              =0  : 客の到着処理           */
	/*              =1  : 窓口のサービス終了     */
	/*        [1] : 入り口番号 or 窓口番号       */
	/*********************************************/
	function Next(&$sw)
	{
		$tm    = $this->end;   // 次の処理時刻
		$sw[0] = -1;
						// 次の客の到着時刻
		for ($i1 = 0; $i1 < count($this->inl); $i1++) {
			$x = $this->inl[$i1];
			if ($x->arrive_time >= 0.0 && $x->arrive_time < $tm) {
				$sw[0] = 0;
				$sw[1] = $i1;
				$tm    = $x->arrive_time;
			}
		}
						// サービス終了時刻
		for ($i1 = 0; $i1 < count($this->ent); $i1++) {
			$x = $this->ent[$i1];
			if ($x->service > 0 && $x->end_time <= $tm) {
				$sw[0] = 1;
				$sw[1] = $i1;
				$tm    = $x->end_time;
			}
		}
	
		if ($sw[0] < 0)
			$this->end = $this->p_time;
	}
	
	/**********************************/
	/* 終了処理                       */
	/*      return : =-1 : 終了前処理 */
	/*               =-2 : 実際の終了 */
	/**********************************/
	function End_o_s()
	{
		$sw           = -2;
		$this->p_time = $this->end;   // 現在時刻
	
		for ($i1 = 0; $i1 < count($this->ent); $i1++) {
			$x = $this->ent[$i1];
			if ($x->service > 0) {   // サービス中の客はいるか?
				if ($sw == -2) {
					$sw = -1;
					$this->end = $x->end_time;   // 窓口$i1のサービス終了時刻
				}
				else {
					if ($x->end_time > $this->end)
						$this->end = $x->end_time;   // 窓口$i1のサービス終了時刻
				}
			}
		}
	
		return $sw;
	}
	
	/************************/
	/* 客の到着処理         */
	/*      kk : 入り口番号 */
	/************************/
	function Arrive($kk)
	{
	/*
	          客数の増加と次の客の到着時刻の設定
	*/
		$this->nc     += 1;   // 到着客数カウンタ
		$this->p_time  = $this->inl[$kk]->arrive_time;   // 現在時刻
		if ($this->inl[$kk]->a_t == 0)   // 次の客の到着時刻
			$this->inl[$kk]->arrive_time = $this->p_time + Exp_b($this->inl[$kk]->mean);   
		else if ($this->inl[$kk]->a_t == 1)
			$this->inl[$kk]->arrive_time = $this->p_time + $this->inl[$kk]->mean;   
		else {
			if (count($this->inl[$kk]->que) <= 0)
				$this->inl[$kk]->arrive_time = -1.0;
			else
				$this->inl[$kk]->arrive_time = array_shift($this->inl[$kk]->que);
		}
		if ($this->inl[$kk]->arrive_time >= $this->end)
			$this->inl[$kk]->arrive_time = -1.0;
	/*
	          系内客数の処理
	*/
		$this->c_now_c += count($this->cus) * ($this->p_time - $this->now_c_t);   // 系内客数にその数が継続した時間を乗じた値の累計
		$this->now_c_t  = $this->p_time;   // 現在の系内客数になった時刻
		if (count($this->cus)+1 > $this->max_c)
			$this->max_c = count($this->cus) + 1;   // 最大系内客数
	/*
	          空いている窓口を探す
	*/
		$k1 = $this->inl[$kk]->out_n;
		$this->que[$k1]->nc++;
		$k = -1;
		for ($i1 = 0; $i1 < $this->que[$k1]->m; $i1++) {
			$k2 = $this->que[$k1]->out_n[$i1];   // 処理窓口
			if ($this->ent[$k2]->service == 0) {
				$k = $k2;
				break;
			}
		}
	/*
	          窓口に空きがない場合
	*/
		if ($k < 0) {
			$ct_p = new Customer(0, $k1, $this->p_time);
			$this->cus['no'.strval($this->nc)] = $ct_p;   // 客の登録(系内客数)
			$this->que[$k1]->c_ql += count($this->que[$k1]->que) * ($this->p_time - $this->que[$k1]->ql_t);   // 待ち行列長にその長さが継続した時間を乗じた値の累計
			array_push($this->que[$k1]->que, $this->nc);   // 客の登録(待ち行列)
			$this->que[$k1]->ql_t = $this->p_time;   // 現在の待ち行列長になった時刻
			if (count($this->que[$k1]->que) > $this->que[$k1]->max_q_l)
				$this->que[$k1]->max_q_l = count($this->que[$k1]->que);   // 最大待ち行列長
		}
	/*
	          すぐサービスをうけられる場合
	*/
		else {
			$ct_p = new Customer(1, $k, $this->p_time);
			$this->cus['no'.strval($this->nc)] = $ct_p;   // 客の登録(系内客数)
			$this->ent[$k]->service = $this->nc;   // サービスを受けている客番号
			$this->ent[$k]->busy_t  = $this->p_time;   // 窓口がふさがった時刻
			if ($this->ent[$k]->s_t == 0)   // 窓口のサービス終了時刻
				$this->ent[$k]->end_time = $this->p_time + Exp_b($this->ent[$k]->mean);
			else
				$this->ent[$k]->end_time = $this->p_time + $this->ent[$k]->mean;
		}
	}
	
	/**********************************/
	/* サービス終了時の処理           */
	/*      kk : サービス終了窓口番号 */
	/**********************************/
	function Service($kk)
	{
	/*
	          時間の設定
	*/
		$this->p_time = $this->ent[$kk]->end_time;   // 現在時刻
		$this->ent[$kk]->end_time = -1.0;   // サービス終了時間
	/*
	          システムの外へ出る場合
	*/
		if ($this->ent[$kk]->to == 0) {
	/*
	               系内客数の処理
	*/
			$this->c_now_c += count($this->cus) * ($this->p_time - $this->now_c_t);   // 系内客数にその数が継続した時間を乗じた値の累計
			$this->now_c_t  = $this->p_time;   // 現在の系内客数になった時刻
	/*
	               滞在時間の処理
	*/
			$it = $this->cus['no'.strval($this->ent[$kk]->service)];   // サービス中の客
			$x1 = $this->p_time - $it->time;
			$this->c_sys += $x1;   // 滞在時間の累計
			if ($x1 > $this->max_sys)
				$this->max_sys = $x1;   // 最大滞在時間
			unset($this->cus['no'.strval($this->ent[$kk]->service)]);   // 客の削除(系内客数)
		}
	/*
	          他の窓口処理へ入る場合の処理
	*/
		else {
			$k1 = $this->ent[$kk]->out_n;
			$this->que[$k1]->nc++;
			$sw = 1;
			$k2 = 0;
			if (count($this->que[$k1]->que) == 0) {
				for ($i1 = 0; $i1 < $this->que[$k1]->m; $i1++) {
					$k2 = $this->que[$k1]->out_n[$i1];   // 窓口
					if ($this->ent[$k2]->service == 0) {
						$sw = 0;
						break;
					}
				}
			}
	/*
	               待ち行列がある場合
	*/
			if ($sw > 0) {
				$this->que[$k1]->c_ql += count($this->que[$k1]->que) * ($this->p_time - $this->que[$k1]->ql_t);   // 待ち行列長にその長さが継続した時間を乗じた値の累計
				array_push($this->que[$k1]->que, $this->ent[$kk]->service);   // 客の登録(待ち行列)
				$this->que[$k1]->ql_t = $this->p_time;   // 現在の待ち行列長になった時刻
				if (count($this->que[$k1]->que) > $this->que[$k1]->max_q_l)
					$this->que[$k1]->max_q_l = count($this->que[$k1]->que);   // 最大待ち行列長
				$it = $this->cus['no'.strval($this->ent[$kk]->service)];
				$it->state1 = 0;   // 客の状態変更(待ち行列)
				$it->state2 = $this->ent[$kk]->out_n;   // 客の状態変更(待ち行列番号)
			}
	/*
	               すぐサービスをうけられる場合
	*/
			else {
				$this->ent[$k2]->service = $this->ent[$kk]->service;   // サービスを受けている客番号
				$this->ent[$k2]->busy_t  = $this->p_time;   // 窓口がふさがった時刻
				if ($this->ent[$k2]->s_t == 0)   // 窓口のサービス終了時刻
					$this->ent[$k2]->end_time = $this->p_time + Exp_b($this->ent[$k2]->mean);
				else
					$this->ent[$k2]->end_time = $this->p_time + $this->ent[$k2]->mean;
			}
		}
	/*
	          窓口使用時間の処理
	*/
		$this->ent[$kk]->service  = 0;   // 窓口を空き状態にする
		$this->ent[$kk]->c_busy  += ($this->p_time - $this->ent[$kk]->busy_t);   // 窓口がふさがっている時間の累計
	/*
	          この窓口に対する待ち行列がある場合
	*/
		$k3 = $this->ent[$kk]->in_n;
		if (count($this->que[$k3]->que) > 0) {
			$this->que[$k3]->c_ql += count($this->que[$k3]->que) * ($this->p_time - $this->que[$k3]->ql_t);   // 待ち行列長にその長さが継続した時間を乗じた値の累計
			$n = array_shift($this->que[$k3]->que);   // 待ち行列の先頭にいる客
			$this->que[$k3]->ql_t = $this->p_time;   // 現在の待ち行列長になった時刻
			$it = $this->cus['no'.$n];
			$x1 = $this->p_time - $it->time;
			$this->que[$k3]->c_wt += $x1;   // 待ち時間の累計
			if ($x1 > $this->que[$k3]->max_wt)
				$this->que[$k3]->max_wt = $x1;   // 最大待ち時間
			for ($i1 = 0; $i1 < $this->que[$k3]->m; $i1++) {
				$k4 = $this->que[$k3]->out_n[$i1];   // 窓口
				if ($this->ent[$k4]->service == 0) {
					$this->ent[$k4]->service = $n;   // 窓口の客番号
					$this->ent[$k4]->busy_t  = $this->p_time;   // 窓口がふさがった時刻
					if ($this->ent[$k4]->s_t == 0)   // 窓口のサービス終了時刻
						$this->ent[$k4]->end_time = $this->p_time + Exp_b($this->ent[$k4]->mean);
					else
						$this->ent[$k4]->end_time = $this->p_time + $this->ent[$k4]->mean;
					$it->state1 = 1;   // 客の状態変更(サービス中)
					$it->state2 = $k4;   // 客の状態変更(窓口番号)
					break;
				}
			}
		}
	}
	
	/**************************/
	/* 統計量の計算と最終出力 */
	/**************************/
	function Output()
	{
						// System
		printf("全客数 %d", $this->nc);
		printf(" 最大系内客数 %d 最大滞在時間 %.3f\n", $this->max_c, $this->max_sys);
		printf("平均系内客数 %.3f", $this->c_now_c / $this->p_time);
		printf(" 平均滞在時間 %.3f", $this->c_sys / $this->nc);
		printf(" 終了時間 %.3f\n", $this->p_time);
						// Entity
		for ($i1 = 0; $i1 < count($this->ent); $i1++) {
			$e = $this->ent[$i1];
			print("Entity ".$e->name);
			printf(" 稼働率 %.3f\n", $e->c_busy / $this->p_time);
		}
						// Queue
		for ($i1 = 0; $i1 < count($this->que); $i1++) {
			$q = $this->que[$i1];
			print("Queue ".$q->name);
			printf(" 客数 %d", $q->nc);
			printf("   最大待ち行列長 %d", $q->max_q_l);
			printf("   最大待ち時間 %.3f\n", $q->max_wt);
			printf("      平均待ち行列長 %.3f", $q->c_ql / $this->p_time);
			printf("   平均待ち時間 %.3f\n", $q->c_wt / $q->nc);
		}
	}
}
	
/****************/
/* main program */
/****************/
					// 入り口
	printf("入り口(Inlet)の数は? ");
	fscanf(STDIN, "%d", $n_i);
	$inl = array();
	for ($i1 = 0; $i1 < $n_i; $i1++) {
		printf("%d 番目の入り口(Inlet)\n", $i1+1);
		printf("     名前は? ");
		fscanf(STDIN, "%s", $name1);
		$que = array();
		printf("     到着分布(=0:指数分布,=1:一定時間間隔,<0:指定,客数の負値)? ");
		fscanf(STDIN, "%d", $n);
		if ($n == 0) {
			printf("          到着時間間隔の平均値は? ");
			fscanf(STDIN, "%lf", $m_a);
		}
		else if ($n == 1) {
			printf("          到着時間間隔は? ");
			fscanf(STDIN, "%lf", $m_a);
		}
		else {
			for ($i2 = 0; $i2 < -$n; $i2++) {
				printf("          到着時間は? ");
				fscanf(STDIN, "%lf", $x);
				array_push($que, $x);
			}
		}
		printf("     並ぶ待ち行列の名前は? ");
		fscanf(STDIN, "%s", $name2);
		$inl_e = new Inlet($name1, $n, $m_a, $que, $name2);
		array_push($inl, $inl_e);
	}
					// 待ち行列
	printf("待ち行列(Queue)の数は? ");
	fscanf(STDIN, "%d", $n_q);
	$que = array();
	for ($i1 = 0; $i1 < $n_q; $i1++) {
		printf("%d 番目の待ち行列(Queue)\n", $i1+1);
		printf("     名前は? ");
		fscanf(STDIN, "%s", $name1);
		printf("     入り口(0),または,窓口(n>0,窓口の数)から? ");
		fscanf(STDIN, "%d", $n);
		$in = array();
		if ($n == 0) {
			printf("          入り口の名前は? ");
			fscanf(STDIN, "%s", $name2);
			array_push($in, $name2);
		}
		else {
			for ($i2 = 0; $i2 < $n; $i2++) {
				printf("          %d 番目の窓口の名前は? ", $i2+1);
				fscanf(STDIN, "%s", $name3);
				array_push($in, $name3);
			}
		}
		printf("     処理する窓口の数は? ");
		fscanf(STDIN, "%d", $m);
		$out = array();
		for ($i2 = 0; $i2 < $m; $i2++) {
			printf("          %d 番目の窓口の名前は? ", $i2+1);
			fscanf(STDIN, "%s", $name4);
			array_push($out, $name4);
		}
		$que_e = new Queue($name1, $n, $in, $m, $out);
		array_push($que, $que_e);
	}
					// 窓口
	printf("窓口(Entity)の数は? ");
	fscanf(STDIN, "%d", $n_e);
	$ent = array();
	for ($i1 = 0; $i1 < $n_e; $i1++) {
		printf("%d 番目の窓口(Entity)\n", $i1+1);
		printf("     名前は? ");
		fscanf(STDIN, "%s", $name1);
		printf("     サービス分布(=0:指数分布,=1:一定時間)? ");
		fscanf(STDIN, "%d", $s_t);
		if ($s_t == 0) {
			printf("          サービス時間の平均値は? ");
			fscanf(STDIN, "%lf", $m_s);
		}
		else {
			printf("          サービス時間は? ");
			fscanf(STDIN, "%lf", $m_s);
		}
		printf("     待ち行列(入力)の名前は? ");
		fscanf(STDIN, "%s", $name2);
		printf("     終了後,外部(0),または,待ち行列(1)? ");
		fscanf(STDIN, "%d", $sw);
		$name3 = "";
		if ($sw > 0) {
			printf("          待ち行列(出力)の名前は? ");
			fscanf(STDIN, "%s", $name3);
		}
		$ent_e = new Entity($name1, $s_t, $m_s, $name2, $sw, $name3);
		array_push($ent, $ent_e);
	}
					// 全体の制御を行うクラス
	printf("シミュレーション終了時間? ");
	fscanf(STDIN, "%lf", $end);

	$base = new Q_base($inl, $que, $ent, $end);   // 全体の制御を行うクラス
					// 実行
	$base->Control();
					// 出力
	$base->Output();

/*
------------入力例(簡単な場合)-----------
1
  Inlet
    0
    5
    Queue
1
  Queue
    0
      Inlet
    2
      Entity1
      Entity2
2
  Entity1
    0
      4
    Queue
    0
  Entity2
    0
      4
    Queue
    0
10000

------------入力例(複雑な場合)-----------
2
  Inlet1
    0
      5
    Queue1
  Inlet2
    0
      5
    Queue2
3
  Queue1
    0
      Inlet1
    1
      Entity1
  Queue2
    0
      Inlet2
    1
      Entity2
  Queue3
    2
      Entity1
      Entity2
    2
      Entity3
      Entity4
4
  Entity1
    0
      4
    Queue1
    1
      Queue3
  Entity2
    0
      4
    Queue2
    1
      Queue3
  Entity3
    0
      3
    Queue3
    0
  Entity4
    0
      3
    Queue3
    0
10000
*/

?>