「信頼性工学のはなし―信頼度99.9999…%をめざして」1~2章

大村平「信頼性工学のはなし―信頼度99.9999…%をめざして」日科技連 の読後行間補充メモ

同書籍は、印刷数表による信頼性工学の啓蒙書。

本稿では、同書籍の設例について、Python [Google Colaboratory]による演算処理例を示す。




1章 信頼性を支える3本の柱 



p5 双発と4発、どちらを信頼するか。

efp = float(input('エンジンの故障確率',))
print(f'双発機の墜落確率:{efp**2}')
print(f'4発機の墜落確率:{efp**4}')
print(f'双発機が遅れる[=エンジンのいずれか又は全部が故障する]確率:{1-(1-efp)**2}')
print(f'4発機が遅れる[=エンジンのいずれか又は全部が故障する]確率:{1-(1-efp)**4}')
エンジンの故障確率0.001

双発機の墜落確率:1e-06
4発機の墜落確率:1.0000000000000002e-12
双発機が遅れる[=エンジンのいずれか又は全部が故障する]確率:0.001998999999999973
4発機が遅れる[=エンジンのいずれか又は全部が故障する]確率:0.003994003998999962

  • \(1e-06\) とあるのは、\(1\times 10^{-6}\) すなわち、0.000001 を指す。
  • \(1.00.......002e-12\) とあるのは、\(1.00.......002\times 10^{-12}\) すなわち、0.00000000000100.......002 を指す。


p9 2進法で表す 表1.1

import pandas as pd

decimal = []
binary = []
for i in range(10):
  decimal.append(i) # 10進数
  bin = format(i,'04b') #4桁の2進数
  binary.append(bin)
del i # 変数を廃棄

DF = pd.DataFrame([decimal,binary]).T
DF.columns = ['10進法','2進法']
DF # 表1.1
	10進法	2進法
0	0	    0000
1	1	    0001
2	2	    0010
3	3	    0011
4	4    	    0100
5	5	    0101
6	6	    0110
7	7	    0111
8	8	    1000
9	9	    1001


p10 パリティ・ビットを付ける 表1.2

(処理工程)

  1. 2進法の数値における1の個数をカウントし、奇数であれば0を末尾に加える
  2. 2進法の数値における1の個数をカウントし、偶数であれば1を末尾に加える
  3. 上記処理結果を、PB付き列として生成して、一覧表化する

# コードは上記の続き
import re

def parity_odd(string):
    new_str = ""
    string = re.sub('[^0-1]', '', string)
    if string.count("1") % 2 == 1: #1の個数を2で除した余りが1[奇数]か否か[偶数]
        new_str = string +"0" # 奇数の場合、0を末尾に
    else:
        new_str = string +"1" # 偶数の場合、1を末尾に
    return new_str

# 新列(PB付)を加える
PB_col = []
for n in range(DF.shape[0]): # 行数分、繰り返す
  PB_col.append(parity_odd(DF['2進法'][n]))
del n # 変数を廃棄
DF['PB付き'] = PB_col
DF
	10進法	2進法	PB付き
0	0	        0000	00001
1	1    	        0001	00010
2	2	        0010	00100
3	3	        0011	00111
4	4	        0100	01000
5	5	        0101	01011
6	6	        0110	01101
7	7	        0111	01110
8	8	        1000	10000
9	9	        1001	10011


p11 5桁のうちのどれか1つを間違える確率

import math

# 関数 n個のうちr個のみで間違いが発生する確率
def error_p(n,r,p):
  return math.comb(n,r)*(p**r)*(1-p)**(n-r)

n = int(input('全体n 個:',))
r = int(input('間違い r個:',))
p = float(input('0と1を間違える確率:',))
print(f'{n}個のうち{r}個だけ間違える確率:{round(error_p(n,r,p),7)}')
全体n 個:5
間違い r個:1
0と1を間違える確率:0.001
5個のうち1個だけ間違える確率:0.00498


p11 5桁のうちのどれか2つを間違える確率

コードは上記と同じ。
全体n 個:5
間違い r個:2
0と1を間違える確率:0.001
5個のうち2個だけ間違える確率:1e-05




2章 バスタブが語る故障のパターン 



p26 信頼性と故障の続柄

  • 信頼度\(R\)
  • 故障確率\(F\)
\(R=1-F\)


p27 人間の死亡率をグラフに描く 表2.1

(処理工程)
  1. 生存者データを設定
  2. 生存者データの差分 →死亡者数
  3. 死亡者数を加算 →死亡者累計数
  4. 死亡者数/生存者 →死亡率
  5. 一覧表化
# 表2.1
import pandas as pd
import numpy as np

# 年齢の列
age_col = []
ages = np.array([0,10])
for i in range(11):
  age_col.append(ages+10*i)

# 生存者データ
live_col = [100,95,94,93,91,85,69,42,17,4,0]

DFal = pd.DataFrame([age_col,live_col]).T
DFal.columns = ['Ages', 'Living']

# 死亡者数
Dead = []
for i in range(10):
  Dead.append(DFal.loc[:,'Living'][i] -DFal.loc[:,'Living'][i+1])
Dead_column = pd.Series(Dead)
DFald = pd.concat([DFal, Dead_column],axis=1)
DFald.columns = ['Ages', 'Living','Dead']

# 死亡者累計数
Dead_Accum = []
for j in range(10):
  Dead_Accum.append(DFald.loc[:,'Living'][0] -DFald.loc[:,'Living'][j+1])
DA_column = pd.Series(Dead_Accum)
DFalda = pd.concat([DFald, DA_column],axis=1)
DFalda.columns = ['Ages', 'Living','Dead','Dead_Accum']

