Supply chain risk analysis system MERIODAS (MEta RIsk Oriented Disruption Analysis System)

簡易システムの紹介ビデオ

サプライ・チェイン・リスク分析システム MERIODAS (MEta RIsk Oriented Disruption Analysis System)

YouTubeVideo("9D13CjGXrNM")

MITのSimchi-LeviとFord Motorsとの共同研究;Wagner Prize受賞

途絶条件下でのクリティカルな部品工場を求めるためのモデル

集合:

  • $G=(V,E)$: 工場の輸送可能関係を表すグラフ;点の添え字を $f,g$ とする.
  • $BOM$: 部品展開表(BOM)を表すグラフ; 点 $p$ の子ノードの集合を $CHILD_p$ とする.点の添え字を $p,q$ とする.
  • $D=(N,A)$: 製品の移動関係を表すグラフ;点の添え字を $i,j$ とする.点は工場 $f$ と製品 $p$ の組であり, $i=(f,p)$ の関係がある. また、$(i,j)\in A$ であるのは、$i=(g,q), j=(f,p)$ としたとき、 $(i,j) \in E$(輸送可能)かつ $q \in CHILD_p$ (子製品・親製品の関係)を満たすときに限るものとする。 以下では、点、枝はこのグラフの点、枝を指すものとする。
  • $PRODUCT_i$: 工場 $i$ で生産可能な製品の集合

パラメータ:

  • $\phi_{pq}$: 親製品$p \in P$を1ユニット製造するのに必要な子製品$q \in Child_p$の部品数
  • $R_{ij}$: 枝 $(i,j)$ での製品の変換比率;上の $\phi_{pq}$ から計算される。
  • $I_i$: 点 $i (\in N)$ におけるパイプライン在庫量
  • $DEM_i$: 点 $i (\in N)$ における単位期間内での需要量
  • $UB_i$: 点 $i (\in N)$ における生産可能量上限($0$ のとき途絶中であることを表す.)
  • $CAP_f$: 工場 $f$ の単位期間内での生産容量

変数:

  • $y_{ij}$: 点 $i$ から点 $j$ への輸送量
  • $u_j$: 点 $i (\in N)$ 上での生産量
  • $\tau$: 余裕生存時間(TTS:Time-to-Survive)
$$ \begin{array}{l l l} maximize & \tau & \\ s.t. & u_j \leq \sum_{i=(g,q)} \frac{1}{R_{ij}} y_{ij} & \forall j=(f,p), q \in CHILD_p \\ & \sum_{j} y_{ij} \leq u_i + I_i & \forall i \in N \\ & DEM_j \tau \leq u_j & \forall i \in N \\ & \sum_{p \in PRODUCT_i} u_{ip} \leq CAP_i \tau & \forall i \in N \\ \end{array} $$

最初の制約(生産量と入庫輸送量の関係): 工場 $f$ における製品 $p$ の生産量 $u_{j} (j=(f,p))$ は、その部品 $q$ の輸送量以下でなくてはいけない。 ここで、輸送量は出発地点 $i$ における子製品 $q$ の単位で表現されているので、親製品の量は変換比率 $R_{ij}$ で割らなければならない。

2番目の制約(生産量と出庫輸送量の関係): 点 $i$ から出る輸送量 $y_{ij}$ は、生産量 $u_i$ とパイプライン在庫量 $I_i$ の和以下でなくてはならない。

3番目の制約(需要満足条件): 生産量は途絶期間内の需要量以上でなければならない。

4番目の制約(工場の生産容量制約): 工場 $i$ で生産される総量は、その容量 $CAP_i$ 以下でなければならない。

各点(工場と製品の組)が途絶したシナリオ(点 $i$ の生産量上限 $UB_i$ を $0$ に設定) において上の問題を解き、そのときの目的関数値が、点の途絶時に品切れがおきない最大の期間(余裕生存時間)となる。

