===== 時間計画保全のマルコフ決定過程による表現 ===== はじめに:この箇所のみ、状態を0から始める、として番号付けを行なっている。状態数がN+1の時、状態の番号は0からNまでとなる。 ==== このページの目的 ==== 時間計画保全と状態監視保全を、同じ土俵の上で比較することがこのページの目的である。 同じ土俵とは、例えば次のように条件を揃えることを言う。 * 時間計画保全と状態監視保全を同じモデルで比較する * 状態監視によって状態推移を観測していても、途中で修理などせず、故障した時点で緊急取替を行う * 時間計画保全と状態監視保全で、費用を共通にする 一つ目は、時間計画保全は寿命分布に基づいてこストレートを最小化するように、取替年齢を定める。 この点に関しては、2つの考え方がある。 - 劣化量データから寿命分布を推定する (寿命分布派) - 劣化量データからマルコフ連鎖を推定し、それから寿命分布を作る (マルコフ解析派) このいずれを用いて時間計画保全を最適化しても、この原稿の目的には合致している。[[::r:maintenance:hard_time_vs_condition_monitoring|このページ]]は後者の考え方で、時間計画保全を最適化している。一方で、特に説明はしなかったが、提供した劣化量データから閾値0.8)に到達する時間を個々に求めて寿命データを作り、[[::r:survival|こちらで説明した手順]]に基づいて寿命分布を推定してもよい。これらのいずれ、もしくは両方を行うかは、受講者に任せたい。 二つ目は、マルコフ決定過程のために時間計画保全を表現できれば、同じ土俵で比較できる。そのために劣化状態に加えて、年齢という状態変数を用意し、2次元の状態空間でマルコフ連鎖によって劣化が進行していくモデルを考える。 三つ目は現実には、時間計画保全と状態監視保全では稼働継続の費用が全く異なる。 時間計画保全ではシステムを動作させる費用のみが稼働継続の費用だが、 状態監視保全では状態監視システムの構築費用の減価償却費と状態監視システムの稼働費用が上乗せされる。このページではその差がさほど大きくないと想定して、無視することにした。 ==== 年齢取替の行動の状態遷移行列 ==== 次の関数は1期間ごとに1ずつ年齢を重ねる、という状態遷移を表す行列を生成する。ここでのSは状態空間だが、年齢の範囲を表す集合でもある。 mmdp_create.ageing.matrix = function(S) { R = max(S)-min(S) n = length(S) if( R != n-1 ) { stop("age space is not regular and/or does not begin with 0.") } max.S = max(S) P = rbind(cbind(0,diag(rep(1,max.S))),0) P[max.S+1,max.S+1] = 1 rownames(P)=S colnames(P)=S return(P) } 次のコードは年齢を0から20までに設定する。 mmdp_create.ageing.matrix(c(0:20)) === 状態指定取替 P.Age === ある状態でのみ取替を実行し、他の状態では何もしない行動を状態指定取替として定義しておく。 次の関数は状態を年齢に取り、指定した年齢で取替を行い、他の年齢では何もしないという行動を表す状態遷移行列を生成する。 mmdp_create.age.replacement.matrix = function(S,T.ast) { R.S = max(S)-min(S) n.S = length(S) if( R.S != n.S-1 ) { stop("state space is not regular and/or does not begin with 0.") } P = diag(rep(1,n.S)) P[T.ast+1,1] = 1 P[T.ast+1,T.ast+1] = 0 rownames(P) = S colnames(P) = S return(P) } これも状態空間が0から4の場合に実行してみておく。 次の実行例は、年齢が0から4まで推移する対象に、年齢2で取替を行う行列を生成する。 mmdp_create.age.replacement.matrix(c(0:4),2) 状態指定取替は年齢取替のマルコフ決定過程における表現を与える。 > mmdp_create.age.replacement.matrix(c(0:4),3) 0 1 2 3 4 0 1 0 0 0 0 1 0 1 0 0 0 2 0 0 1 0 0 3 1 0 0 0 0 4 0 0 0 0 1 この行動は、通常の状態監視保全では現れないことを注意しておく。 === 劣化の状態遷移行列に故障時の取替を加える === 時間計画保全では、予防取替と事後取替がある。 ここでは故障状態になったら強制的に緊急取替を行うように状態遷移行列を変更している。 最後の一行に注目して欲しい。 P.Dgr = matrix(c( 9/10, 1/10, 0, 0, 0, 0, 9/10, 1/10, 0, 0, 0, 0, 9/10, 1/10, 0, 0, 0, 0, 9/10, 1/10, 1, 0, 0, 0, 0), nrow=5, ncol=5, byrow=TRUE) rownames(P.Dgr) = c(0:4) colnames(P.Dgr) = c(0:4) P.Dgr 年齢取替をマルコフ決定過程で評価するためには、劣化の状態遷移行列をP.Dgrを持っている時、最後の一行を次のコードで変更しなければならない。 P.Dgr[dim(P.Dgr)[1],] = c(1,rep(0,dim(P.Dgr)[1]-1)) この変更を行わないと、故障状態に至っても、事後取替(緊急取替)をせずに故障状態に留まらせてしまう。 この事後取替込みの、劣化の費用関数を次のように与えてみる。 C.Opr.Dgr = c(0,0,0,0,2000) 残りのコード。年齢の範囲はT*を切り上げた値か、その次まで用意する。 状態遷移行列の準備。 S.Dgr = c(0:(dim(P.Dgr)[1]-1)) S.Age = c(0:10) P.Age = mmdp_create.ageing.matrix(S.Age) P.Hrd = mmdp_create.age.replacement.matrix(S.Age,4) P.Dgr.2 = mmdp_expand.P.2(list(P.Dgr,P.Age)) P.Hrd.2 = mmdp_expand.P.2(list(mmdp_create.replacement.matrix(S.Dgr),P.Hrd)) P = array(0,dim=c(dim(P.Dgr.2)[1],dim(P.Dgr.2)[2],2)) P[,,1] = P.Dgr.2 P[,,2] = P.Hrd.2 費用の準備。 C.Opr.Dgr = c(0,0,0,0,2000) C.Opr.Age = rep(0,length(S.Age)) C.Rpl.Dgr = rep(150,length(S.Dgr)) C.Rpl.Age = rep(0,length(S.Age)) C.Opr.Opr = mmdp_expand.R.2(list(C.Opr.Dgr,C.Opr.Age)) C.Rpl.Rpl = mmdp_expand.R.2(list(C.Rpl.Dgr,C.Rpl.Age)) Cost = cbind(C.Opr.Opr,C.Rpl.Rpl) R = -Cost 上の各数値は各自で設定し直す必要がある。 年齢が6になったら、交換を行うという保全基準の方策は、次のように与える。 cbind(expand.grid(c(0:4),c(0:10)),c(rep(1,5*6),rep(2,5*5))) 反復によって総期待割引き費用を求めるには、MDPtoolboxパッケージの中の関数mdp_eval_policy_iterativeを用いる。この関数の引数は、状態遷移行列のリスト、効用関数のリスト、割引き係数、方策、である。 mdp_eval_policy_iterative(P,R,0.95,c(rep(1,5*6),rep(2,5*5))) 価値反復法によって、故障したら事後取替、そして年齢による予防取替、の2つの最適な方策を求めてみる。これも同じくMDPtoolboxパッケージの関数mdp_value_iterationを用いる。 mdp_value_iteration(P,R,0.95) 年齢による予防取替は、年齢に達しない限り、そのまま放置をするのだが、それが1年間放置する、という結果になってしまう。なぜだろうか? 同じ設定での状態監視保全は、前回の内容そのままなので省略する。