OptimizationState#

Layer 4: Extend Framework

OptimizationStateは、Optimizerの実行コンテキストとチェックポイントを保持する値です。Stage互換経路では、Stageがこの状態を直接受け取り、replace()で更新したコピーを次のStageへ渡します。

構造化ランタイムでは、グラフネイティブコンポーネントがOptimizationState全体を受け取ることはありません。コンポーネントは宣言したStateKeyに限定されたStateViewを受け取り、変更をStatePatchとして返します。ランタイムはそのパッチをStateStoreへ適用し、次の実行境界を生成します。

OptimizationStateの役割#

OptimizationStateは、Stage互換経路が実行に使う値、利用者が確認する結果、再開に必要な値の3つをまとめます。コンポーネント契約、グラフ構造、コンパイラの規則を保持する場所ではありません。状態の所有者は、Stage互換経路ではOptimizerと状態自体、graph-native経路ではStateStoreです。

OptimizationStateはreplace()で新しい値を生成し、StateStoreはStatePatchを適用して新しい世代を生成します。コンポーネントがStateStoreやOptimizationStateを直接変更できると、コンパイラもランタイムも、契約外で行われた書き込みを追跡したり、もはや一致しない再開地点を検出したりできません。

二つの状態境界#

OptimizationState と StateView は、異なる実行境界を表します。

境界

受け取る値

返す値

主な利用者

Stage互換境界

OptimizationState

OptimizationState

既存Stage、sequential compatibility ランタイム

graph-native境界

宣言済みの StateView

StatePatch または NodeResult

Component、Compiler、構造化ランタイム

この二つの境界を混同すると、グラフネイティブコンポーネントが任意の状態を読み書きできるように見えます。構造化パイプラインでは、ComponentContractが読み書きするStateKeyを宣言し、ランタイムはその範囲だけをコンポーネントへ渡します。

OptimizationStateが保持する値#

OptimizationState は、利用者が結果を確認したり、実行を再開したりするための値を保持します。

値

内容

problem

最適化対象のProblem

population

現在のPopulationへの互換性用ショートカット

archive

評価済み解のArchiveへの互換性用ショートカット

pareto_archive

非劣解集合への互換性用ショートカット

rng

乱数生成器

fe

真の評価回数

gen

世代数

data

Stage互換拡張用の追加データ

population、archive、pareto_archiveは、内部で名前付きのコレクションを参照します。新しいグラフネイティブコンポーネントが任意の値をdataへ入れる設計にはせず、代わりにStateContractでStateKeyを宣言します。

StateStore、StateView、StatePatch#

StateStoreは、型付きのStateKeyを値に対応付ける状態ストアです。コンポーネントに渡されるStateViewは、ComponentContractが宣言した読み取りキーだけを公開します。

Componentが状態を変更するときは、直接Storeを変更せずに StatePatch を返します。 RuntimeはPatchを現在のStoreへ適用し、次の状態を生成します。 この方式によって、Componentが宣言していないStateを偶然に読み書きすることを防ぎます。

コンパイラは、StateContractのreads、writes、exportsがStateBindingと対応していることを確認します。ランタイムはStateViewを宣言済みの読み取りキーに限定し、StatePatchの書き込みをストアの型付きキーと世代へ適用します。同じキーで競合するパッチや、存在しないキーを削除するパッチは、ランタイムの診断規則に従って扱います。

from saealib.core import StatePatch, StateView
from saealib.core import RUNTIME_GENERATION


def execute(view: StateView) -> StatePatch:
    current = view.get(RUNTIME_GENERATION)
    return StatePatch(writes={RUNTIME_GENERATION: current + 1})

実際のStateKeyは文字列ではなく、saealib.core.stateが提供する型付きキーです。上のコードは、ビューから読み取り、パッチを返す境界だけを示すよう簡略化しています。

Stage互換経路での更新#

カスタムStageはOptimizationStateを受け取り、state.replace(...)で更新後の状態を返します。

from saealib import Stage


class LogGenerationStage(Stage):
    name = "log_generation"

    def execute(self, state):
        print(state.gen)
        return state

Stage互換経路で追加の値を持たせる場合は、state.dataをコピーしてからreplace()に渡します。グラフネイティブコンポーネントで同じ値を扱う場合は、StateKeyとStatePatchを使います。

更新とチェックポイント#

replace(**kwargs) -> OptimizationState は、Stage互換経路で値を更新するためのメソッドです。 archive は評価結果を蓄積するために変更され、rng は乱数を生成するたびに内部状態が進みます。 これらは、他の値を replace() で渡す設計と異なる、明示された例外です。

save(path)とload(path, problem)はOptimizationStateのnpzチェックポイントを扱います。自動チェックポイントについてはCheckpointingを参照してください。pickle形式ではOptimizer側の状態も必要なため、どの保存経路を使うかはCheckpointCallbackとOptimizerの組み合わせで決まります。

どの状態境界を使うか#

  • 既存のStageを実装する:OptimizationState と replace() を使う。

  • 新しいグラフネイティブComponentを実装する:ComponentContract、StateView、StatePatch を使う。

  • Optimizerの実行結果を確認する:Optimizer.run() または Optimizer.iterate() が返す OptimizationState を使う。

  • 実行を再開する:saealib.context.OptimizationState.load() と Optimizer.run_from() を使う。

代表的な失敗#

Stage互換経路で誤った対象にreplace()を呼ぶと、次のStageが期待する値を受け取れません。graph-native経路でStateContractにないキーを読み取り、書き込み、または公開すると、コンパイラの状態効果検証で診断になります。別のProblemや互換性のない計画にチェックポイントを適用すると、保存された状態と実行境界がずれます。

関連コンポーネント#

  • Stage:OptimizationState を直接受け取る互換性用の実行単位

  • Framework:Component、Contract、Graph、Compilerの関係

  • Runtime:計画、ランタイム、StatePatchが適用される境界

  • Population:Population、Archive、ParetoArchiveのデータ構造

  • Checkpointing:チェックポイントの保存と再開

参照#