G = nx.DiGraph() #plant graph
BOM=nx.DiGraph() #BOM: bill of materials
G.add_edges_from( [(1,0),(2,0)] )
#  工場グラフ
#  1 => 0
#  2 => 0

UB={} 
Capacity = {0: 300, 1: 500, 2: 200 }
Product  = {0: ['P4','P5'], 1:['P1','P3'], 2: ['P2','P3']}

BOM.add_weighted_edges_from([ ('P1','P4', 1), ('P2','P5',2),('P3','P5',1) ])

#Construct product graph(生産グラフ)
ProdGraph = nx.tensor_product(G,BOM)
#print(ProdGraph.edges())
Temp = ProdGraph.copy()
for (i,p) in Temp:
    if p not in Product[i]:
        ProdGraph.remove_node( (i,p) )
print("ProdGraph Nodes=",ProdGraph.nodes())
print("ProdGraph Edges=",ProdGraph.edges())

Pipeline, Demand= {}, {}
for n in ProdGraph:
    Pipeline[n] =300.
    UB[n] = 1000000.
    if ProdGraph.out_degree(n)==0:
        Demand[n]=100.
R={}
for (u,v) in ProdGraph.edges():
    (i,p)=u
    (j,q)=v
    R[u,v]=BOM[p][q]['weight']
print("R=",R)
print("Demand=",Demand)
ProdGraph Nodes= [(1, 'P1'), (1, 'P3'), (0, 'P4'), (0, 'P5'), (2, 'P2'), (2, 'P3')]
ProdGraph Edges= [((1, 'P1'), (0, 'P4')), ((1, 'P3'), (0, 'P5')), ((2, 'P2'), (0, 'P5')), ((2, 'P3'), (0, 'P5'))]
R= {((1, 'P1'), (0, 'P4')): 1, ((1, 'P3'), (0, 'P5')): 1, ((2, 'P2'), (0, 'P5')): 2, ((2, 'P3'), (0, 'P5')): 1}
Demand= {(0, 'P4'): 100.0, (0, 'P5'): 100.0}

ベンチマーク問題例からデータを生成する関数 data_generation_for_scrm

3つの有向グラフが必要となる。

  1. ベンチマークのグラフが部品展開表 BOM
  2. 工場グラフ: 各段階に n_plnts 個の工場があり、次段階に確率 prob で枝があるグラフ
  3. 生産グラフ: 各段階の工場にその段階の品目が n_flex 個割り振られるように設定して得られるグラフ;工場と製品の集合のテンソル積から、工場で生産できない製品を表す点を除くことによって得ることができる。

引数:

  • BOM : ベンチマーク問題例から読み込まれた部品展開表 (BOM) を表すNetworkXの有向グラフ
  • n_plnts : ベンチマークのBOMの各階層ごとの工場数(既定値は3)
  • n_flex : 各工場で生産可能な製品の数;生産の柔軟性を表す。どの工場でも生産されない製品は最後の工場で生産する。(既定値は2)
  • prob : 工場グラフにおける枝の発生確率;同じ順番の点間には枝をはり、それ以外の枝をこの確率で発生させる。(既定値は0.5)
  • capacity_factor : 工場の生産容量を決めるパラメータ。総需要量にこの値を乗じた量が、各工場の容量になる。(既定値は1.0)
  • production_factor : 生産量上限を決めるパラメータ。総需要量にこの値を乗じた量が、各地点の生産量上限になる。(既定値は1.0)
  • pipeline_factor : パイプライン在庫量を決めるパラメータ。総需要量に生産時間の値とこの値を乗じた量が、各地点のパイプライン在庫量になる。(既定値は1.0)
  • seed : 乱数の種 (既定値は1)

