シミュレーション工学5

Dublin Core

Creator

Date Created

Rights

CC BY-NC 4.0 - 非営利目的のみ許可

note Item Type Metadata

note

つり銭問題のシミュレーション

学習目標

  • シミュレーション手法の理解と実践
  • 確率論的思考の習得
  • 実問題の数学的モデル化
  • 統計的分析手法の応用
  • プログラミングによる数値計算

前提知識

  • 基本的な確率の概念
  • Pythonプログラミングの基礎
  • 統計の基本概念(平均、分散、分布)

問題設定

変数の定義

  • x: ある時点での1000円札の枚数
  • y: お釣りの必要枚数
  • n: メンバー数(15人)

支払いパターン

  • 1000円札3枚で支払い: x → x + 3
  • 10000円札1枚で支払い: x → x - 7(お釣りとして1000円札7枚必要)
  • 確率: 各パターン50%の確率

お釣り必要枚数の計算

  • y = 0 (min x ≥ 0): 最小値が0以上の場合、お釣りの準備は不要
  • y = |min x| (min x < 0): 最小値がマイナスの場合、マイナス分だけ必要

シミュレーションの流れ

フローチャート

開始
  ↓
x = 0, min_x = 0
  ↓
部員i (i=1 to 15)
  ↓
ランダム選択 (50%確率)
  ↓
┌─────────────────┬─────────────────┐
│ 1000円札3枚     │ 10000円札1枚    │
│ x = x + 3       │ x = x - 7       │
└─────────────────┴─────────────────┘
  ↓
min_x = min(min_x, x)
  ↓
i < 15? → Yes → 次の部員
  ↓ No
y = max(0, -min_x)
  ↓
結果を記録
  ↓
終了
    

ステップ詳細

  1. 初期化: お釣りの枚数をx=0で初期化
  2. 支払い決定: 50%の確率で1000円札3枚か10000円札1枚を決定
  3. 状態更新: 支払い方法に応じてxを更新:
    • 1000円札3枚: x → x + 3
    • 10000円札1枚: x → x - 7
  4. 最小値記録: min_x = min(min_x, x)
  5. 繰り返し: 15回繰り返す
  6. 結果計算: xの最小値から必要なお釣りの枚数を決定

Python実装例

実行方法

  1. Pythonがインストールされていることを確認
  2. 以下のコードをtsurisen.pyとして保存
  3. コマンドプロンプトでpython tsurisen.pyを実行
import random

def tsurisen_simulation(trials=10000):
    """
    つり銭問題のシミュレーション
    
    Args:
        trials (int): シミュレーション回数(デフォルト: 10000回)
    """
    MEMBER_N = 15  # 部員数
    result = []    # 結果を格納するリスト
    
    # 指定回数だけシミュレーションを実行
    for _ in range(trials):
        x = 0      # お釣りとして持っている1000円札の枚数
        min_x = 0  # xの最小値を記録
        
        # 15人の部員が順番に支払う
        for _ in range(MEMBER_N):
            if random.random() < 0.5:
                # 50%の確率で1000円札3枚で支払う
                x += 3
            else:
                # 50%の確率で10000円札1枚で支払う
                x -= 7
            # 現在のxの最小値を更新
            min_x = min(min_x, x)
        
        # 必要なお釣り枚数を計算
        # min_x が 0以上ならお釣り不要, 0未満ならその絶対値だけ必要
        y = 0 if min_x >= 0 else abs(min_x)
        result.append(y)
    
    # 結果を表示
    print("=== つり銭問題シミュレーション結果 ===")
    print(f"シミュレーション回数: {trials:,}回")
    print(f"必要なお釣りの枚数の平均: {sum(result)/len(result):.2f}枚")
    print(f"最小必要お釣り枚数: {min(result)}枚")
    print(f"最大必要お釣り枚数: {max(result)}枚")
    print(f"お釣り不要(0枚)の確率: {result.count(0)/len(result)*100:.1f}%")
    
    # 分布を表示
    from collections import Counter
    distribution = Counter(result)
    print("\n=== お釣り枚数の分布 ===")
    for count in sorted(distribution.keys()):
        print(f"{count}枚: {distribution[count]:,}回 ({distribution[count]/len(result)*100:.1f}%)")

