Posts Tagged with "ISO 26262"

既に発行済みのブログであっても適宜修正・追加することがあります。
We may make changes and additions to blogs already published.

EGASアーキテクチャ (3)

posted by sakurai on January 23, 2025 #935

挙げられたフォールトにはランダムハードウエアフォールトとシステマティックフォールトの2種類が混ざっています。ランダムハードウエアフォールトのみに関して、設計、検証上の注意点を教えてください。

ChatGPT:
ランダムハードウェアフォールト(Random Hardware Fault)は、シリコンや電子部品の経年劣化や物理的要因(放射線、温度、振動など)によって確率的に発生する故障であり、設計上・製造上のミス(いわゆるシステマティックフォールト)とは異なる性質を持ちます。ISO 26262の文脈でも、ランダムハードウェアフォールトに対してはハードウェアアーキテクチャメトリクス(Single Point Fault Metric, Latent Fault Metricなど)や、FMEDA (Failure Mode, Effects and Diagnostic Analysis) を用いて、想定される故障モードを分析し、必要な診断機能や冗長化を実装して要求レベル(ASIL)を満たすことが求められます。

以下では、ランダムハードウェアフォールトに着目したときの設計上・検証上の注意点を整理します。


1. 設計上の注意点

1-1. ハードウェアアーキテクチャメトリクスへの適合

ISO 26262 Part 5 では、Single Point Fault Metric (SPFM)Latent Fault Metric (LFM)、さらにシステムレベルでは Probabilistic Metric for random Hardware Failures (PMHF) といった指標を達成する必要があります。
- SPFM: 単一点故障(検出されずに安全目標を侵害する恐れのある故障)の確率をいかに低く抑えるか。
- LFM: ある程度時間が経過しないと顕在化しない潜在故障をどれだけ検出できるか。
- PMHF: システムレベルで安全目標が侵害される確率を年間あたりいくつに抑えられるか。

これらを満たすため、以下のようなハードウェア診断・冗長化が設計段階で考慮されます。

  1. 冗長化設計
    • 二重化(2エレメント)やモニタ系を持つことで故障検知と安全側制御を可能にする。
  2. 自己診断機能(オンチップBIST, RAMテスト, ECC/パリティ等)
    • CPU/メモリ内部でのビット化け、回路の破損を検出する機構。
  3. アナログフロントエンドの診断
    • センサ用ADCにリファレンス電圧監視、クロスチェックなどを用意して入力故障を検出する。

1-2. FMEDAによる故障モード・診断カバレッジの分析

部品レベルからECUレベルまで、FMEDA (Failure Mode, Effects and Diagnostic Analysis) を実施し、以下を明確にするのが一般的です。

  1. 故障モードの洗い出し
    • 例: トランジスタ短絡、抵抗断線、コンデンサリーク、配線ショート、メモリビットフリップ等。
  2. 故障の影響(Effect)評価
    • その故障が安全機能にどう影響を与えるか(単一点故障なのか、それともシステムは検出可能なのか)。
  3. 診断方法(Diagnostic Coverage)の見積もり
    • どの診断機能を使ってどれくらいの確率で故障を検出できるのか。
  4. 故障率(λ)の妥当性評価
    • 部品の信頼性データ(IEC TR 62380, SN29500, FIDESなどの信頼性規格)を参照し、ランダム故障率を定量化。

FMEDAの結果をもとに、冗長化や診断の追加を行いながら、要求されるハードウェアメトリクスを達成するかどうかを評価します。

1-3. 物理的・環境的要因への対策

ランダムハードウェアフォールトの発生率は、温度・振動・湿度などの使用環境によって大きく変化します。
- 温度上昇 → バイポーラトランジスタの熱暴走、電解コンデンサの寿命短縮など。
- 振動/衝撃 → はんだクラック、部品の破断など。
- 湿度/水分 → PCBへの腐食、漏電による誤作動。

設計段階で、ECUの筐体構造、防振設計、放熱設計、封止(ポッティング)などを吟味し、過酷な環境条件下でも故障率が過度に上がらないようにすることが必要です。

1-4. フェイルセーフコンセプト・安全機構の導入

ランダムフォールトが起きても、システム全体の安全を保つためのフェイルセーフコンセプトを策定します。

  1. デグレード制御
    • 例: スロットルポジションがわからなくなったらリミット制御やアイドル固定。
  2. フェイルサイレント化
    • 致命的な故障が発生した場合は、出力ドライバを強制的にOFFし、出力をカットする。
  3. エスケープパス
    • 車両制御機能が部分的に失われても安全に停止できるようブレーキ・ステア系などの冗長設計を検討。

2. 検証上の注意点

2-1. ハードウェア診断機構のテスト

ランダムハードウェアフォールトを想定した診断機構(例: ECC、BIST、ウォッチドッグなど)が、実際に故障を想定した条件下で正しく検出・動作するかを検証します。

  1. フォールトインジェクションテスト
    • シミュレーションやプロトタイプ基板上で、メモリビットフリップや回路短絡/断線を模擬して、診断が作動するかを確認する。
  2. ソフトウェア診断ルーチンのデバッグ
    • ランタイムで実行するCPU自己診断、RAMテストなどが意図したタイミング・カバレッジで動作しているかを計測。

2-2. 信頼性試験・加速試験

  • 環境試験(熱サイクル、振動、湿度、耐久試験)
    • ランダムフォールトの発生メカニズムを早期に引き起こすための加速試験(例: HALT/HASSなど)で、実際にどの程度の故障が発生するかを評価。
  • バーンイン試験
    • 製造直後の初期故障(Infant Mortality)を除去するために、通電して高温環境下で一定時間運転し、不良素子を早期に検出。

2-3. FMEDA・FTAの整合性確認

  • FMEDA結果で見積もった診断カバレッジや故障率をシステム全体のフォルトツリー解析(FTA) と照合し、
    • 「単一故障が検出できずに安全目標を侵害する確率が、ASIL要件を満たす範囲内にあるか」
    • 「複合故障の検出・制御がどの程度可能か」
      をシミュレーションや実機試験で確認する。

2-4. 整合性レポートとコンフィギュレーション管理

  • 機能安全の開発プロセスでは、文書化追跡性(Traceability) が重視されます。
  • ランダムハードウェアフォールト対策として導入した設計・診断機能が、どの安全要求(SR: Safety Requirement)に対して妥当性を持つのかを明確にレポート化し、ソフトウェアやシステム全体と整合性を取ります。

3. まとめ

ランダムハードウェアフォールトは、システマティックフォールト(設計不良やソフトウェアバグ等)とは異なり、確率的に避けられない側面があります。そのため、ISO 26262のハードウェア開発プロセスでは以下が特に重視されます。

  1. ハードウェアアーキテクチャメトリクス(SPFM/LFM/PMHF)の達成
  2. FMEDAを中心とした故障モード解析と診断カバレッジ設計
  3. 物理的・環境的要因を考慮した信頼性設計(温度、振動、防湿など)
  4. 診断機能(オンチップBISTやECC等)とフェイルセーフコンセプトの徹底
  5. フォールトインジェクションや加速試験等による検証

