问题描述¶
Hosaki函数由下式定义:
$$f(x_1, x_2) = \left(1 - 8x_1 + 7x_1^2 - \frac{7}{3}x_1^3 + \frac{1}{4}x_1^4\right)x_2^2 e^{-x_2}$$
这是一个盒约束问题。变量 x1 和 x2 的定义域分别为 [0, 5] 和 [0, 6]。问题的目标是找到该函数的最小值。更多细节,请参阅 hosaki_function.html。
学习要点¶
- 使用 OptAgent 的
create_double_external_function表达外部函数 - 使用浮点决策变量表示连续定义域
- 使用时间上限控制求解预算
建模思路¶
Hosaki函数问题的 OptAgent 模型使用两个 浮点决策变量:x1 和 x2。这些变量的定义域分别为 [0, 5] 和 [0, 6]。
该问题没有任何约束条件,只有一个需要最小化的目标函数。目标函数由 external function 定义。OptAgent 回调通过上下文读取 x1 和 x2 的候选值,并返回该函数在对应点的值;模型随后直接最小化这个 external call 表达式。
本示例使用 solve(model, time_limit_s=...) 限制求解时间。需要控制外部函数的新评价次数时,可使用求解接口的 external_evaluation_limit 参数。
Python 实现¶
import math
from pathlib import Path
from optagent import OptModel, solve
#
# External function
#
def hosaki_function(argument_values):
x1 = argument_values[0]
x2 = argument_values[1]
return (1 - 8 * x1 + 7 * pow(x1, 2) - 7 * pow(x1, 3) / 3 + pow(x1, 4) / 4) * pow(x2, 2) * math.exp(-x2)
def main(output_file=None, time_limit=1):
model = OptModel()
# Numerical decisions
x1 = model.float(0, 5)
x2 = model.float(0, 6)
# Preserve the original black-box model: evaluate Hosaki through an
# external callback rather than rewriting it as a native expression.
external_hosaki = model.create_double_external_function(hosaki_function)
func_call = external_hosaki(x1, x2)
model.minimize(func_call)
# Limit this example by wall-clock time; the objective stays an external call.
solution = solve(model, time_limit_s=float(time_limit))
if not solution.feasible:
raise RuntimeError(f"No feasible solution found: {solution.feasible}")
values = {'objective': func_call.value, 'x1': x1.value, 'x2': x2.value}
result_text = f"obj={values['objective']:.6f}\nx1={values['x1']:.6f}\nx2={values['x2']:.6f}"
print(f"Status = {solution.feasible}\n{result_text}")
if output_file is not None:
Path(output_file).write_text(result_text + "\n", encoding="utf-8")
return solution
本地运行¶
Hosaki 函数不需要外部实例文件,直接调用 main 即可。
solution = main(time_limit=1)