[1] エクスポート・インポート機能
「工程’s」にはオプションで、エクスポート・インポート機能があって、工程データを12種類のTSV(Tab Separated Values)ファイルに出力できます。
例題1.kzdに対してエクスポートをかけます。

この操作を行うと、指定したフォルダに次のように13種類のtsvファイルが作成されます。

ここで重要なのが赤枠で囲んだ3つのファイルで、koutes.tsv、constraint.tsv、requirement.tsvはそれぞれ日程計画、先行制約、資源制約に関する情報を含んでいます。
tsvファイルを、EXCELにdrag-dropすれば、簡単に中身をチェックできます。いま適当に編集してtsvファイルに戻したとします。これらを次のようにインポートすれば、例題1.kzdが変更されます。

[2] テンプレート
一つの計画を再利用したい場面はいろいろ考えられます。「工程’s」では通常の.kzdファイルのほかに、テンプレートファイル.kzt出力して、これを再利用することができます。
[3] 工程’sファイルの複製
計画期間が重なる2つの計画に対して山積み行って、リソースの不足がないかをチェックしたい場合があります。この目的のために次図を考えます。

まず、(a)は元ファイル(たとえば「例題1.kzd」)とします。同じ計画を一定期間おいて繰り返す場合は、(b)のように全部のアクティビティを選択してコピーすればOKです。これは「工程’s」の編集操作の範囲内で行うもので、おのずとアクティビティの数が限られます。
次に、(c)は(a)のすべてのアクティビティを一括して扱うために、最上位のグループ(黄色のバー)を設置した様子を表しています。具体的には次図となります。

これを一定期間ずらした計画との山積みの重複の様子を見るには、最上位のグループをコピーして、(f)のようにその下にペーストします。これは同一ファイル内の操作になります。
一方、(c)からテンプレートファイルを(d)のように作成し、これを一定期間ずらして読み込んで、もう一つの計画(e)を作成しておきます。一方のファイルの最上位のグループをコピーして、(g)のように他方のファイルの中でペーストします。これは2つの異なるファイル間の操作になります。ここで、2つのファイルは全く別の計画(別のテンプレートから作成された計画)でもよいことに注意してください。
第1章の例題1を「工程’s」を用いてstep-by-stepで作成してみます。
[1]準備
編集期間設定

現在日の設定

プロジェクト名称の設定

カレンダー編集(略)
通し日の設定(略)
[2]リソースの定義
資源マスター編集

[3]アクティビティの定義
WBSの設定
– グループの挿入

– グループプロパティの設定

– グループバーの表示・非表示(略)
– ツリービューの表示・非表示

アクティビティバーの設置

– IDの設定
– 名称の設定
– 必要資源の設定
– シンボル変更(略)
[4]先行制約の定義
先行制約の定義
山積み

– 山積みグラフの表示
– 供給資源量表示・非表示
– 供給資源量設定
造船工程計画

造船工程計画とは、ブロック製作のために2種類のリソース(場所、作業員)のタイムライン化(時間軸に並べること)と言えます。2つの計画AB,BC,CAは比較的簡単に求まりますが、3つの計画A,B,Cの共通部分ABCを求める必要があります。
問題の規模
例題2に対して、次式に基づいて、「問題の規模」を計算してみます。

、
だから、ブロックBLK1については

ブロックBLK2については

ブロックBLK3については

したがって、例題2に対して問題の規模は

と計算できます。
本書では、すべてのRCPSPについて、問題の規模を次のコードで、モードの総数として求めていますす。
OptSeq |
#====問題の規模:
A=[]
for a in prob.act: A.append(a.name)
print("アクティビティ:",A)
N=len(prob.act)
print("アクティビティ総数(含待機数):",N)
M=[]
for a in prob.act: M.append(len(a.modes))
print("モード数:",M)
print("平均モード数:",round(sum(M)/N))
P=math.ceil(math.log10(round(sum(M)/N)**N))
print("問題の規模: 10**",P)
|
ここで、RCPSPとして定式化されたモデルを
としています。
により、すべてのアクティビティ名のリスト
を求めて、その長さを
としています。また各アクティビティに付されたモードの個数を並べたリスト
を求めています。平均モード数
を求め、これを
乗することで、問題の規模としています。
rcpsp11.py
OptSeq |
#rcpsp11.py
from optseq import *
#====データセット
#i:[名前、期間、後続、資源]
data={
1:["A01",3,[4,6],3],
2:["A02",4,[5,7],1],
3:["A03",6,[8] ,1],
4:["A04",4,[5,7],4],
5:["A05",5,[8] ,4],
6:["A06",5,[9] ,4],
7:["A07",4,[10] ,5],
8:["A08",2,[10] ,2],
9:["A09",2,[10] ,5],
10:["A10",5,[0] ,3],
}
#====アクティビティ
prob=Model()
act={}
for i in data:
act[i]=prob.addActivity(data[i][0])
#====先行制約
for i in data:
for j in data[i][2]:
if j>0: prob.addTemporal(act[i],act[j])
#====資源制約
res=prob.addResource("Resource",capacity={(0,"inf"):10})
mode={}
for i in data:
mode[i]=Mode("M{0:02d}_{1:02d}".format(i,data[i][3]),\
duration=data[i][1])
mode[i].addResource(res,requirement=data[i][3])
act[i].addModes(mode[i])
#====求解
prob.Params.Makespan=True
prob.Params.TimeLimit=1
prob.optimize()
prob.write("rcpsp11.txt")
prob.writeExcel("rcpsp11.csv")
|
rcpsp11.pyはPython言語で記述されています。
データセットはPythonの辞書データとして定義されており、keyがアクティビティ名となっていて、先行関係はkeyを参照して指定されていることに注意してください。ここでは簡単のために数字を用いていますが、文字列を用いることもできます。たとえばデータセットの定義は次のように行うこともできます。
OptSeq |
#====データセット
data={
#"id":["名称",期間,["後続#1"," 後続#2"]、員数],
"A01":["A1(3人)",3,["A04"," A06"],3],
"A02":["A2(1人)",4,["A05"," A07"],1],
"A03":["A3(1人)",6,["A08"," 0"],1],
"A04":["A4(4人)",4,["A05"," A07"],4],
"A05":["A5(4人)",5,["A08"," 0"],4],
"A06":["A6(4人)",5,["A09"," 0"],4],
"A07":["A7(5人)",4,["A10"," 0"],5],
"A08":["A8(2人)",2,["A10"," 0"],2],
"A09":["A9(5人)",2,["A10"," 0"],5],
"A10":["A10(3人)",4,["0"," 0"],3],
}
|
その他のコードについては、別途詳しく説明します。
図1.1

図1.1は「工程’s」で作成されており、作成時のカレンダーが用いられています。ただ例題1は特定のカレンダーに依存しないので、「通し日」を用いて、次のように表すこともできます。

「工程’s」の基礎については、次にまとめています。
「工程’s」の基礎