こうしたプロセスを通じて、ランダムハードウェアフォールトの発生率を可能な限り低減し、故障が発生しても安全要求を侵害しない(もしくは侵害の確率を必要十分に低く抑える)ようなシステムを実現することが重要となります。

ChatGPT の回答は必ずしも正しいとは限りません。重要な情報は確認するようにしてください。


左矢前のブログ 次のブログ右矢

EGASアーキテクチャ (2)

posted by sakurai on January 22, 2025 #934

2エレメントで3層構造を持つアーキテクチャの特徴を詳述してください。

ChatGPT:
以下では、EGAS(電子スロットル制御)システムに代表される「2エレメントで3層構造を持つアーキテクチャ」を例に、各層・各要素がどのように安全性を確保しているかを詳述します。なお「2エレメント」とは主にメイン系(Main)とモニタ系(Monitor)の2経路をもつことを指し、「3層構造」はセンサ入力層・制御(演算)層・アクチュエータ出力層の3段階にわたって安全を確保する仕組みを指します。


1. 全体像と目的

  1. 2エレメント(二重構成)
    メイン系とモニタ系の2経路(あるいは2要素)を用意し、一方の故障を他方が検出して安全な状態に導くことが主眼となります。例えばメイン系がアクセル開度やエンジントルクを計算し、モニタ系が常時メイン系の出力値と自身で計算した値を比較することで、誤作動を即座に検出する構造です。

  2. 3層構造(入力-制御-出力)
    典型的には以下の3つの層に分けて、それぞれで冗長性や診断を組み込みます。

    • 入力層: ペダル位置センサ、スロットル位置センサなど
    • 制御層: マイクロコントローラ(メイン系とモニタ系)、ソフトウェア
    • 出力層: スロットルバルブアクチュエータ、あるいは燃料噴射系など

各層ごとに故障診断(監視)やフェイルセーフを組み合わせることで、高いASIL(Automotive Safety Integrity Level)要求にも対応可能なアーキテクチャを構築します。


2. 入力層 (Sensor Layer)

  1. 二重化センサ
    • アクセルペダル(APS: Accelerator Pedal Position Sensor)やスロットルバルブ位置(TPS: Throttle Position Sensor)などのセンサを、
      $$ 2 \text{系} \quad (\text{例: } \text{APS}_1, \text{APS}_2) $$ のように二重化(あるいは多重化)して設置します。
    • それぞれのセンサが出力する値を常時比較し、異常(出力の大きな乖離など)を検出した際には、メイン系・モニタ系のソフトウェアが安全状態(リミット制御やフェイルセーフ)に移行するようになっています。
  2. 入力信号の妥当性チェック
    • メイン系マイコンとモニタ系マイコンの双方が、二重化センサから取得した信号に対して妥当性チェックを行います。
    • $(\text{APS}_1) $と$ (\text{APS}_2) $の差分が規定値以上なら警報やデグレードモード(パワー制限)へ移行するなど、安全に関する振る舞いをソフトウェア設計上で定義します。

3. 制御層 (Control/Computation Layer)

  1. メイン系 (Main) とモニタ系 (Monitor)
    • メイン系:
      通常のエンジントルク演算、アクセル開度演算などを実施するメインのマイクロコントローラ(あるいはCPUコア)。実際にスロットルバルブや燃料噴射量などを決定します。
    • モニタ系:
      メイン系の演算結果が妥当かを常時監視するサブマイクロコントローラや第二のCPUコア。モニタ系は簡易的な演算(例: アクセル開度→トルクのざっくりとした見積もり)を並行して行い、メイン系の出力を比較・検証します。
  2. クロスチェックと故障検知
    • 同一センサ情報の独立演算
      モニタ系もメイン系とは独立した方法または簡易モデルで同一センサ情報を演算し、メイン系の出力とのクロスチェックを実施します。
    • ウォッチドッグ(Watchdog)やタイマベースの監視
      メイン系・モニタ系の処理が停止したり暴走した場合に、ウォッチドッグタイマがリセットや出力無効化を指示し、出力層を安全側に移行させる仕組みを備えます。
  3. ソフトウェアレイヤの多層防御
    • AUTOSARなどのソフトウェアプラットフォームを使用する場合、BSW(Basic Software) レイヤとASW(Application Software) レイヤでそれぞれ診断機能を実装します。
    • メモリ保護機構やプログラムフロー監視など、ハードウェア機能(例: Lockstep CPU、ECC保護つきメモリ)とも連携してソフトウェアの破損・暴走を検知します。

4. 出力層 (Actuator Layer)

  1. スロットルアクチュエータの冗長化・診断
    • 出力段であるスロットルアクチュエータには、ポジションセンサを二重化するなどしてアクチュエータ内部でも故障を検知できるようにします。
    • モニタ系がスロットルアクチュエータの目標値と実際の開度を比較し、大きな差異が生じた場合は出力を制限する(リミット制御)またはアイドル状態に強制移行させるなどのフェイルセーフを実行します。
  2. 電源制御やリレーによるフェイルサイレント化
    • 出力ドライバの電源ラインに安全リレーやFETスイッチなどを設け、システムが致命的な異常と判断した場合には強制的に駆動信号を遮断します(フェイルサイレント化)。
    • 遮断後はエンジン出力を絞ったり、アクセル操作が反映されない状態にすることで車両の安全を確保します。

5. アーキテクチャがもたらす安全メリット

  1. 単一点故障への耐性
    いずれか1つのセンサやマイコンに故障が生じても、もう一方の正常系(メイン系またはモニタ系)で検知し、安全動作へ移行できる。
  2. 潜在的な故障の早期検知
    クロスチェック(メイン系 vs モニタ系)により、たとえソフトウェアバグやメモリエラーなどの故障モードでも異常値を早期発見しやすい。
  3. ASIL Dレベルへの適合が容易
    エンジン制御のような安全度要求の高い機能ではASIL Dが割り当てられる場合が多いが、2エレメント3層構造によって冗長性と故障検出率を高めることで、ISO 26262の厳しい要求を満たす設計を行いやすい。

6. まとめ

「2エレメントで3層構造を持つEGASアーキテクチャ」は、入力(センサ)・制御(マイコン)・出力(アクチュエータ)の各層において冗長化と診断機構を備え、かつメイン系とモニタ系という2つの経路で相互監視を行う仕組みです。これにより、単一点故障やソフトウェア異常を検出・隔離し、必要に応じて車両を安全状態に導くことが可能となります。ISO 26262で要求される高いASIL(特にCやD)にも適合するために、多層的な安全策が組み込まれるのが最大の特徴です。

ChatGPT の回答は必ずしも正しいとは限りません。重要な情報は確認するようにしてください。


左矢前のブログ 次のブログ右矢

EGASアーキテクチャ

posted by sakurai on January 21, 2025 #933

EGASアーキテクチャについて、ChatGPTに聞いてみました。

