Termination#

Layer 2: Compose

Optimizerは、交換可能なトップレベルコンポーネントであるTerminationに、最適化をいつ停止するかの判断を委譲します。Optimizer.set_termination(termination)で渡します。Stage互換経路(同期パイプライン)では、各世代の終了時にis_terminated(ctx) -> boolが呼び出されます。

Terminationの役割#

Termination(*conditions)は1つ以上の条件を受け取り、そのいずれか1つでも真になった時点で終了します(OR結合)。 コンストラクタに複数条件を渡す書き方は、後述するany_ofと同じ意味になります。

from saealib import Termination, max_fe, max_gen

termination = Termination(max_fe(2000), max_gen(100))

クラスメソッドも用意されています。

クラスメソッド

意味

Termination.any_of(*conditions)

いずれか1つで終了(Termination(*conditions)と同義)

Termination.all_of(*conditions)

全て満たすまで終了しない

Termination.not_(condition)

条件を満たさない間だけ終了しない

組み込み終了条件#

Terminationに渡す各条件は、TerminationConditionという薄いラッパーです。 組み込みのファクトリ関数はいずれもTerminationConditionを返します。

関数

終了条件

max_fe(value)

評価回数がvalueに到達(ctx.fe >= value)

max_gen(value)

世代数がvalueに到達(ctx.gen >= value)

f_target(value)

アーカイブの最良目的値がvalueに到達。単目的向けで、ctx.directionから最小化/最大化を自動判定する。アーカイブが空の間は終了しない

stalled(window, tol=1e-8)

window世代連続で改善がtolを超えなければ終了

stalledが返すTerminationConditionは、内部に「これまでの最良スコア」をクロージャで保持する状態付きの条件です。 1回のrunにつき1つのインスタンスを使う想定であり、複数のrunで使い回すと前回の状態が残ってしまいます。

Terminationの拡張#

TerminationConditionは抽象基底クラスではなく、任意のcallableを受け取って|(OR)/&(AND)/~(NOT)という演算子オーバーロードを提供する合成用のラッパーです。 OptimizationState -> boolを返すプレーンな関数はどこでも自動的にTerminationConditionへ変換されるため、独自の終了条件を追加するのに基底クラスを継承する必要はありません。

from saealib import Termination, max_fe


def my_condition(ctx):
    f = ctx.archive.get("f")
    return f is not None and len(f) > 0 and f.min() < 1e-6


termination = Termination(max_fe(2000), my_condition)

名前や説明文を明示的に持たせたい場合だけ、TerminationCondition(func, name=..., doc=...)で明示的にラップします。

複数の条件は演算子で宣言的に組み合わせられます。

from saealib import max_fe, max_gen, stalled

both = max_fe(2000) & max_gen(100)  # continues until both are met
either = max_gen(100) | max_fe(2000)  # stops on whichever comes first
not_stalled = ~stalled(20)  # while not stalled

注釈

TerminationCondition のコンストラクタの spec 引数は、Registry がプリセットへシリアライズするときに使う内部フィールドであり、通常のユーザーコードで意識する必要はありません。

関連コンポーネント#

参照#