関数を使った上下限指定 (dynamic_bounds_fun)
警告
これは開発中の機能です。将来のバージョンでは動作と使い方が変更される可能性があります。
サンプルファイル
注釈
この機能を使った完全なサンプルは pipe_dynamic_bounds.py です。 pipe.femprj を Femtet で開いた状態でお試しください。
dynamic_bounds_fun とは
dynamic_bounds_fun は、通常の拘束条件の代替として使える機能で、 「ある変数の上下限が他の変数の関数で表せる」 場合に利用できます。
pyfemtet では、通常の拘束関数は以下の流れで処理されます:
変数を提案
拘束違反か判定
違反していれば再提案
拘束が厳しい場合は 2→3 が何度も繰り返されます。 dynamic_bounds_fun を使うと 不可能な提案がそもそも出ない ため、この無駄が発生しません。
注釈
dynamic_bounds_fun は拘束関数を高速化する機能ではなく、拘束関数が変数の上下限の形で書ける場合に限り、拘束そのものを置き換える機能です。
注釈
initial_value は常に上下限の範囲に入っている必要があります。
dynamic_bounds_fun を使うタイミング
ある変数の下限・上限が他の変数の関数として書ける場合
それ以外の拘束は通常通り
add_constraintを使います(dynamic_bounds_funと通常の拘束関数は併用可能)。
dynamic_bounds_fun が利用可能な例
問題
変数 a: 下限 0, 上限 10
変数 b: 下限 0, 上限 10
拘束関数:
a + b < 10
この拘束関数は次のように書けます:
変数 a: 下限 0, 上限 10
変数 b: 下限 0, 上限
10 - a
dynamic_bounds_fun の定義
まず、上下限を計算する関数を定義します。
def dynamic_bounds_of_b(opt) -> tuple[float, float]:
"""Return the dynamic lower and upper bounds of b."""
params = opt.get_variables()
return 0, 10. - params['a']
注釈
動的な上下限を計算する関数は、引数として opt: AbstractOptimizer を取り、戻り値として下限・上限を表す ふたつの数値 を返さなければなりません。
変数登録
次に、変数追加時にその関数を登録します。
femopt.add_parameter(name='a', initial_value=0, lower_bound=0, upper_bound=10)
femopt.add_parameter(
name='b', initial_value=0,
properties={
'dynamic_bounds_fun': dynamic_bounds_of_b
}
)
これにより、b の上下限は常に (0, 10 - a) となり、 a + b < 10 を満たさない組合せは最初から提案されなくなります。
警告
dynamic_boundsを計算する 関数の中では、その上下限を適用する変数より前に add_parameter された変数しか参照してはいけません。
そうしない場合、エラーや警告なく前回の試行の変数値が参照されてしまいます。
# OK:
add_parameter('a', ...)
add_parameter('b', properties={"dynamic_bounds_fun": fun_using_a})
# NG:
add_parameter('b', properties={"dynamic_bounds_fun": fun_using_a})
add_parameter('a', ...)