機能安全、特にISO 26262において、EGASアーキテクチャとは何ですか?

ChatGPT:
機能安全(特にISO 26262)でよく言及される「EGASアーキテクチャ」とは、一般的に “Electronic Gas (またはGaspedal) System” の略称であり、いわゆるドライブ・バイ・ワイヤ(Drive-by-Wire)方式の電子スロットル制御システムを指します。従来のアクセルペダルとスロットルバルブをワイヤやリンケージで機械的につないでいた構造に代わって、ペダル位置センサ・電子制御ユニット(ECU)・スロットルアクチュエータといった電子的構成要素でアクセル開度を制御する仕組みです。

EGASアーキテクチャでは、以下のような機能安全上の特徴・考慮事項が存在します。

  1. ペダル位置センサの冗長化
    アクセルペダルの踏み込み量を計測するペダル位置センサを二重化や多重化し、それぞれのセンサ信号を相互に監視することで故障検知を行います。ISO 26262では、ASIL(Automotive Safety Integrity Level)の要求に応じて十分な冗長度や故障診断機構を設計し、安全目標を満たす必要があります。

  2. ECU内の監視機能(トルクモニタリング等)
    エンジントルクを演算するメインのマイクロコントローラに加え、モニタ用のサブマイクロコントローラやウォッチドッグなどを配置することで、メイン系の異常動作を検出します。必要に応じてフェイルセーフ(エンジンを強制的にアイドルにするといった制御)を実行し、車両の安全を確保します。

  3. スロットルアクチュエータの安全機構
    スロットルバルブを動かすアクチュエータにも故障診断やフェイルセーフ動作を盛り込むことが求められます。例えば、スロットルバルブのポジションセンサを二重化して、開度に矛盾がないかをチェックする仕組みを設計します。

  4. ASIL割り当てと安全コンセプト
    EGASのように車両の加速・減速に直接関わる機能は、ISO 26262におけるASIL評価で高いレベル(例:ASIL CやD)が割り当てられることが多く、それに応じて高度な故障診断、冗長化、監視機能が求められます。

要するに、EGASアーキテクチャは機械的リンケージを排して電子的にアクセル開度(スロットル開度)を制御するシステムの総称であり、ISO 26262の枠組みにおいては、故障時の安全性(フェイルセーフ)や冗長性を確保するためのさまざまな仕組みを持つことが重要とされています。これにより、アクセル制御の異常が起きても車両挙動が過度に危険にならないようにすることが、機能安全上の大きな目的となります。

ChatGPT の回答は必ずしも正しいとは限りません。重要な情報は確認するようにしてください。


以下はhttps://nvdungx.github.io/EGAS-concept/に掲載されている図の引用です。

図%%.1
図933.1 EGASアーキテクチャ図

なお、本稿はRAMS 2026に投稿予定のため一部を秘匿していますが、論文公開後の2026年2月頃に開示予定です。


左矢前のブログ 次のブログ右矢

Fault treeの自動生成 (21)

posted by sakurai on January 20, 2025 #932

次に、IFやSMを単一エレメントではなく複数エレメントのグループとします。これは実際には基本形のFTに対してIFやSMの部分はBEではなくサブツリーが配置されるため、その処理を行わせるためのAIに対する学習となります。

図%%.1
図932.1 RBD

図932.1を読み取ったChatGPTの生成したMARDファイルを以下に示します。

TEST.BED

*Saphire 8.2.9
TEST =
* Name , Descriptions , Project
A , A fault (20FIT) , TEST
B , B fault (40FIT) , TEST
D , D fault (5FIT) , TEST
E , E fault (10FIT) , TEST
SM_IF_COVREM , SM_IF coverage leftover (1-DC=40%) , TEST
SM_IF_COV , SM_IF coverage (DC=60%) , TEST

TEST.BEI

*Saphire 8.2.9
TEST =
* Name ,FdT,UdC,UdT,UdValue, Prob, Lambda, Tau, Mission, Init,PF,UdValue2,Calc. Prob,Freq,Analysis Type,Phase Type,Project
A ,3, , , , ,2.0E-008, ,1.0E+005, , , ,2.0E-003, ,RANDOM,CD,TEST
B ,3, , , , ,4.0E-008, ,1.0E+005, , , ,4.0E-003, ,RANDOM,CD,TEST
D ,3, , , , ,5.0E-009, ,1.0E+005, , , ,5.0E-004, ,RANDOM,CD,TEST
E ,3, , , , ,1.0E-008, ,1.0E+005, , , ,1.0E-003, ,RANDOM,CD,TEST
SM_IF_COVREM ,1, , , ,4.0E-001, , , , , , ,4.0E-001, ,RANDOM,CD,TEST
SM_IF_COV ,1, , , ,6.0E-001, , , , , , ,6.0E-001, ,RANDOM,CD,TEST

TEST.FTD

TEST =
* Name , Description, SubTree, Alternate, Project
TOP , TEST , , , TEST

TEST.FTL

TEST, TOP =
TOP AND IF SM_IF
IF OR A B
SM_IF OR SM_IF_COVREM DPF
DPF AND SM_IF_COV SM_IF_GROUP
SM_IF_GROUP OR D E

TEST.GTD

TEST=
* Name , Description, Project
TOP , TEST , ,TEST
IF , IF Subtree , ,TEST
SM_IF , SM_IF , ,TEST
DPF , DPF , ,TEST
SM_IF_GROUP , SM_IF Subtree , ,TEST

図932.2にこれらのMARDをSpahireにロードし生成したFTを示します。

$$\img[-1.35em]{/images/withinseminar.png}$$

図932.2 生成されたFT

図932.3にSaphireで取得したMCSを示します。

図%%.3
図932.3 生成されたFTのMCS

Saphireで生成したcut setの表に対してPMHFの欄を追加し、かつ故障率の項を黄色で塗っています。これによりSPF/RFかDPFかが容易に理解されます。

なお、本稿はRAMS 2026に投稿予定のため一部を秘匿していますが、論文公開後の2026年2月頃に開示予定です。


左矢前のブログ 次のブログ右矢

Fault treeの自動生成 (20)

posted by sakurai on January 17, 2025 #931

前稿のExcelの整形マクロはChatGPTにより作成して貰ったものですが、備忘のため貼り付けておきます。

Option Explicit