if __name__ == "__main__":
    tsurisen_simulation()

実装の説明

このコードは、部員15人がランダムに1000円札3枚または10000円札1枚で会費を払う場合について1万回試行し、必要な1000円札のお釣り枚数が最小で何枚必要かを統計的に調べます。

出力される統計情報:

  • 必要なお釣りの枚数の平均値
  • 最小必要お釣り枚数(最頻値)
  • 最大必要お釣り枚数
  • お釣り不要(0枚)の確率

実用的な対策とアドバイス

幹事向けの準備指針

  1. 事前準備: 平均的な必要枚数分の1000円札を用意
  2. リスク管理: 最大必要枚数分の余裕を持って準備
  3. 効率的な集金方法:
    • 事前に支払い方法を確認
    • 小額紙幣での支払いを推奨
    • 電子マネー併用を検討

シミュレーション結果の活用

  • 確率的な準備: 95%の確率でカバーできる枚数を計算
  • コスト分析: お釣り準備のコストとリスクのバランス
  • 代替案の検討: 支払い方法の変更による効果測定

モデル化の確認

1. モデル化の目的を明らかにする

対象の選択

  • シミュレーション対象: 部の会費を集める際のつり銭問題

目的の決定

  • 目的: 必要なつり銭の枚数を調べる

2. モデルの構造を決定する

現実問題の抽象化

必要な構造情報:

  • 会費の支払い方法
  • お釣りの支払い方法
  • お釣りの枚数
  • お札や小銭の種類
  • サークルの人数

3. 分析手法の選択

  • プログラム(Python)
  • Excel
  • 専用アプリ

4. 仮定・条件の設定

シミュレーション条件

  • 部員数: 15人
  • 支払い方法: 一人ずつ幹事に支払う
  • 支払いパターン:
    • 1000円札3枚で支払う
    • 10000円札1枚で支払う
  • お釣り: 10000円札で支払われた場合、1000円札7枚をお釣りとして支払う

5. モデルの数式表現

数学的モデル

  • 状態変数: xt = 時点tでの1000円札の枚数
  • 確率変数: Zi = 部員iの支払い方法
    • P(Zi = 1) = 0.5 (1000円札3枚)
    • P(Zi = -1) = 0.5 (10000円札1枚)

状態遷移式

xt+1 = xt + 3Zi if Zi = 1

xt+1 = xt - 7 if Zi = -1

目的関数

y = max(0, -mint=115 xt)

期待値の計算

  • 1000円札3枚の期待増加: 3 × 0.5 = 1.5枚
  • 10000円札1枚の期待減少: -7 × 0.5 = -3.5枚
  • 1人あたりの期待変化: 1.5 - 3.5 = -2枚
  • 15人全体の期待変化: -2 × 15 = -30枚

理論的考察

この問題はランダムウォークの一種で、負の値に到達する確率を求める問題として定式化できます。

高度な分析と検証

統計的検証

import numpy as np
from scipy import stats
import matplotlib.pyplot as plt

def advanced_analysis():
    """高度な統計分析"""
    # シミュレーション実行
    results = []
    for _ in range(100000):
        x, min_x = 0, 0
        for _ in range(15):
            if np.random.random() < 0.5:
                x += 3
            else:
                x -= 7
            min_x = min(min_x, x)
        results.append(0 if min_x >= 0 else abs(min_x))
    
    # 統計量の計算
    mean_val = np.mean(results)
    std_val = np.std(results)
    median_val = np.median(results)
    
    # 信頼区間の計算
    confidence_interval = stats.norm.interval(0.95, loc=mean_val, scale=std_val/np.sqrt(len(results)))
    
    print(f"平均: {mean_val:.3f}")
    print(f"標準偏差: {std_val:.3f}")
    print(f"中央値: {median_val:.3f}")
    print(f"95%信頼区間: [{confidence_interval[0]:.3f}, {confidence_interval[1]:.3f}]")
    
    # 分布の可視化
    plt.hist(results, bins=20, alpha=0.7, density=True)
    plt.xlabel('必要なお釣り枚数')
    plt.ylabel('確率密度')
    plt.title('つり銭必要枚数の分布')
    plt.show()

