Stage#
組み込みStrategyは、世代処理を Stage という単位に分けて実行します。
Stageは既存AlgorithmとカスタムStageを支えるsequential compatibility surfaceです。
Pipeline は構造化DSLです。
graph-native component、入れ子のPipeline、Repeat、Loop、Branchを記述しますが、OptimizationState を直接実行しません。
Pipelineを実行可能な計画へ変換する処理は、Optimizerが内部でCompilerへ委譲します。
通常の利用者がCompilerを直接呼び出す必要はありません。
このページでは、Stageの互換性用契約、組み込みStage、カスタムStageの実装方法を説明します。 graph-native componentの実装方法は Framework を参照してください。
Stageの役割#
Stage が実装する境界は execute(state: OptimizationState) -> OptimizationState です。
Stageは OptimizationState を受け取り、一つの処理を行って更新後のStateを返します。
この境界はgraph-native componentの execute(StateView) -> StatePatch とは異なります。
クラス属性は3つあります。
name:pipeline["name"]で検索する機械可読識別子label: 人間が読める説明notation:to_pseudocode()で使うLaTeX表記
パイプライン#
Pipelineは構造化されたシーケンスです。要素にはグラフネイティブなコンポーネント、入れ子のPipeline、構造化された制御値を指定できます。Loweringは入れ子の名前をグラフ領域として保持し、実行時にrepeat/loopの進行を再開できるようにします。
操作 |
説明 |
|---|---|
|
|
|
トップレベルの構造エントリを置換 |
|
|
組み込みStage#
次の表は、各運用Stageの本番用contract()(reads、writes、exports)から生成されます。次のコマンドで更新します: python scripts/generate_stage_docs.py。
クラス |
名前 |
ラベル |
表記 |
読み取り |
書き込み |
エクスポート |
|---|---|---|---|---|---|---|
CountGenerationStage |
count_generation |
Count generation |
\(gen \leftarrow gen + 1\) |
|
|
— |
AskStage |
ask |
Generate offspring |
\(\mathcal{Q} \leftarrow \text{ask}(P, n)\) |
|
|
— |
SurrogatePredictStage |
surrogate_predict |
Surrogate prediction |
\(\hat{y} \leftarrow \text{predict}(\mathcal{Q}, \mathcal{A})\) |
|
|
— |
PendingEvaluationContextStage |
pending_evaluation_context |
Pending evaluation context |
\(C \leftarrow \text{pending}(C)\) |
— |
— |
— |
AcquisitionStage |
acquisition |
Acquisition scoring |
\(\mathbf{s} \leftarrow \text{acquire}(\mathcal{Q}, \hat{y}, \mathcal{A})\) |
|
|
— |
SurrogateFitStage |
surrogate_fit |
Fit surrogate |
\(\hat{f} \leftarrow \text{fit}(\mathcal{A})\) |
|
— |
— |
TopKSelectionStage |
top_k_selection |
Top-k pre-selection |
\(\mathcal{Q} \leftarrow \text{top-}k(\mathcal{Q}, \mathbf{s})\) |
|
|
— |
SortByScoreStage |
sort_by_score |
Sort offspring by score |
\(\mathcal{Q} \leftarrow \text{sort\_desc}(\mathcal{Q},\,\mathbf{s})\) |
|
|
— |
EvaluationPlanStage |
evaluation_plan |
Plan evaluation |
\(R \leftarrow \text{plan}(Q)\) |
|
|
— |
AsyncEvaluationSubmitStage |
async_evaluation_submit |
Submit asynchronous evaluation |
|
|
— |
|
EvaluationSubmitStage |
evaluation_submit |
Submit evaluation |
\(H \leftarrow \text{submit}(R)\) |
|
|
— |
EvaluationCollectStage |
evaluation_collect |
Collect evaluation |
\(U \leftarrow \text{collect}(H)\) |
|
|
— |
EvaluationApplyStage |
evaluation_apply |
Apply evaluation |
\(Q \leftarrow \text{apply}(U)\) |
|
|
— |
EvaluationAcknowledgeStage |
evaluation_acknowledge |
Acknowledge evaluation |
\(H \leftarrow \text{ack}(U)\) |
|
|
— |
TrueEvaluationStage |
true_evaluation |
True objective evaluation |
\(\mathcal{Q}_{eval} \leftarrow \text{eval}(\mathcal{Q})\) |
|
|
— |
ArchiveUpdateStage |
archive_update |
Archive update |
\(\mathcal{A} \leftarrow \mathcal{A} \cup \mathcal{Q}_{eval}\) |
|
|
— |
FeedbackStage |
feedback |
Apply feedback |
\(\mathcal{Q} \leftarrow \mathrm{feedback}(\mathcal{Q})\) |
|
|
— |
TellStage |
tell |
Update population |
\(P \leftarrow \text{tell}(P, \mathcal{Q})\) |
|
— |
— |
SurrogateOnlyLoopStage |
surrogate_only_loop |
Surrogate-only generations |
\(\text{for}\;i=1\dots gen\_ctrl\): \(P \leftarrow \mathrm{tell}(P,\,\mathrm{acquire}(\mathrm{predict}(\mathrm{ask}(P))))\) |
|
— |
— |
InitializationStage |
initialization |
Initialize population |
\(\mathcal{A}_0,\,P_0 \leftarrow \mathrm{init}(n_{\mathrm{init}})\) |
— |
— |
— |
TellStageは、状態契約がStage境界を記述するためwrites=()を宣言します。レガシーアルゴリズムを使う場合、レガシーアダプターは実行中にアルゴリズムの個体群を変更できますが、そのランタイム動作はStage契約に追加されません。
契約表には、非同期評価や入れ子のサロゲートのみのループで使われるStageを含む、すべての運用Stageが含まれます。
AskStageはalgorithm.ask()を呼び出し、state.offspringに書き込み、cbmanagerを介してPostCrossover/PostMutation/PostAskEventを発火します。
SurrogatePredictStageは予測データを取得し、AcquisitionStageはスコアを計算して計画用に完全なAcquisitionResultを保持します。
SurrogateFitStageは、アーカイブが変化しない内部ループに先立ってサロゲートを一度だけ事前適合するために使います。
内部ループで適合結果を再利用できる場合は、サロゲート予測Stageの前に使います。
SurrogateOnlyLoopStageはステージベースの互換性戦略で引き続き利用できます。GenerationBasedStrategyは、代わりに構造化されたRepeat領域で同じ制御フローを表します。
注釈
InitializationStageのexecute()に渡されたstate引数は無視され、常に初期化から新しい状態を作ります。
ユーザー定義パイプラインの先頭で、初期化自体をパイプラインの一部として扱いたい場合に使います。
組み込み戦略がこれらのStageと構造化領域をどう組み合わせるかは、strategiesとComponents overviewのパイプライン図を参照してください。 このページでは各Stage単独の契約を扱います。
独自Stageの実装方法#
sequential compatibility経路にカスタムStageを追加するときは、Stageを継承してexecute()を実装します。
state.replace(...)で新しいStateを返し、StageからCompilerのStatePatch値を直接操作しないようにします。
from saealib import Stage
class LogGenerationStage(Stage):
"""A custom stage that just prints the generation number to stdout."""
name = "log_generation"
label = "Log generation number"
def execute(self, state):
print(f"generation {state.gen}")
return state
互換性用Stageで追加の値を渡す場合は、OptimizationState.data に保存します。
値を追加するときは、state.replace(data={**state.data, "key": value}) のように新しい辞書を渡します。
graph-native componentで同じことを行う場合は、宣言した StateKey と StatePatch を使います。
to_pseudocode#
to_pseudocode(expand=False, indent=0)は、各Stageのnotationを論文用の擬似コード(LaTeX algorithmic表記)として出力する仕組みです。
AskStage/TellStage/SurrogateOnlyLoopStageには、expand=TrueのときにAlgorithm.ask_notation/tell_notationを展開する専用実装があります。
関連コンポーネント#
Extension guidelines:
pipeline.replace/findによるStageの並べ替え方strategies: 組み込みStrategyによるStageの組み合わせ方
OptimizationState:
execute()が読み書きする状態オブジェクトComponents overview: パイプライン全体の構造図