Sub SampleMacro_Final()

    Dim ws As Worksheet
    Set ws = ActiveSheet  ' カレントシート

    '----------------------------------------------------------------------
    ' (A) まず、B列削除「前」のシートで C列(5行目以降)の最終行を求める
    '     ここをレコードの最終行とする。
    '----------------------------------------------------------------------
    Dim lastRow As Long
    With ws
        lastRow = .Cells(.Rows.Count, "C").End(xlUp).Row
    End With

    If lastRow < 5 Then
        MsgBox "C列の5行目以降にデータがありません。処理を中断します。"
        Exit Sub
    End If

    '----------------------------------------------------------------------
    ' (1) A6:A(lastRow) を数値化
    '----------------------------------------------------------------------
    With ws.Range("A6:A" & lastRow)
        .NumberFormat = "General"
        .Value = .Value
    End With

    '----------------------------------------------------------------------
    ' (2) B列を削除
    '----------------------------------------------------------------------
    ws.Columns("B").Delete

    '----------------------------------------------------------------------
    ' (3) B5:B(lastRow) → 旧C列 の内容を数値化
    '----------------------------------------------------------------------
    With ws.Range("B5:B" & lastRow)
        .NumberFormat = "General"
        .Value = .Value
    End With

    '----------------------------------------------------------------------
    ' (4) C5:C(lastRow) → 旧D列 の内容を数値化
    '----------------------------------------------------------------------
    With ws.Range("C5:C" & lastRow)
        .NumberFormat = "General"
        .Value = .Value
    End With

    '----------------------------------------------------------------------
    ' (5) グリッド線のチェックを外す
    '----------------------------------------------------------------------
    ActiveWindow.DisplayGridlines = False

    '----------------------------------------------------------------------
    ' (6) A4:F4 に罫線 & グレー15% & 中央揃え ほか見出し設定
    '     - ボールド解除(.Font.Bold = False)
    '     - B4セルを"Prob" に
    '     - F4セルに「PMHF」+改行+「[FIT]」
    '----------------------------------------------------------------------
    With ws.Range("A4:F4")
        .Borders.LineStyle = xlContinuous
        .Borders.Weight = xlThin
        .Borders(xlInsideVertical).LineStyle = xlContinuous
        .Borders(xlInsideVertical).Weight = xlThin
        .Borders(xlInsideHorizontal).LineStyle = xlContinuous
        .Borders(xlInsideHorizontal).Weight = xlThin
        .Interior.ColorIndex = 15
        .HorizontalAlignment = xlCenter         ' 横方向を中央揃え
        .VerticalAlignment = xlVAlignCenter     ' 縦方向を中央揃え
        .Font.Bold = False                      ' ★ボールドを外す
    End With

    ' ★ B4セルを"Prob"に
    ws.Range("B4").Value = "Prob"

    ' ★ F4セルは改行入りで"PMHF\n[FIT]"
    ws.Range("F4").Value = "PMHF" & Chr(10) & "[FIT]"
    ws.Range("F4").WrapText = True

    '----------------------------------------------------------------------
    ' (7) A5:F5 を罫線(背景は標準)、揃えはあとでまとめる
    '----------------------------------------------------------------------
    With ws.Range("A5:F5")
        .Borders.LineStyle = xlContinuous
        .Borders.Weight = xlThin
        .Borders(xlInsideVertical).LineStyle = xlContinuous
        .Borders(xlInsideVertical).Weight = xlThin
        .Borders(xlInsideHorizontal).LineStyle = xlContinuous
        .Borders(xlInsideHorizontal).Weight = xlThin
    End With

    '----------------------------------------------------------------------
    ' A列が "total" or 数値 → F列に =B列/1E4*1E9 (小数点1桁表示)
    ' 対象は 行5~lastRow
    '----------------------------------------------------------------------
    Dim r As Long
    Dim valA As Variant
    For r = 5 To lastRow
        valA = ws.Range("A" & r).Value
        If LCase(valA) = "total" Or (IsNumeric(valA) And Not IsEmpty(valA)) Then
            ws.Range("F" & r).Formula = "=B" & r & "/1E4*1E9"
            ws.Range("F" & r).NumberFormat = "0.0"
        End If
    Next r

    '----------------------------------------------------------------------
    ' (8)~(10) グループごとに "外枠のみ" 罫線 → 行6~lastRow
    '----------------------------------------------------------------------
    Dim i As Long, j As Long
    Dim dataA As Variant, dataD As Variant
    Dim foundRow As Long

    i = 6
    Do While i <= lastRow
        dataA = ws.Range("A" & i).Value
        dataD = ws.Range("D" & i).Value  ' 旧E列→新D列

        ' 終了条件: AもDも空 or i>lastRow
        If (IsEmpty(dataA) Or dataA = "") And (IsEmpty(dataD) Or dataD = "") Then
            Exit Do
        End If

        foundRow = 0
        For j = i + 1 To lastRow + 1
            If j > lastRow Then
                foundRow = lastRow + 1
                Exit For
            End If

            Dim tmpA As Variant, tmpD As Variant
            tmpA = ws.Range("A" & j).Value
            tmpD = ws.Range("D" & j).Value

            If (IsEmpty(tmpA) Or tmpA = "") And (IsEmpty(tmpD) Or tmpD = "") Then
                foundRow = j
                Exit For
            End If
            If (IsNumeric(tmpA) And Not IsEmpty(tmpA)) Or (IsEmpty(tmpD) Or tmpD = "") Then
                foundRow = j
                Exit For
            End If
        Next j

        If foundRow = 0 Then
            Exit Do
        End If

        ' グループ外枠のみ罫線
        Call SetOuterBorders(ws.Range(ws.Cells(i, "A"), ws.Cells(foundRow - 1, "F")))

        i = foundRow
    Loop

    '----------------------------------------------------------------------
    ' (11)~(15) 相当: A6:F(lastRow) に最終的な罫線(外枠+縦罫線)
    '----------------------------------------------------------------------
    Call SetOuterBorders(ws.Range("A6:F" & lastRow))
    Call SetInsideVerticalBorders(ws.Range("A6:F" & lastRow))

    '----------------------------------------------------------------------
    ' D1結合対策(任意)
    '----------------------------------------------------------------------
    ws.Range("D1").MergeArea.ClearContents
    With ws.Range("A1:E1")
        .Merge
        .HorizontalAlignment = xlLeft
    End With

    '----------------------------------------------------------------------
    ' E列の色付け
    '----------------------------------------------------------------------
    Dim valE As Variant
    Dim strE As String
    For r = 5 To lastRow

        valA = ws.Range("A" & r).Value
        Dim strA As String
        strA = Replace(Replace(Replace(CStr(valA), vbCr, ""), vbLf, ""), " ", "")
        strA = Trim(strA)
        
        If LCase(strA) = "total" Or (IsNumeric(strA) And strA <> "") Then
            ws.Range("E" & r).Interior.ColorIndex = xlNone
        Else
            valE = ws.Range("E" & r).Value
            strE = Replace(Replace(Replace(CStr(valE), vbCr, ""), vbLf, ""), " ", "")
            strE = Replace(strE, Chr(160), "")
            strE = Trim(strE)
            
            Dim chkE As String
            chkE = LCase(strE)
            
            If Right(chkE, 1) = ")" Then
                chkE = Left(chkE, Len(chkE) - 1)
            End If
            
            If chkE = "" Then
                ws.Range("E" & r).Interior.ColorIndex = xlNone
            ElseIf Right(chkE, 3) = "fit" Then
                ws.Range("E" & r).Interior.Color = RGB(249, 241, 227)
            ElseIf Right(chkE, 1) = "%" Then
                ws.Range("E" & r).Interior.ColorIndex = xlNone
            Else
                ws.Range("E" & r).Interior.ColorIndex = 45
            End If
        End If
    Next r
    
    '----------------------------------------------------------------------
    ' ★ もともとD5にあった括弧を削除(最終的にはD4になる)
    '----------------------------------------------------------------------
    Dim tmpStr As String, p As Long
    tmpStr = ws.Range("D5").Value
    p = InStr(tmpStr, "(")
    If p > 0 Then
        tmpStr = Trim(Left(tmpStr, p - 1))
        ws.Range("D5").Value = tmpStr
    End If

    '----------------------------------------------------------------------
    ' 行2を削除 → D5 が D4 に繰り上がる
    '----------------------------------------------------------------------
    ws.Rows(2).Delete
    lastRow = lastRow - 1

    '----------------------------------------------------------------------
    ' 列オートフィット & 横位置調整
    '   見出し行(A4:F4) → 実際は A3:F3 になる
    '   データ行(A5:F...) → 実際は A4:F...
    '----------------------------------------------------------------------
    ws.Range("A3:F" & lastRow).Columns.AutoFit
    
    With ws.Range("A4:A" & lastRow): .HorizontalAlignment = xlRight: End With
    With ws.Range("B4:B" & lastRow): .HorizontalAlignment = xlRight: End With
    With ws.Range("C4:C" & lastRow): .HorizontalAlignment = xlRight: End With
    With ws.Range("D4:D" & lastRow): .HorizontalAlignment = xlLeft:  End With
    With ws.Range("E4:E" & lastRow): .HorizontalAlignment = xlLeft:  End With
    With ws.Range("F4:F" & lastRow): .HorizontalAlignment = xlRight: End With

    MsgBox "処理が完了しました。最終行は " & lastRow

