二乗和平方根とモンテカルロ法を比べてみた¶
目次
寸法公差の計算をする3つの方法¶
寸法の公差の累積を計算する方法はいくつかあります。
ワーストケース¶
単純に元の寸法の公差をそのまま積み上げていく方法です。
二乗和平方根¶
自然界のものの分布は数が増えるにつれて正規分布に近づいていくという性質と、分散の加法性を利用して、品質を維持するように公差を積み上げる方法です。
モンテカルロ法¶
寸法のサンプルをたくさん作ってそのサンプルを積み上げた結果を使い、積み上げ後の公差を推定する方法です。中心極限定理を利用するものです。
二乗和平方根とモンテカルロ法は一致するのか¶
ばらつきが正規分布するときに、二乗和平方根とモンテカルロ法の計算結果が同じになるかどうか、試してみました。
サンプル¶
1辺が5±0.1mmの立方体を2つ積んだときの、全体の高さを計算してみます。
ワーストケース¶
ワーストケースは単純です。
モンテカルロ法¶
二乗和平方根では元の寸法の分布は正規分布であるということが前提になります。 そこで、正規分布の乱数のマトリックスを2つ作って各要素を足してみます。
コードはこんな感じ。 Jupyter NotebookでPythonを使います。
%matplotlib inline
import scipy
import matplotlib.pyplot as plt
import numpy as np
a = norm.rvs(loc=5, scale=0.1/4, size=1000000)
ave = scipy.average(a)
sig = scipy.std(a, ddof=1)
print('平均 : ' , ave)
print('4 σ : ' , 4 * sig)
b = norm.rvs(loc=5, scale=0.1/4, size=1000000)
ave = scipy.average(b)
sig = scipy.std(b, ddof=1)
print('平均 : ' , ave)
print('4 σ : ' , 4 * sig)
c = a + b
ave = scipy.average(c)
sig = scipy.std(c, ddof=1)
print('組み合わせ')
print('平均 : ' , ave)
print('4 σ : ' , 4 * sig)
d = c[c>(ave + 4 * sig)]
d = np.append(d, c[c<(ave - 4 * sig)])
print('不良品は n=' + str(len(d)) + '/1,000,000')
plt.hist(c, bins=100)
plt.show()
もとの寸法はどちらも4σ(Cpk=1.33)の工程能力があるとします。サンプル数は1,000,000個にしました。
計算結果はこうなります。
4σでの公差が0.1415となりましたので、二乗和平方根とほぼ一致しました。 Cpk=1.33のときの推定不良率は63.3ppmということですが、今回の計算結果は82ppmでした。
元の寸法は正規分布する乱数ですので、計算のたびに少しずつ結果が変わります。今回の結果としては、二乗和平方根とモンテカルロ法がまずまず一致したと考えて良いと思います。
正規分布でないばらつきを積み上げると正規分布に近づくのか¶
寸法のばらつきが一様分布であると仮定した場合に、モンテカルロ法での公差がどうなるか試してみました。
設計をしていると、できるだけ正確に公差を計算しなければなりません。ですが、できれば積み上げた公差は小さい方が、他の部分の設計に余裕ができるというものです。
寸法のばらつきは正規分布すると仮定して、各寸法のばらつきの確率と積み上げ後の寸法のばらつきの確率を同じになるように計算するのが、二乗和平方根の考え方です。
モンテカルロ法でも、各寸法のサンプルを正規分布になるようにばらつかせると、二乗和平方根とほぼ同じ結果が得られます。
「でもさあ、そもそもその寸法は本当に正規分布するの?」
「その箇所はCpk<1.6なの?」
ということで、サンプルのばらつき(分布)を一様分布にして、モンテカルロ法で公差を計算してみます。
計算例¶
1辺が5±0.1mmのサイコロを積み上げていったときの、全体の高さの寸法公差を計算してみました。
計算にはJupyter NotebookでPythonを使いました。こういう計算にはとても便利なツールです。
コード¶
%matplotlib inline
from scipy.stats import uniform
import matplotlib.pyplot as plt
import numpy as np
a = uniform.rvs(loc=4.9, scale=0.2, size=1000000)
ave = scipy.average(a)
sig = scipy.std(a, ddof=1)
print('平均 : ' , ave)
print('4 σ : ' , 4 * sig)
b = uniform.rvs(loc=4.9, scale=0.2, size=1000000)
ave = scipy.average(b)
sig = scipy.std(b, ddof=1)
print('平均 : ' , ave)
print('4 σ : ' , 4 * sig)
c = uniform.rvs(loc=4.9, scale=0.2, size=1000000)
ave = scipy.average(c)
sig = scipy.std(c, ddof=1)
print('平均 : ' , ave)
print('4 σ : ' , 4 * sig)
d = uniform.rvs(loc=4.9, scale=0.2, size=1000000)
ave = scipy.average(d)
sig = scipy.std(d, ddof=1)
print('平均 : ' , ave)
print('4 σ : ' , 4 * sig)
e = uniform.rvs(loc=4.9, scale=0.2, size=1000000)
ave = scipy.average(e)
sig = scipy.std(e, ddof=1)
print('平均 : ' , ave)
print('4 σ : ' , 4 * sig)
f = uniform.rvs(loc=4.9, scale=0.2, size=1000000)
ave = scipy.average(f)
sig = scipy.std(f, ddof=1)
print('平均 : ' , ave)
print('4 σ : ' , 4 * sig)
g = uniform.rvs(loc=4.9, scale=0.2, size=1000000)
ave = scipy.average(g)
sig = scipy.std(g, ddof=1)
print('平均 : ' , ave)
print('4 σ : ' , 4 * sig)
z = a + b + c + d + e + f + g
ave = scipy.average(z)
sig = scipy.std(z, ddof=1)
print('組み合わせ')
print('平均 : ' , ave)
print('4 σ : ' , 4 * sig)
plt.hist(z, bins=100)
plt.show()
4.9から5.1までの間の一様分布な数値を1,000,000個入れた配列を作って、足していきます。
合計してできあがった分布の標準偏差を計算して、その標準偏差の4倍を公差の上限値(マイナス符号を付けたら下限値)とします。Cpkを1.6にする前提ですね。
計算結果¶
1つずつ積み上げていった結果です。ついでに合成結果の分布も合わせて示します。
寸法を足していくにつれて、だんだんと正規分布っぽい形になっていっていますね。
この公差をグラフにしてみるとこうなります。
二乗和平方根が最も公差が小さいのは、そもそも各寸法のばらつき前提が異なりますから、計算手法によるものというよりも計算の前提の差と考えた方が良いと思います。
積み上げる寸法が少ないときには、モンテカルロ法よりもワーストケースの方が公差が小さくなります。ある程度の数の寸法を積み上げたところでやっとワーストケースを逆転します。
これは正規分布でない分布に対して4σの計算をしているからです。現実に起こり得ることよりも、公差を広く計算してしまっています。モンテカルロ法の問題ではなく、盲目的に4σを計算するのがまずいということです。
今回は6個を積み上げてやっとモンテカルロ法がワーストケースを逆転しましたが、実際には公差の組み合わせによって逆転するタイミングは変わるものと思います。
数学に詳しければ証明できるのかもしれないけど。もう少し勉強しておけばよかった。
公開日