# 死亡率%
Dead_percent = []
for k in range(10):
  Dead_percent.append(DFalda.loc[:,'Dead'][k] /DFalda.loc[:,'Living'][k])
DP_column = pd.Series(Dead_percent)
DF = pd.concat([DFalda, round(DP_column*100,1)],axis=1)
DF.columns = ['Ages', 'Living','Dead','Dead_Accum', 'Dead_Percent']
DF
	Ages		Living		Dead	Dead_Accum	Dead_Percent
0	[0, 10]	    100		5.0		5.0		5.0
1	[10, 20]	    95		1.0		6.0		1.1
2	[20, 30]	    94		1.0		7.0		1.1
3	[30, 40]	    93		2.0		9.0		2.2
4	[40, 50]	    91		6.0		15.0		6.6
5	[50, 60]	    85		16.0		31.0		18.8
6	[60, 70]	    69		27.0		58.0		39.1
7	[70, 80]	    42		25.0		83.0		59.5
8	[80, 90]	    17		13.0		96.0		76.5
9	[90, 100]	        4		4.0		100.0	100.0
10	[100, 110]	0		NaN		NaN		NaN


p30 図21 死亡者数のグラフ

# コードは上記の続き
import matplotlib.pyplot as plt

# 年齢をリスト化
Ages_list = []
for m in DF['Ages']:
  Ages_list.append(m[0])

# グラフ描画
plt.bar(Ages_list, DF['Dead'],width=9,align='edge') #alignをedgeとするとx座標は棒の左端に変更
plt.title('Dead')
plt.xlabel('Ages')


p30 図21 死亡者累計のグラフ

# コードは上記の続き
plt.bar(Ages_list, DF['Dead_Accum'],width=9,align='edge', color='orange')
plt.title('Dead_Accumulated')
plt.xlabel('Ages')


p30 図2.1 死亡率のグラフ

# コードは上記の続き
plt.bar(Ages_list, DF['Dead_Percent'],width=9,align='edge', color='lightgreen')
plt.title('Dead_Percent')
plt.grid()
plt.xlabel('Ages')



p31 図2.2 人間の死亡率


p32~37 図2.3、図2.4 故障率\(k\) のバスタブ曲線

ワイブル故障分布(p151)

\begin{eqnarray*} f(t)&=&k(t)\times R(t)\\&=&\cfrac{m}{\eta}\left(\cfrac{t-\gamma}{\eta}\right)^{m-1} \times e^{-\left( \cfrac{t-\gamma}{\eta}\right)^m}\end{eqnarray*}

を構成する故障率関数

\(k(t)=\cfrac{m}{\eta} \left(\cfrac{t-\gamma}{\eta}\right)^{m-1}\)

を使用する。
式中の各パラメータの趣旨は、以下のとおり。
  • \(m\) …形状パラメータ
  • \(\eta\) …尺度パラメータ
  • \(\gamma\) …位置パラメータ

(処理工程)
  1. 形状パラメータを期間別に3つ用意する(初期、偶発、摩耗期間)
  2. 尺度パラメータ、位置パラメータを設定
  3. パラメータ値を故障率関数に入力して、各故障率を演算する
  4. 3つの演算結果を合計 →観測故障率
  5. グラフ化

# 故障確率k
import numpy as np
import math
from  matplotlib import pyplot as plt
import japanize_matplotlib

# 設定値
m_list = [0.5, 1, 10] # 形状パラメータ(初期、偶発、摩耗)
eta_value = 1 # 尺度パラメータ(半減期、時定数)
gamma_value = 0 # 位置パラメータ

# 各時期(初期、偶発、摩耗)のパラメータ設定
g_wide =1 # グラフ横幅
step = 0.0001 # グラフ描画刻み

p1 = [0, g_wide, m_list[0], eta_value, gamma_value] # 始点、終点、形状、尺度、位置
p2 = [0, g_wide, m_list[1], eta_value, gamma_value]
p3 = [0, g_wide, m_list[2], eta_value, gamma_value]
graph_list = [p1,p2,p3] # リスト化

# 関数 故障確率 k (ワイブル)
def k_weibull(m_value,eta_value,gamma_value,time): # 形状、尺度、位置、時間
  khead = m_value/eta_value
  ktail = (time - gamma_value)/eta_value
  kpower = m_value -1
  y_value = khead * ktail ** kpower
  return y_value

# 関数 グラフ用データ作成
def xylist(start,end,m_value,eta_value,gamma_value): # 始点、終点、形状、尺度、位置
  x_list = []
  y_list = []
  for time in np.arange(start,end,step):
    x_list.append(time) # 時間リスト
    y_list.append(k_weibull(m_value,eta_value,gamma_value,time)) # 演算結果リスト
  return x_list, y_list

#  各グラフのパラメータを関数(グラフ用データ)に渡して、描画
ky_lists = []
for graph in graph_list:
  x_data = xylist(graph[0],graph[1],graph[2],graph[3],graph[4])[0]
  y_data = xylist(graph[0],graph[1],graph[2],graph[3],graph[4])[1]
  plt.plot(x_data, y_data, linestyle="--")
  ky_lists.append(y_data)

# バスタブ曲線
ky_lists[2] = np.nan_to_num(ky_lists[2], nan=0) # nan を0に置換
ky_sums = [x+y+z for (x,y,z) in zip(ky_lists[0], ky_lists[1],ky_lists[2])] # 3データを合計
plt.plot(x_data, ky_sums, label="観測故障率", color='red', linewidth=3)

# グラフ凡例等
plt.xlim(0,g_wide)
plt.ylim(0,15)
plt.yticks([])
plt.xlabel('time')
plt.ylabel('k [/t]')
plt.legend()
plt.title('バスタブ曲線')
plt.show()