End Sub

'------------------------------------------------------------------------------
' 外枠だけ罫線を付ける
'------------------------------------------------------------------------------
Private Sub SetOuterBorders(rng As Range)
    With rng
        With .Borders(xlEdgeLeft)
            .LineStyle = xlContinuous
            .Weight = xlThin
        End With
        With .Borders(xlEdgeTop)
            .LineStyle = xlContinuous
            .Weight = xlThin
        End With
        With .Borders(xlEdgeRight)
            .LineStyle = xlContinuous
            .Weight = xlThin
        End With
        With .Borders(xlEdgeBottom)
            .LineStyle = xlContinuous
            .Weight = xlThin
        End With
    End With
End Sub

'------------------------------------------------------------------------------
' 縦の内側線だけ
'------------------------------------------------------------------------------
Private Sub SetInsideVerticalBorders(rng As Range)
    With rng.Borders(xlInsideVertical)
        .LineStyle = xlContinuous
        .Weight = xlThin
    End With
End Sub

ChatGPT の回答は必ずしも正しいとは限りません。重要な情報は確認するようにしてください。

なお、本稿はRAMS 2026に投稿予定のため一部を秘匿していますが、論文公開後の2026年2月頃に開示予定です。


左矢前のブログ 次のブログ右矢

Fault treeの自動生成 (19)

posted by sakurai on January 16, 2025 #930

ChatGPTにRBDを示してFTを生成させます。まず基本形のRBDを図930.1に示します。

図%%.1
図930.1 RBD

ここでは2nd SMは省略しています。その理由はワーストケース評価を行いたいためです。冗長系ではRFがほとんど存在しないため、2nd SMの効果が大きく見えてきますが、このような非冗長系においては1st SMの効果であるRFが支配的であり、経験からはRFは95%以上となる場合が多いと考えます。

図930.1を読み取ったChatGPTの生成したMARDファイルを以下に示します。

TEST.BED

*Saphire 8.2.9
TEST =
* Name , Descriptions , Project
IF_FAULT , IF fault(10FIT) , TEST
SM_FAULT , SM_IF fault(20FIT) , TEST
SM_IF_COVREM , SM_IF coverage leftover(1-DC=10%) , TEST
SM_IF_COV , SM_IF coverage(DC=90%) , TEST

TEST.BEI

*Saphire 8.2.9
TEST =
* Name ,FdT,UdC,UdT,UdValue, Prob, Lambda, Tau, Mission, Init,PF,UdValue2,Calc. Prob,Freq,Analysis Type,Phase Type,Project
IF_FAULT ,3, , , , ,1.0E-008, ,1.0E+005, , , ,1.0E-003, ,RANDOM,CD,TEST
SM_FAULT ,3, , , , ,2.0E-008, ,1.0E+005, , , ,2.0E-003, ,RANDOM,CD,TEST
SM_IF_COVREM ,1, , , ,1.0E-001, , , , , , ,1.0E-001, ,RANDOM,CD,TEST
SM_IF_COV ,1, , , ,9.0E-001, , , , , , ,9.0E-001, ,RANDOM,CD,TEST

TEST.FTD

TEST =
* Name , Description, SubTree, Alternate, Project
TOP , TEST , , , TEST

TEST.FTL

TEST, TOP =
TOP AND IF_FAULT SM_IF
SM_IF OR SM_IF_COVREM DPF
DPF AND SM_IF_COV SM_FAULT

TEST.GTD

TEST=
* Name , Description, Project
TOP , TEST , ,TEST
SM_IF , SM_IF gate , ,TEST
DPF , coverage partial path , ,TEST

図930.2にこれらのMARDをSpahireにロードし生成したFTを示します。

$$\img[-1.35em]{/images/withinseminar.png}$$

比較のために前記事に掲載した基本形のFT図$\dagger$を示します。

図%%.3
図929.1 生成されたFT

図930.3にSaphireで取得したMCSを示します。予想どおりRFが98%以上であり、DPFは2%未満となりました。

図%%.3
図930.3 生成されたFTのMCS

Saphireで生成したcut setの表に対してPMHFの欄を追加し、かつ故障率の項を黄色で塗っています。これによりSPF/RFかDPFかが容易に理解されます。

なお、本稿はRAMS 2026に投稿予定のため一部を秘匿していますが、論文公開後の2026年2月頃に開示予定です。


$\dagger$ S. Atsushi, "A Framework for Performing Quantitative Fault Tree Analyses for Subsystems with Periodic Repairs," 2021 Annual Reliability and Maintainability Symposium (RAMS), Orlando, FL, USA, 2021, pp. 1-6.


左矢前のブログ 次のブログ右矢

Fault treeの自動生成 (18)

posted by sakurai on January 15, 2025 #929

Fault Treeの構成

PMHF式に準拠してFault Tree (FT)を構成します。まず基礎となるFTは図929.1のとおりです。このFT構成法は弊社の$\dagger$過去論文に依るものです。これは後で示すPMHF式を再現するように構成しています。

図%%.1
図929.1 FTの構成