返値:

  • Demand : 需要地点の需要を入れた辞書
  • total_demand : 総需要量
  • UB : 各点での生産量上限を入れた辞書
  • Capacity : 工場の生産容量を入れた辞書
  • Pipeline : 各点でのパイプライン在庫量を入れた辞書
  • R : 親製品を生産するために必要な子製品の数を入れた辞書
  • Product : 工場で生産可能な製品を入れた辞書
  • G : 工場グラフ
  • ProdGraph : 生産グラフ
  • pos2 : 工場グラフの点の座標を入れた辞書
  • pos3 : 生産グラフの点の座標を入れた辞書

data_generation_for_scrm[source]

data_generation_for_scrm(BOM, n_plnts=3, n_flex=2, prob=0.5, capacity_factor=1.0, production_factor=1.0, pipeline_factor=1.0, seed=1)

ベンチマーク問題例から、データを生成する関数

data_generation_for_scrmの使用例

inventoryモジュールの read_willems関数を用いてベンチマーク問題を読み込む。 返値は、部品展開表 BOM と点の位置を表す辞書 pos である。

draw_graph[source]

draw_graph(G, pos, title='', size=30, color='Yellow')

グラフをPlotlyで描画する関数

BOM, pos = read_willems(file_name="01") # ベンチマーク問題例からBOMデータを読み込む
Demand, total_demand, UB, Capacity, Pipeline, R, Product, G, ProdGraph, pos2, pos3 = \
                          data_generation_for_scrm(BOM, n_plnts = 3, n_flex = 2, prob = 0.1, capacity_factor=30.0, production_factor=10.0, pipeline_factor =.1)
fig = draw_graph(G, pos2, "Plant Graph", color ="Red", size=20)
#fig.show()
Image("../figure/plant_graph.png")
fig = draw_graph(BOM, pos, "BOM Graph", color ="Green", size=10)
#fig.show()
Image("../figure/bom.png")
fig = draw_graph(ProdGraph, pos3, "Production Graph", color ="Yellow", size=20)
#fig.show()
Image("../figure/production_graph.png")

リスク分析問題を解く関数

引数:

  • Demand : 需要地点の需要を入れた辞書
  • UB : 各点での生産量上限を入れた辞書
  • Capacity : 工場の生産容量を入れた辞書
  • Pipeline : 各点でのパイプライン在庫量を入れた辞書
  • R : 親製品を生産するために必要な子製品の数を入れた辞書
  • Product : 工場で生産可能な製品を入れた辞書
  • ProdGraph : 生産グラフ
  • BOM : 部品展開表 (BOM) を表すグラフ

返値:

  • survival_time: 各点の余裕生存期間(点の途絶時に品切れがおきない最大の期間)を入れたリスト

solve_scrm[source]

solve_scrm(Demand, UB, Capacity, Pipeline, R, Product, ProdGraph, BOM)

リスク分析問題を解く関数

solve_scrm関数の使用例

if False:
    survival_time = solve_scrm(Demand, UB, Capacity, Pipeline, R, Product, ProdGraph, BOM)
    survival_time
[0.0,
 0.0,
 0.0,
 0.0,
 0.0,
 0.0,
 2.9486166,
 2.9486166,
 2.9486166,
 2.9486166,
 2.9486166,
 2.9486166,
 2.9486166,
 2.9486166,
 2.9486166,
 2.9486166,
 2.9486166,
 2.9486166]

リスク分析ネットワークを描画する関数 draw_scrm

引数:

  • ProdGraph : 生産グラフ
  • survival_time: 各点の余裕生存期間(点の途絶時に品切れがおきない最大の期間)を入れたリスト
  • Pipeline : 各点でのパイプライン在庫量を入れた辞書
  • UB : 各点での生産量上限を入れた辞書
  • pos3 : 生産グラフの点の座標を入れた辞書

返値:

  • リスク分析ネットワークの図オブジェクト

draw_scrm[source]

draw_scrm(ProdGraph, survival_time, Pipeline, UB, pos3)

リスク分析ネットワークを描画する関数

#fig = draw_scrm(ProdGraph, survival_time, Pipeline, UB, pos3)
#fig.show()
Image("../figure/risk_analysis_network.png")