simulation-orchestrator について
simulation-orchestratorは、シミュレーション実行キャンペーンを管理するPythonスキルです。標準ライブラリを使い、パラメータスイープ用設定の生成、ジョブ状況の追跡、完了結果の集計を行います。
主な機能
- 01grid、linspace、LHSスイープの生成
- 02シミュレーションキャンペーンの初期化と管理
- 03ジョブ状況と進捗の追跡
- 04指標と実行結果の集計
- 05指標の方向に応じた最良実行の特定
活用シーン
- 01パラメータ調査用の設定作成
- 02シミュレーションキャンペーンのジョブ監視
- 03完了した実行を結果指標で比較
- 04指標の最小値または最大値を選択
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ heshamfs/ materials-simulation-skills --skill simulation-orchestratorインストール後、Claude Code で/simulation-orchestratorを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
CHANGELOG.mdevals/evals.jsonevals/files/config.jsonsimulation.jsonevals/files/case3_init/config_0000.jsonconfig_0001.jsonconfig_0002.jsonconfig_0003.jsonmanifest.jsonevals/files/case3_status/campaign.jsonevals/files/case4_campaign/campaign.jsonconfig_0000.jsonconfig_0001.jsonconfig_0002.jsonresult_job_0000.jsonresult_job_0001.jsonresult_job_0002.jsonreferences/aggregation_methods.mdcampaign_patterns.mdsweep_strategies.mdscripts/campaign_manager.pyjob_tracker.pyresult_aggregator.pysweep_generator.py詳細
シミュレーションオーケストレーター
目標
複数のシミュレーションキャンペーンを管理するツールを提供します。パラメーターのスイープを生成し、ジョブの実行状況を追跡し、完了した実行の結果を集約します。
要件
- Python 3.10+
- 外部依存関係なし(Python 標準ライブラリのみを使用)
- Linux、macOS、Windows で動作します
収集する入力
オーケストレーションスクリプトを実行する前に、ユーザーから以下を収集してください。
| 入力 | 説明 | 例 |
|---|---|---|
| 基本設定 | シミュレーション設定のテンプレート | base_config.json |
| パラメーター範囲 | 範囲を指定してスイープするパラメーター | dt:[1e-4,1e-2],kappa:[0.1,1.0] |
| スイープ方法 | パラメーター空間のサンプリング方法 | grid、lhs、linspace |
| 出力ディレクトリ | キャンペーンファイルの保存先 | ./campaign_001 |
| シミュレーションコマンド | 各シミュレーションを実行するコマンド | python sim.py --config {config} |
判断の指針
スイープ方法の選択
Need every combination (full factorial)?
├── YES → Use grid (warning: exponential growth with parameters)
└── NO → Is space-filling coverage needed?
├── YES → Use lhs (Latin Hypercube Sampling)
└── NO → Use linspace for uniform sampling per parameter
| 方法 | 最適な用途 | サンプル数 |
|---|---|---|
grid | 低次元(1~3)、正確な端点が必要 | n^d(指数関数的) |
linspace | 1D スイープ、均等な間隔 | パラメーターごとに n |
lhs | 高次元、空間充填型 | ユーザー指定の予算 |
キャンペーン規模の目安
| パラメーター数 | 各グリッドの点数 | 実行総数 | 推奨 |
|---|---|---|---|
| 1 | 10 | 10 | グリッドで問題ありません |
| 2 | 10 | 100 | グリッドで対応できます |
| 3 | 10 | 1,000 | LHS を検討してください |
| 4+ | 10 | 10,000+ | LHS または DOE を使用してください |
スクリプトの出力(JSON フィールド)
| スクリプト | 出力フィールド |
|---|---|
scripts/sweep_generator.py | configs、parameter_space、sweep_method、total_runs |
scripts/campaign_manager.py --action init | campaign_id、total_jobs、config_dir、command_template |
scripts/campaign_manager.py --action status | campaign_id、status、jobs、progress、total_jobs、created_at |
scripts/campaign_manager.py --action list | jobs(ジョブレコードの配列) |
scripts/job_tracker.py | job_id、status、start_time、end_time、exit_code |
scripts/result_aggregator.py | summary(minimize を含む)、statistics、best_run、failed_runs |
スイープするパラメーター名に関する注意:
sweep_generator.pyは、スイープする各値をキーのパスに従って基本設定に書き込みます。単独の名前(例:kappa)はトップレベルのキーを上書きし、ドット表記の名前(例:parameters.kappa)はネストされたキーを対象にします。スイープするキーのパスは、ソルバーが値を読み取る場所と一致している必要があります。parameters.kappaがネストされた設定に対してkappaをスイープすると、使用されないトップレベルのキーが追加され、基本設定の値がそのまま使われます。references/sweep_strategies.mdを参照してください。
ワークフロー
ステップ 1:パラメータースイープの生成
すべてのパラメーターの組み合わせに対する設定を作成します。
python3 scripts/sweep_generator.py \
--base-config base_config.json \
--params "dt:1e-4:1e-2:5,kappa:0.1:1.0:3" \
--method linspace \
--output-dir ./campaign_001 \
--json
ステップ 2:キャンペーンの初期化
キャンペーン追跡構造を作成します。
python3 scripts/campaign_manager.py \
--action init \
--config-dir ./campaign_001 \
--command "python sim.py --config {config}" \
--json
ステップ 3:ジョブ状況の追跡
実行中のジョブを監視します。
python3 scripts/job_tracker.py \
--campaign-dir ./campaign_001 \
--update \
--json
ステップ 4:結果の集約
完了した実行の結果をまとめます。
python3 scripts/result_aggregator.py \
--campaign-dir ./campaign_001 \
--metric final_energy \
--json
result_aggregator.py はデフォルトで最小化します。best_run はメトリック値が最も低い実行です(summary.minimize は true です)。より高い値が望ましい場合(例:収率、精度、スループット)は、--maximize を渡すと、best_run は値が最も高い実行になります。
# Higher is better -> select the maximum
python3 scripts/result_aggregator.py \
--campaign-dir ./campaign_001 \
--metric yield \
--maximize \
--json
判断の指針:より高い値が望ましい場合(収率、精度、スループット)は
--maximizeを渡してください。それ以外の場合、報告されるbest_runは最小値になります。
CLI の例
# Generate 5x3=15 runs varying dt (5 values) and kappa (3 values)
python3 scripts/sweep_generator.py \
--base-config sim.json \
--params "dt:1e-4:1e-2:5,kappa:0.1:1.0:3" \
--method linspace \
--output-dir ./sweep_001 \
--json
# Generate LHS samples for 4 parameters with budget of 20 runs
python3 scripts/sweep_generator.py \
--base-config sim.json \
--params "dt:1e-4:1e-2,kappa:0.1:1.0,M:1e-6:1e-4,W:0.5:2.0" \
--method lhs \
--samples 20 \
--output-dir ./lhs_001 \
--json
# Check campaign status
python3 scripts/campaign_manager.py \
--action status \
--config-dir ./sweep_001 \
--json
# List jobs (read-only), optionally filtered by status
python3 scripts/campaign_manager.py \
--action list \
--config-dir ./sweep_001 \
--status-filter failed \
--json
# Get summary statistics from completed runs (minimize: best = lowest)
python3 scripts/result_aggregator.py \
--campaign-dir ./sweep_001 \
--metric final_energy \
--json
# Maximization metric: best = highest value (yield, accuracy, throughput)
python3 scripts/result_aggregator.py \
--campaign-dir ./sweep_001 \
--metric yield \
--maximize \
--json
会話形式のワークフロー例
ユーザー:フェーズフィールドシミュレーションで、dt と kappa のパラメータースイープを実行したいです。dt は 1e-4 から 1e-2 の間で 5 個、kappa は 0.1 から 1.0 の間で 4 個の値を試したいです。
エージェントのワークフロー:
- 実行総数を計算:5 x 4 = 20 回
- スイープ設定を生成:
python3 scripts/sweep_generator.py \ --base-config simulation.json \ --params "dt:1e-4:1e-2:5,kappa:0.1:1.0:4" \ --method linspace \ --output-dir ./dt_kappa_sweep \ --json - キャンペーンを初期化:
python3 scripts/campaign_manager.py \ --action init \ --config-dir ./dt_kappa_sweep \ --command "python phase_field.py --config {config}" \ --json - ユーザーによるシミュレーション実行後、結果を集約:
python3 scripts/result_aggregator.py \ --campaign-dir ./dt_kappa_sweep \ --metric interface_width \ --json
エラー処理
| エラー | 原因 | 解決方法 |
|---|---|---|
Base config not found | ファイルパスが無効です | ベース設定ファイルが存在することを確認してください |
Invalid parameter format | パラメーター文字列の形式が正しくありません | 形式 name:min:max:count または name:min:max を使用してください |
Output directory exists | 上書きが発生します | --force を使用するか、新しいディレクトリを選択してください |
No completed jobs | 集計する結果がありません | ジョブが完了するまで待つか、失敗がないか確認してください |
Metric not found | 結果ファイルにフィールドがありません | 結果 JSON のメトリック名を確認してください |
他のスキルとの統合
simulation-orchestrator は、他の simulation-workflow スキルと連携します。
parameter-optimization simulation-orchestrator
│ │
│ DOE samples ────────────────>│ Generate configs
│ │
│ │ Run simulations
│ │
│<──────────────────────────── │ Aggregate results
│ │
│ Sensitivity analysis │
│ Optimizer selection │
一般的な組み合わせワークフロー
parameter-optimization/doe_generator.pyを使用してサンプル点を取得しますsimulation-orchestrator/sweep_generator.pyを使用して設定ファイルを作成します- シミュレーションを実行します(ユーザーの責任です)
simulation-orchestrator/result_aggregator.pyを使用して結果を収集しますparameter-optimization/sensitivity_summary.pyを使用して分析します
検証チェックリスト
キャンペーンの best_run や要約統計量を信頼する前に、各項目について具体的な証拠を記録してください。
- スイープ対象のキーのパスによって、ソルバーが読み取る値が実際に変更されたことを確認しました。少なくとも1つの生成された
config_NNNN.jsonを開き、スイープ対象パラメーター(例:parameters.kappa)が、重複した未使用のトップレベルキーではなく、想定された階層で想定どおりの値になっていることを確認しました(sweep_generator.pyはキーのパスを使用して書き込みます)。 -
result_aggregator.py --jsonのジョブ集計を照合し、summary.total_jobs、summary.completed、summary.failedを記録して、completed + failed == total_jobsであることを確認しました。件数が一致しない場合、実行が(結果ファイルの欠落、またはextract_metricがNoneを返したために)通知なしにスキップされています。無視せず、原因を調査してください。 -
completed > 0であることを確認し、記録されたsummary.metricがソルバーによって実際に書き込まれるフィールドと一致することを確認しました。メトリックの誤記や欠落があると、extract_metricはNoneを返し、エラーなしで完了実行数がゼロになります。 -
summary.minimizeを記録し、best_runを示す前に、意図した方向と一致することを確認しました(デフォルトは最小化です。収率/精度/スループットの場合は--maximizeを使用します)。 -
job_tracker.pyの「completed」を物理的な成功として扱っていません。結果ファイルの存在だけでジョブを完了と判定し、exit_codeを 0 として記録するため、実際の終了ステータス/ソルバーログを別途確認し、ゼロ以外のコードや NaN/Inf 出力がないことを確認しました。 - メトリック値に外れ値/妥当性チェック(例:
references/aggregation_methods.mdの Tukey 1.5x IQR)を適用し、best_run.valueが、異常終了した実行による不自然な極値ではなく、物理的に妥当であることを確認しました。 - LHS スイープの場合、使用した
--seedを記録し、サンプルセットを再現できるようにmanifest.json(パラメーターの範囲、total_runs、parameter_space)を保存しました。
よくある落とし穴と誤った正当化
| つい選びがちな近道 | それが誤りである理由/すべきこと |
|---|---|
| 「ジョブトラッカーに完了と表示されているので、実行は成功しました。」 | job_tracker.py は結果ファイルが存在すると「完了」と判定し、exit_code を 0 に固定します。実際の終了コードは読み取りません。部分的な結果ファイルを書き出したクラッシュ実行も、正常に終了した実行と同じように見えます。ソルバーの実際の終了ステータスと出力の妥当性を確認してください。 |
「completed の数が多いので、結果はすべてそろっています。」 | 結果ファイルがないジョブや、extract_metric で読み取れないメトリックを持つジョブは、completed にも failed にも数えられず、黙ってスキップされます。completed + failed と total_jobs を照合してください。差があれば、実行が失われています。 |
「集計で best_run が返されたので、それが最適値です。」 | デフォルトでは、アグリゲーターは最小化します。値が大きいほど良い場合は --maximize を渡さなければならず、そうしないと best_run は最悪の値になります。必ず summary.minimize を記録し、最適化の方向を確認してください。 |
「kappa をスイープしたので、実行ごとに値が変わります。」 | sweep_generator.py はキーのパスを使って値を書き込みます。ベース設定で値が parameters.kappa の下にネストされているのに、単独の名前 kappa をスイープすると、すべての設定で元のネストされた値が維持され、未使用のトップレベルキーが追加されます。このスイープには科学的な意味がありません。ソルバーが読み取る正確なドット区切りパスを指定してください。 |
| 「メトリック名はだいたい合っていれば十分です。」 | メトリック名に誤りがあるか、メトリックが存在しない場合、extract_metric はすべての実行で None を返すため、completed は 0 になり、統計情報も空になります。エラーも発生しません。メトリックがソルバーの出力フィールドと完全に一致することを確認してください。 |
| 「グリッドですべてを網羅できるので、すべてのパラメーターに使いましょう。」 | グリッドは n^d となり、指数関数的に増大します(パラメーター 4 個 × 10 で 10,000 回の実行)。4 次元以上では、予算を慎重に設定して lhs を使い、グリッドはパラメーター 1~3 個の場合に限って使用してください。 |
| 「LHS はランダムなので、何も記録する必要はありません。」 | LHS で再現性を得るには、--seed を固定する必要があります。シードと manifest.json を記録しないと、サンプルセットを再生成したり、その妥当性を示したりできません。 |
セキュリティ
入力の検証
- メトリック名(
result_aggregator.py --metric)は、巧妙に細工されたキーによるパストラバーサルやインジェクションを防ぐため、[a-zA-Z_][a-zA-Z0-9_.]*に照らして検証されます - スイープするパラメーター名(
sweep_generator.py --params)は、[a-zA-Z_][a-zA-Z0-9_]*(.[a-zA-Z_][a-zA-Z0-9_]*)*に照らして検証されます(ネストされたキーにはドット表記を使用)。無効な名前は拒否されます campaign_manager.pyは、シェル連結演算子(;、|、&、バッククォート、$)を拒否するよう、コマンドテンプレートを検証します--paramsの書式文字列は解析・検証されます(name:min:max:count。有限の数値境界を使用し、NaN/Infは拒否されます。min < maxであり、正の整数の個数は最大 100,000 です)。1 回のスイープで指定できるパラメーターは最大 32 個です--methodは固定の許可リスト(grid、linspace、lhs)に照らして検証されます--samplesは、上限(最大 1,000,000)以下の正の整数であることを検証されます--actionは固定の許可リスト(init、status、list)に照らして検証されます。読み取り専用のlistアクションでは、--status-filterがpending、running、completed、failedのいずれかであることを検証します
ファイルアクセス
sweep_generator.pyは、--base-configで指定された単一のベース設定ファイル(JSON)を読み込み、生成された設定を--output-dirに書き込みますresult_aggregator.pyは、結果ファイルごとに 10 MB のファイルサイズ上限と JSON の最大ネスト深度を適用し、数値型を厳密に検証します(bool、NaN、Infを拒否します)- 結果ファイル内のすべての文字列値は、表示する前にサニタイズされます(長さを切り詰め、制御文字を除去します)
- シェルコマンドに埋め込まれる設定パスは、安全な文字の許可リストに照らして検証され、
shlex.quote()でエスケープされます
ツールの制限
- Read:スクリプトのソース、参照資料、ベース設定、キャンペーンのステータスファイルの確認に使用します
- Write:生成したスイープ設定、キャンペーンマニフェスト、集計結果の保存に使用します。書き込み先はユーザーの作業ディレクトリに限定されます
- Grep/Glob:キャンペーンファイルや結果ファイルの検索、参照箇所の検索に使用します
- スキルの
allowed-toolsでは、信頼できないシミュレーション出力を処理する際にエージェントが任意のコマンドを実行できないよう、Bashを除外しています
安全対策
eval()、exec()、動的コード生成は使用しません- すべてのサブプロセス呼び出しで明示的な引数リストを使用します(
shell=Trueは使用しません) - ツールの範囲を縮小し(Bashなし)、エージェントの操作を読み取り/書き込みのみに制限しています
- コマンドテンプレートは検証しますが、スキル自体では実行しません。実行はユーザーの責任です
制限事項
- ジョブスケジューラーではありません:SLURM/PBSへのジョブ投入は行わず、設定の生成とステータスの追跡を行います
- 並列実行には対応していません:ユーザーはシミュレーションを外部で実行する必要があります(GNU parallel、SLURMなどを使用できます)
- ファイルベースの追跡:ステータスはファイルで追跡されます。データベースやリアルタイム監視はありません
- ローカルファイルシステム:すべてのファイルにローカルマシンからアクセスできることを前提としています
参考資料
references/campaign_patterns.md- 一般的なキャンペーン構成references/sweep_strategies.md- パラメータスイープの設計ガイドreferences/aggregation_methods.md- 結果集計の手法
バージョン履歴
正式な日付入りの履歴については、CHANGELOG.mdを参照してください。概要:
- v1.1.3 (2026-06-24):スクリプトの実際の動作に基づく「検証チェックリスト」と「よくある落とし穴と正当化」を追加(結果ファイルのみでの「完了」判定、読み取れないメトリクスのサイレントスキップ、デフォルトでの最小化、キー単位のパスマージの意味)
- v1.1.1 (2026-06-23):
sweep_generator.pyにドット記法によるネストした上書きを追加し、入力検証を強化(--paramsの名前/有限値/件数の上限、--samplesの範囲)。--maximizeとlistアクションを文書化し、「スクリプトの出力」表と使用例の数値を修正 - v1.1.0 (2026-03-26):メタデータ、評価スイート、セキュリティレビュー、CHANGELOGを標準化
- v1.0.0 (2026-02-25):スイープ、キャンペーン、追跡、集計機能を備えた初回リリース