次に対応するPMHF式を示します。前記FTの構成法にはMethod 1, 2, 3と3種あり、それぞれ以下のような特徴があります。

  • Method 1: 2nd SMが無いものとする。もっとも単純なツリーであり、真値よりもPMHFは大となるため、初期にワーストケースを見るのに都合が良い。 $$ M_\text{PMHF}=(1-K_\text{IF,RF})\lambda_\text{IF}+K_\text{IF,RF}\lambda_\text{IF}\lambda_\text{SM} $$
  • Method 2: 2nd SMのカバレージ$K_\text{SM,MPF}$の効果を加えたもの。ただし、真値よりも次のMethod 3で加わる効果が入っていない分だけPMHFが小さく算出されることが問題。ただしこの誤差は$K_\text{SM,MPF}$が小さい時または$\tau$が小さい時は無視できる。 $$ M_\text{PMHF}=(1-K_\text{IF,RF})\lambda_\text{IF}+K_\text{IF,RF}\lambda_\text{IF}\lambda_\text{SM}\color{red}{\left((1-K_\text{SM,MPF})T_\text{lifetime}\right)} $$
  • Method 3: Method 2の効果に加えて、2nd SMの定期検査周期間$\tau$内の不検出効果を加える。PMHFとしては真値であるが、加えた不検出効果は、$K_\text{SM,MPF}$が小さい時または$\tau$が小さい時は無視できる。 $$ M_\text{PMHF}=(1-K_\text{IF,RF})\lambda_\text{IF}+K_\text{IF,RF}\lambda_\text{IF}\lambda_\text{SM}\left((1-K_\text{SM,MPF})T_\text{lifetime}\color{red}{+K_\text{SM,MPF}\tau}\right) $$

Method 3の係数の効果を3Dグラフに表すと図929.2のような形になります。

$$\img[-1.35em]{/images/withinseminar.png}$$

記事#927で述べたように、$K_\text{MPF}$が小さいか$\tau$が小さい場合にはこの効果は無視できます。

なお、本稿はRAMS 2027に投稿予定のため一部を秘匿していますが、論文公開後の2027年2月頃に開示予定です。


$\dagger$ S. Atsushi, "A Framework for Performing Quantitative Fault Tree Analyses for Subsystems with Periodic Repairs," 2021 Annual Reliability and Maintainability Symposium (RAMS), Orlando, FL, USA, 2021, pp. 1-6.


左矢前のブログ 次のブログ右矢

Fault treeの自動生成 (17)

posted by sakurai on January 14, 2025 #928

Method3での新旧係数比較

昔の記事の表217.1にMethod3での手作業の係数がまとめてありますが、これとChatGPTによる係数の割り当てを比較します。

まずChatGPTにカットセットの旧の表(表217.2)と新の表(表925.1)を見せ、old.txtとnew.txtを作成してもらいました。

old.txt

C4,M1,M2
C2,M2,SC1
C2,M1,SC2
C1,SC1,SC2
C1,SA1,SA2
C2,M2,MCU1
C2,M1,MCU2
C1,MCU2,SC1
C1,MCU1,SC2
C5,I2,M1
C5,I1,M2
C1,MCU1,MCU2
C3,I2,SC1
C3,I1,SC2
C7,I1,I2
C3,I2,MCU1
C3,I1,MCU2
C8,I2,P1
C8,I1,P2
C6,M2,P1
C6,M1,P2
C4,P2,SC1
C4,P1,SC2
C9,P1,P2
C4,MCU2,P1
C4,MCU1,P2
C2,D2,M1
C2,D1,M2
C1,D2,SC1
C1,D1,SC2
C1,D2,MCU1
C1,D1,MCU2
C3,D2,I1
C3,D1,I2
C3,CA2,SA1
C3,CA1,SA2
C4,D2,P1
C4,D1,P2
C1,D1,D2
C7,CA1,CA2

new.txt

C12,M1,M2
C17,M2,SC1
C17,M1,SC2
C15,SC1,SC2
C15,SA1,SA2
C17,M2,MCU1
C17,M1,MCU2
C15,MCU2,SC1
C15,MCU1,SC2
C19,I2,M1
C19,I1,M2
C15,MCU1,MCU2
C16,I2,SC1
C16,I1,SC2
C18,I1,I2
C16,I2,MCU1
C16,I1,MCU2
C13,I2,P1
C13,I1,P2
C14,M2,P1
C14,M1,P2
C12,P2,SC1
C12,P1,SC2
C11,P1,P2
C12,MCU2,P1
C12,MCU1,P2
C17,D2,M1
C17,D1,M2
C15,D2,SC1
C15,D1,SC2
C15,D2,MCU1
C15,D1,MCU2
C16,D2,I1
C16,D1,I2
C16,CA2,SA1
C16,CA1,SA2
C12,D2,P1
C12,D1,P2
C15,D1,D2
C18,CA1,CA2

さらにそれを比較するプログラムを作成してもらいました。

#!/usr/bin/env python3
import sys
import csv
from collections import defaultdict

"""
Usage:
  python transform_coverage.py old.txt new.txt

Where:
  old.txt, new.txt each line looks like:
    C4,M1,M2
    C1,SA1,SA2
  etc.

We parse the first token as coverage name (e.g. 'C4'),
the rest as element names (e.g. 'M1','M2').
We store them in a dictionary keyed by the sorted tuple of elements.

Then we produce a transform table:
  old_coverage -> new_coverage
for each matching element-tuple.
If multiple old coverages map to the same new coverage or vice versa,
we show those collisions or many-to-many relationships explicitly.
"""

def parse_cutset_file(filename):
    """
    Parse lines like "C4,M1,M2" into:
      coverage='C4'
      elements=('M1','M2')  # sorted
    We'll store coverage -> set of element_tuples
    We'll also store element_tuple -> coverage
    Returns (coverage2sets, element2cov)
    """
    coverage2sets = defaultdict(set)   # coverage -> { (el1,el2,...) , ... }
    element2cov = {}
    with open(filename, "r", encoding="utf-8") as f:
        for line in f:
            line=line.strip()
            if not line or line.startswith("#"):
                continue
            # split by comma
            parts = [x.strip() for x in line.split(",")]
            coverage = parts[0]
            elements = parts[1:]
            # sort elements so (M1,M2) == (M2,M1)
            sorted_e = tuple(sorted(elements))
            coverage2sets[coverage].add(sorted_e)
            element2cov[sorted_e] = coverage
    return coverage2sets, element2cov

