Function-based Bounds (dynamic_bounds_fun)
Warning
This feature is currently under development. Its behavior and usage may change in future versions.
Sample Files
Note
The full samples are here:
sample project,
sample script
What is dynamic_bounds_fun
dynamic_bounds_fun is a feature that can be used as an alternative to regular constraints,
when “the lower/upper bounds of a variable can be expressed as a function of other variables.”
In pyfemtet, regular constraints work as follows:
propose variables
check whether the constraint is violated
if violated, propose again
When constraints are tight, steps 2→3 may repeat many times.
With dynamic_bounds_fun, invalid proposals are never generated, eliminating this overhead.
Note
dynamic_bounds_fun is not a feature for speeding up constraint evaluation.
It replaces a regular constraint only when the constraint can be rewritten as variable bounds.
Note
initial_value must always lie within the (dynamic) lower and upper bounds.
When dynamic_bounds_fun can be used
The constraint can be rewritten in the form “the lower/upper bound of a variable is a function of other variables.”
Other constraints should still be implemented using
add_constraint. (dynamic_bounds_funand regular constraints can be used together.)
Example where dynamic_bounds_fun is applicable
Problem
Variable a: lower 0, upper 10
Variable b: lower 0, upper 10
Constraint:
a + b < 10
This constraint can be rewritten as:
Variable a: lower 0, upper 10
Variable b: lower 0, upper
10 - a
Defining dynamic_bounds_fun
First, define a function that computes the bounds:
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']
Note
A dynamic-bounds function must accept opt: AbstractOptimizer
and must return two numeric values representing the lower and upper bounds.
Registering the variable
Then register the function when adding the variable:
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
}
)
With this setup, the bounds of b are always (0, 10 - a),
and combinations that do not satisfy a + b < 10 will never be proposed.
Warning
Only variables that have already been registered with add_parameter
at the time the dynamic_bounds function is evaluated can be referenced
inside that function.
If you reference a variable that has not yet been registered, no error is raised, and the value from the previous iteration will be used unintentionally.
# 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', ...)