スケジュール管理手法PERT-Time 解 説 “最早開始時間計算のアルゴリズム”
【 最早開始時間計算アルゴリズムはどこに役立つか 】 ① 多数の仕事を多くの人が協力して行うとき,遅くても 【 最早開始時間計算アルゴリズムはどこに役立つか 】 ① 多数の仕事を多くの人が協力して行うとき,遅くても いつまで仕事が終わるか事前に計算するアルゴリズム. 「スケジュール管理」の標準アルゴリズムとして有名. (実用上は,最も重点的に管理すべきクリティカルパスや作業工程が どの程度余裕があるかの日数計算等の計算も含む) ② 最短経路探索と同様に,情報処理技術者試験にもよく 出題される代表的なアルゴリズム (とゆうことは ソフトウェア開発技術者が知っておくべき基本的な アルゴリズム).
【問題】 グループを組んで,以下のような作業項目と作業日数を もつプログラムを開発するとしたとき,このプログラムは最も早く 【問題】 グループを組んで,以下のような作業項目と作業日数を もつプログラムを開発するとしたとき,このプログラムは最も早く て何日後に完成するか? (注)“データベーススキーマ設計”と“CGIプログラムの調査”が終わらないと次の作業“CGIプログラムの設計”は開始できない. CGIプログラムの設計 12日 4 6 データベースのスキーマ設計 CGIプログラム作成&テスト 5日 9日 プログラム機能の決定 8日 DBアクセス プログラム作成 総合テスト 7日 1 5日 2 4日 7 8 CGIプログラムの調査 3日 6日 10日 3 5 画面設計 ホームページ作成 HTML調査とデザイン 《 C/S型プログラム開発作業を例としたアローダイアグラム 》
基本的な考え方は,すべて最短経路探索と同じ. 1 基本的な考え方は,すべて最短経路探索と同じ. トークンを同じ速さで移動させる. 12日 4 6 5日 9日 8日 5日 7日 1 2 4日 7 8 6日 10日 3 5 3日
トークンの移動結果を各ノードに記録して置く 2 トークンの移動結果を各ノードに記録して置く 14 2 2 -∞ - 2 -∞ - 2 1 経由時間合計 1つ前の経由ノード ノードに入ってくる 入力アークの数 (あらかじめ計算) ノード4に入ってくる入力アーク数 12日 4 6 5 1 1 -∞ - 1 -∞ - 2 1 5日 9日 8日 7日 1 5日 2 4日 7 8 -∞ - 2 3 6日 10日 3 5 3日 -∞ - 1 8 2 1 -∞ - 1
トークンがノードに到着したとき 3 ① すべてのトークンが到着してるかを見て,到着していなければ待つ(=トークンを ① すべてのトークンが到着してるかを見て,到着していなければ待つ(=トークンを 出発させ,次の仕事を始めるためには,前の仕事がすべて終わらなければならな いことを意味している). 14 2 2 1 ノードにトークンが到達したら,“入力アーク数” (=未到着のトークン数を示すデータを兼ねている)を一つ減らす. -∞ - 2 1 経由時間合計 1つ前の経由ノード すでにトークンが出発したノードでは“入力アーク数”は0以外の数(例えば-1)にしておく. 12日 4 6 ノードに入ってくる 入力アークの数 5 1 -1 -∞ - 2 1 5日 9日 8日 7日 1 2 4日 7 8 5日 3日 -∞ - 2 3 6日 10日 3 5 8 2 1 -∞ - 2 0 1
② ノードに記録されている経由時間合計とトークンが経由してきた時間合計を比較する もしトークンが経由してきた時間合計の方が長ければ ② ノードに記録されている経由時間合計とトークンが経由してきた時間合計を比較する もしトークンが経由してきた時間合計の方が長ければ ・ノードの経由時間合計を長い方に書き換える ・1つ前の経由ノードをトークンが経由してきたノードに書き換える 15 3 経由時間合計の長い方の時間が経たな ければ,次の仕事は開始できないので, 最も長い経由時間合計(=その時間にな れば,次の仕事が開始できる最早の時間) をノードに記録する.同時に1つ前の経由 ノードを記録する 14 2 -∞ - 2 1 経由時間合計 1つ前の経由ノード ノードに入ってくる 入力アークの数 12日 4 6 -∞ - 2 1 5日 9日 8日 5日 7日 1 2 4日 7 8 5 1 ‐1 3日 -∞ - 2 3 6日 10日 3 5 18 3 2 8 2 ‐1
トークンがノードから出発するとき 4 ③ 経由時間合計が一番短いノードからトークンを出発させる. ③ 経由時間合計が一番短いノードからトークンを出発させる. なぜなら,計算の都合上,一気にトークンが次のノードに移動したのであって,一番 短い経由時間合計の時間には,他のトークンは実際にはアーク上にあり,出発でき ない. 15 3 2 -∞ - 2 1 経由時間合計 出発させるノードを探すには,入力 ノード数がゼロ(=すべてのトークン が到着)のノードだけ探せばいい. (※入力ノード数が-1のノードは, すでにトークンが出発したノードを 示しているので対象外) 1つ前の経由ノード ノードに入ってくる 入力アーク数 12日 6 4 -∞ - 2 1 5日 9日 8日 7日 1 5日 2 4日 7 8 5 1 -1 -∞ - 2 3 3日 6日 10日 3 8 2 -1 5 18 3 2
アルゴリズムをプログラムにするときの考え方 アークで接続している先のノード番号と作業時間は,link表がもっている. 例えば,ノード2から接続しているノードと時間は・・link[i].connectNode link[i].time (詳しくはデータ構造で説明) History[ 4 ].totalTime History[ 4 ].previousNode History[ 4 ].inputArcCount 15 3 2 4 対応 9日 int q ; // トークンを送るノード番号 q = 4; // ノード4にトークンを送る 5日 7日 1 2 5 1 ‐1 3日 int p ; // 着目しているノード番号 p = 3; // ノード3に着目する 3 8 2 ‐1
《 最早開始時間計算のアルゴリズム 》 トークンの到着 トークンの 出発 《 最早開始時間計算のアルゴリズム 》 経由経路表(route)の初期値として0,最長経由時間合計表(totalTime) の初期値として -∞をそれぞれ設定する p に 始点ノード番号をセットする // トークンをpに置く pが終点ノードに一致するまで繰返す // トークンがpに到着するまで繰り返す pにリンクしているすべてのノードについて繰返す // 繰返しトークンを移動する qをリンク先のノードの番号とする; // トークンの1つの移動先をqとする ノードqまでの時間をtime_q とする; ①ノードqにまだトークンが未到着のアークがあるか(“入力アーク数”>0) /* ②ノードqに到着したトークンの数と経過距離の比較 */ ノードpまでの経由時間 + time_q > ノードqの経由時間 /* ノードpを経由したルートの方が,経由時間合計が短いので ノードp経由に変更する */ ノードqの“経由時間合計”をノードpの“経由時間合計”+ time_q にする ノードqの“1つ前の経由ノード”をpにする ノードqの“入力アーク数”を一つ減らす //qの未到達のアーク数を減らす すべてのトークンが出発したことを示すために“入力アーク数”を-1にする トークンの到着 Yes No トークンの 出発 /* ③ 次にトークンを出発させるノードの決定 */ ネットーク全体から“入力するアーク数”が0で ,かつ経由時間の最も短い ノードを選び出し,次にトークンを進めるべきノードをpとする
【参考】最短経路探索のアルゴリズム トークンの到着 トークンの 出発 経由経路表(route)の初期値として0,最短経由距離表(totalDist) の初期値として ∞をそれぞれ設定する p に 始点ノード番号をセットする // トークンをpに置く pが終点ノードに一致するまで繰返す // トークンがpに到着するまで繰り返す pにリンクしているすべてのノードについて繰返す // 繰返しトークンを移動する qをリンク先のノードの番号とする; //トークンの1つの移動先をqとする ノードqまでの距離をdist_q とする ノードqの出発済みを示すフラッグが降りているか? /* ①ノードqに到着したトークンの経過距離比較 */ ノードpまでの経由距離 + dist_q < ノードqの経由距離 /* ノードpを経由したルートの方が,経由距離合計が短いので ノードp経由に変更する */ ノードqの“経由距離”をノードpまでの“経由距離 ”+dist_qにする; ノードqの“1つ前の経由ノード”をpにする; ノードqのフラッグを下げる トークンが出発済みであることを示すために,ノードpのフラッグを上げる Yes No トークンの到着 トークンの 出発 /* ② 次にトークンを出発させるノードの決定 */ ネットーク全体からフラッグが立っていなくて,かつ経由距離の最も短い ノードを選び出し,次にトークンを進めるべきノードをpとする
《 ネットワークを表すデータ構造 》 Node[] 1 1 2 2 4 2 6 2 Link[] 《 ネットワークを表すデータ構造 》 Node[] 1 2 3 4 1 1 2 2 4 2 6 2 ノード1に接続するリンク(=アーク)データの位置(linkPosition) ノード2に接続するリンク(=アーク)データの位置(linkPosition) ノード3に接続するリンク(=アーク)データの位置(linkPosition) ノード4に接続するリンク(=アーク)データの位置(linkPosition) ノード4に接続するリンク数(linkSize) Link[] 1 2 3 4 5 6 7 8 2 5 3 3 4 9 4 7 5 10 6 12 7 5 connectNode 12日 time 4 6 9日 5日 8日 5日 7日 4日 1 2 7 8 3日 10日 6日 3 5
アルゴリズムの設計と並んで データ構造をいかに設計するかが,計算効率のよさを決める データ構造設計の重要性