def main(oldfile, newfile):
    old_cov2sets, old_elem2cov = parse_cutset_file(oldfile)
    new_cov2sets, new_elem2cov = parse_cutset_file(newfile)

    # We'll create a transform table: oldCov -> newCov
    # by checking each element tuple in old
    # and see what coverage is assigned in new.
    transform_map = defaultdict(set)  
    # key=oldCoverageName, value=set of newCoverageNames
    # Because it's possible multiple new coverages appear.

    # Also track if some old coverage references multiple distinct new coverage
    # or vice versa.

    # all element tuples from old
    for etuple, oldcov in old_elem2cov.items():
        if etuple in new_elem2cov:
            newcov = new_elem2cov[etuple]
            transform_map[oldcov].add(newcov)
        else:
            # no match in new => discrepancy
            transform_map[oldcov].add("NO_MATCH_IN_NEW")

    # Now produce a nice table
    print("=== Coverage transform table ===")
    for oldcov in sorted(transform_map.keys()):
        newcovs = transform_map[oldcov]
        if len(newcovs)==1:
            single = list(newcovs)[0]
            if single=="NO_MATCH_IN_NEW":
                print(f"{oldcov} => [NO MATCH in NEW file!]")
            else:
                print(f"{oldcov} => {single}")
        else:
            # multiple new coverages
            nclist = ",".join(sorted(newcovs))
            print(f"{oldcov} => {{{nclist}}}  # multiple new coverage found for same old coverage")

    print()
    print("=== Reverse check: new coverage => old coverage ===")
    # We'll do similarly in reverse
    # create new_elem2cov from parse => done
    # but we want coverage -> set of element tuples
    rev_map = defaultdict(set)  # new-> old coverage
    for etuple, newcov in new_elem2cov.items():
        if etuple in old_elem2cov:
            oldcov = old_elem2cov[etuple]
            rev_map[newcov].add(oldcov)
        else:
            rev_map[newcov].add("NO_MATCH_IN_OLD")

    for newcov in sorted(rev_map.keys()):
        oldcovs = rev_map[newcov]
        if len(oldcovs)==1:
            single = list(oldcovs)[0]
            if single=="NO_MATCH_IN_OLD":
                print(f"{newcov} => [NO MATCH in OLD file!]")
            else:
                print(f"{newcov} => {single}")
        else:
            # multiple old coverage
            oclist = ",".join(sorted(oldcovs))
            print(f"{newcov} => {{{oclist}}}  # multiple old coverage found for same new coverage")

    print()
    print("=== Detailed mismatch check (cutset by cutset) ===")
    # We'll unify the union of all element tuples
    all_etups = set(list(old_elem2cov.keys())+ list(new_elem2cov.keys()))
    for et in sorted(all_etups):
        ocov = old_elem2cov.get(et,"-")
        ncov = new_elem2cov.get(et,"-")
        elements_str = ",".join(et)
        print(f"Cutset({elements_str}): old={ocov} , new={ncov}")

if __name__=="__main__":
    if len(sys.argv)<3:
        print("Usage: python transform_coverage.py old.txt new.txt")
        sys.exit(0)
    oldfile=sys.argv[1]
    newfile=sys.argv[2]
    main(oldfile,newfile)

ChatGPT の回答は必ずしも正しいとは限りません。重要な情報は確認するようにしてください。

次に以下のコマンドにより、新旧の対応を表示します。

\$ python transform_cov.py old.txt new.txt | head -10 | tail -9

この出力は

C1 => C15
C2 => C17
C3 => C16
C4 => C12
C5 => C19
C6 => C14
C7 => C18
C8 => C13
C9 => C11

となるので、これを表にまとめます。新係数C??の値は直接MARD中のBEIファイルから拾いました。

表928.1
定数記号 定数値 定数記号 定数値
C1 0.2280772 C15 0.2280772
C2 0.2287720 C17 0.2287720
C3 0.2310880 C16 0.2310880
C4 0.2357200 C12 0.2357200
C5 0.2588800 C19 0.2588800
C6 0.3052000 C14 0.3052000
C7 0.3515200 C18 0.3515200
C8 0.5368000 C13 0.5368000
C9 1.0000000 C11 1.0000000

係数名の振り方は異なるものの、係数値とそのエレメントペアへの割り当ては完全に一致していることが確認できました。数値自体も旧のC1~9は表217.1を用いています。

割り当て係数が全く同じであるにも関わらず昔の記事今の記事の頂上侵害確率が、旧$8.32\color{red}{1}\cdot 10^{-4}\Rightarrow$新$8.32\color{red}{4}\cdot 10^{-4}$、及びPMHFにおいて、旧$55.4\color{red}{7}\Rightarrow$新$55.4\color{red}{9}$が若干異なるのは、Saphireの版数の違いと考えられます。旧は2020年版、新は2024年版です。

なお、本稿はRAMS 2027に投稿予定のため一部を秘匿していますが、論文公開後の2027年2月頃に開示予定です。


左矢前のブログ 次のブログ右矢

Fault treeの自動生成 (16)

posted by sakurai on January 13, 2025 #927

3手法と正解値との比較表

3つの手法1, 2, 3について微妙に異なる結果が出たので、表にまとめます。まずExcelによる正解値を算出するのに不信頼度$F(t)$を $$F(t)\approxλt$$ と近似する場合。次に同じく不信頼度$F(t)$を $$F(t)=1-e^{-λt}$$ で表す場合。最後にSaphire 8.2.9 (2024年版)でカットセット分析を実施した値の順に示します。

-Method 1Method 2Method 3
Excel$F(t)\approx\lambda T$頂上事象侵害確率3.428e-37.903e-58.425e-4
PMHF [FIT]228.55.26956.17
$F(t)=1-e^{-\lambda T}$頂上事象侵害確率3.385e-37.840e-58.324e-4
PMHF [FIT]225.75.22755.49
Saphire頂上事象侵害確率3.381e-37.841e-58.324e-4
PMHF [FIT]225.45.22755.49

SaphireとExcelによる$F(t)=1-e^{-\lambda T}$の結果がほぼ一致したことから(これは次稿で解説予定)、Saphireは不信頼度を近似式ではなく正確に求めていることがわかります。ただし、最初の$\lambda T$はPMHF計算の近似により算出された項であることからこれはこれで正しいと考えられるので、$1-e^{\lambda T}$やSaphireの計算のほうが正確であるとも言えません。

PMHFにおける$\tau$の効果

次にMethod 3における$\tau$の値の効き方を調べます。論文においては$\tau=1 [H]$であるようでした。一方ブログでは$\tau=3,420 [H]$として計算しています。

現状では$\tau=3,420 [H]$の時にPMHFは55.49[FIT]ですが、ASIL-Dターゲットの10[FIT]になるには、$\tau$をどの程度まで小さくする必要があるかをExcelのゴールシークで調べたところ、 $$\img[-1.35em]{/images/withinseminar.png}$$ という結論になりました。これは車両寿命の2.17%となり、この例の冗長系がASIL-Dを満足するためには、定期点検修理間隔は車両寿命の2.17%未満である必要があります。

なお、本稿はRAMS 2027に投稿予定のため一部を秘匿していますが、論文公開後の2027年2月頃に開示予定です。


左矢前のブログ 次のブログ右矢

Fault treeの自動生成 (15)

posted by sakurai on January 10, 2025 #926

Method 3に向けてChatGPT-o1 proに作成させたpythonプログラムを示します。これは各エレメントの故障率及び2nd SMによるカバレージに基づき、FTを構成するファイル群MARDを生成するプログラムです。

#!/usr/bin/env python3
import math