if __name__ == "__main__":
    advanced_analysis()

感度分析

  • 部員数の影響: 10人、15人、20人での比較
  • 確率の影響: 支払い方法の確率を変更した場合の効果
  • 会費額の影響: 異なる会費額でのシミュレーション

最適化問題としての定式化

min 準備する1000円札の枚数

s.t. P(お釣り不足) ≤ α

演習問題と実践課題

基礎演習

  1. 手計算による小規模シミュレーション
    • 部員数5人で手計算でシミュレーション
    • 支払いパターン: 1000円札3枚 vs 10000円札1枚
    • 各パターンの確率を計算
  2. パラメータ変更実験
    • 部員数を10人、20人に変更して結果を比較
    • 支払い確率を30%:70%に変更して効果を確認

応用課題

  1. 現実的な条件でのシミュレーション
    • 会費額を5000円に変更
    • 支払い方法を3種類に拡張(1000円札5枚、5000円札1枚、10000円札1枚)
    • 確率分布を非対称にする
  2. コスト最適化問題
    • お釣り準備のコストを考慮
    • 不足時のペナルティコストを設定
    • 最適な準備枚数を数値的に求める

高度な課題

  1. 動的シミュレーション
    • 部員が順番に来る時間間隔をランダム化
    • リアルタイムでのお釣り管理
    • 銀行への換金回数も考慮
  2. 多目的最適化
    • コスト最小化とリスク最小化のトレードオフ
    • パレート最適解の探索

モデルの限界と批判的考察

現実との乖離点

  1. 理想化された仮定
    • 支払い方法が2種類のみ(現実は多様)
    • 確率が固定(個人差を無視)
    • 支払い順序がランダム(実際はパターンがある)
  2. 考慮されていない要因
    • 部員の支払い能力の違い
    • 季節性やイベントの影響
    • 電子マネーやクレジットカードの普及
    • 銀行の営業時間制約
  3. 統計的仮定の問題
    • 独立性の仮定(部員間の影響を無視)
    • 正規分布の仮定(実際の分布は不明)
    • 大数の法則の適用限界

モデル改善の方向性

  1. より現実的な確率分布
    • ベータ分布やポアソン分布の使用
    • 個人差を考慮した混合分布
  2. 動的要素の導入
    • 時間経過による確率変化
    • 学習効果や慣れの影響
  3. 多変量分析
    • 部員の属性(年齢、収入)との相関
    • 外部要因(経済状況、イベント)の影響

検証方法の限界

  • シミュレーション回数の妥当性
  • 初期条件の敏感性
  • パラメータ推定の不確実性

国際的視点と応用

多国通貨での応用

この問題は各国の通貨制度に応用可能です:

アメリカ(USD)

  • 会費: $30
  • 支払い方法: $1札30枚 vs $50札1枚
  • お釣り: $50札で支払い時、$1札20枚が必要

ヨーロッパ(EUR)

  • 会費: €25
  • 支払い方法: €5札5枚 vs €50札1枚
  • お釣り: €50札で支払い時、€5札5枚が必要

文化的要因の考慮

  1. 支払い習慣の違い
    • 日本: 現金重視
    • 北欧: 電子決済普及
    • 発展途上国: 小額紙幣多用
  2. 社会的要因
    • 年齢層による支払い方法の違い
    • 経済状況による影響
    • 教育レベルとの相関

英語版サマリー

English Summary

"""
Change Management Simulation

Problem: Determine optimal amount of small bills to prepare
for collecting membership fees from 15 members.

Payment Methods:
- 3 × 1000-yen bills (increases small bills by 3)
- 1 × 10000-yen bill (requires 7 small bills as change)

Objective: Minimize preparation while avoiding shortage
"""

Collection

Citation

unjuno, “シミュレーション工学5,” unjuno'sResearchLibrary, accessed October 8, 2026, https://archive.unjuno.org/items/show/109.

コメント