# 1) 各要素のFIT(λ)およびカバレッジDC
FIT_map = {
    "P":   2.33e-7,
    "MCU": 8.18e-7,
    "D":   1.09e-7,
    "I":   5.99e-7,
    "M":   1.00e-6,
    "SC":  1.00e-6,
    "CA":  5.10e-8,
    "SA":  1.00e-6,
}
DC_map = {
    "P":   0.00,
    "MCU": 0.99,
    "D":   0.99,
    "I":   0.60,
    "M":   0.90,
    "SC":  0.99,
    "CA":  0.60,
    "SA":  0.99,
}

# 上流G11,G21 => 36ペア, 下流G12,G22 => 4ペア 合計40
G11 = ["P1","MCU1","D1","I1","M1","SC1"]
G21 = ["P2","MCU2","D2","I2","M2","SC2"]
G12 = ["CA1","SA1"]
G22 = ["CA2","SA2"]

T_mission = 1.5e4         # 15000h
tau_over_TL = 3420.0/15000.0  # 0.228

def lam(e):
    """ Return FIT value (lambda) for e (e.g. 'M1' -> base 'M'). """
    return FIT_map[e[:-1]]

def DC(e):
    """ Return DC coverage for e. """
    return DC_map[e[:-1]]

def factor_method3(e1,e2):
    """ Compute factor(4桁丸め前) for handout(手法3):
        base = (1-DC(e1))*(1-DC(e2))
        factor = base + (1-base)*tau_over_TL
    """
    base = (1 - DC(e1)) * (1 - DC(e2))
    return base + (1.0 - base)*tau_over_TL

def all_pairs():
    """ 全40ペア: 上流36 + 下流4 """
    idx=0
    for x in G11:
        for y in G21:
            idx+=1
            yield idx,x,y
    for x in G12:
        for y in G22:
            idx+=1
            yield idx,x,y

# 2) 40ペアの計算
pairs = []
for (i,e1,e2) in all_pairs():
    pairs.append((i,e1,e2))
pairs.sort(key=lambda x:x[0])

# coverage factorを 4桁丸めでユニーク管理し、C11 から順番付与
coverage_map = {}  # dict: factor_4 -> coverage_name
coverage_list = [] # list to store (coverage_name, factor_4)

def coverage_name_for(f4):
    """ 4桁丸めした factor f4 に対応する coverage 名を割当。 
        最初に出たfactorにはC11、その次C12… 
    """
    if f4 in coverage_map:
        return coverage_map[f4]
    # 次のインデックス
    idx = len(coverage_map)  # 0-based
    cname = f"C{idx+11}"     # e.g. if idx=0 => 'C11', idx=1 => 'C12', ...
    coverage_map[f4] = cname
    coverage_list.append( (cname, f4) )
    return cname

results = []
for (i,e1,e2) in pairs:
    raw_factor = factor_method3(e1,e2)   # not rounded yet
    f4 = round(raw_factor,4)            # 4桁丸め
    c_name = coverage_name_for(f4)
    results.append( (i,e1,e2,raw_factor,f4,c_name) )

results.sort(key=lambda x:x[0])

# 各BasicEvent
basic_events = [
  "P1","MCU1","D1","I1","M1","SC1","CA1","SA1",
  "P2","MCU2","D2","I2","M2","SC2","CA2","SA2"
]

def lam_str(e):
    """ return lam in 3E format """
    l = lam(e)
    return f"{l:.3E}"

def unreli(e):
    """ 1-exp(-lam*T_mission) """
    l= lam(e)
    import math
    return 1.0 - math.exp(-l*T_mission)

# 3) 5ファイルを出力
#   METHOD3.BED, METHOD3.BEI, METHOD3.FTD, METHOD3.FTL, METHOD3.GTD
bed_lines = []
bei_lines = []
ftd_lines = []
ftl_lines = []
gtd_lines = []

# 3.1 BED
bed_lines.append("*Saphire 8.2.9\nTEST =")
bed_lines.append("* Name , Descriptions , Project")
for be in basic_events:
    bed_lines.append(f"{be} , {be}desc , TEST")
for (cn,f4) in coverage_list:
    bed_lines.append(f"{cn} , CoverageFactor_{cn} , TEST")

# 3.2 BEI
bei_lines.append("*Saphire 8.2.9\nTEST =")
bei_lines.append("* Name ,FdT,UdC,UdT,UdValue,Prob,Lambda,Tau,Mission,Init,PF,UdValue2,Calc. Prob,Freq,Analysis Type,Phase Type,Project")
# basic events
for be in basic_events:
    l = lam(be)
    l_str = f"{l:.3E}"
    un = unreli(be)
    un_str = f"{un:.3E}"
    # FdT=3 => exp. dist, prob => un
    line = f"{be} ,3, , ,0.000E+000,0.000E+000,{l_str},0,1.500E+004, , ,0.000E+000,{un_str}, ,RANDOM,CD,TEST"
    bei_lines.append(line)
# coverage
for (cn,f4) in coverage_list:
    f_str = f"{f4:.4E}"
    line = f"{cn} ,1, , ,0.000E+000,{f_str},0.000E+000,0,0.000E+000, , ,0.000E+000,{f_str}, ,RANDOM,CD,TEST"
    bei_lines.append(line)

# 3.3 FTD
ftd_lines.append("TEST =")
ftd_lines.append("* Name , Description, SubTree, Alternate, Project")
ftd_lines.append("METHOD3 ,Method3TopDefinition, , ,TEST")

# 3.4 FTL
ftl_lines.append("TEST,METHOD3 =")
mcsnames = [f"MCS{i:02d}" for i in range(1,41)]
mcs_line = " ".join(mcsnames)
ftl_lines.append(f"METHOD3 OR {mcs_line}")
for (i,e1,e2,rawf,f4,cname) in results:
    mcs = f"MCS{i:02d}"
    ftl_lines.append(f"{mcs} AND {e1} {e2} {cname}")

# 3.5 GTD
gtd_lines.append("TEST=")
gtd_lines.append("* Name , Description, Project")
gtd_lines.append("METHOD3 ,Method3TopGate, TEST")
for i in range(1,41):
    gtd_lines.append(f"MCS{i:02d} ,Pair{i:02d}, TEST")


# ---- Write out actual files ----
def write_file(fname, lines):
    with open(fname, "w", encoding="utf-8") as f:
        for ln in lines:
            f.write(ln+"\n")

write_file("METHOD3.BED", bed_lines)
write_file("METHOD3.BEI", bei_lines)
write_file("METHOD3.FTD", ftd_lines)
write_file("METHOD3.FTL", ftl_lines)
write_file("METHOD3.GTD", gtd_lines)

print("Created METHOD3.BED, METHOD3.BEI, METHOD3.FTD, METHOD3.FTL, METHOD3.GTD successfully.")

ChatGPT の回答は必ずしも正しいとは限りません。重要な情報は確認するようにしてください。

なお、本稿はRAMS 2027に投稿予定のため一部を秘匿していますが、論文公開後の2027年2月頃に開示予定です。


左矢前のブログ 次のブログ右矢


ページ: