问题描述¶
解决 曲线拟合问题 即构建一条曲线或数学函数,使其尽可能最佳地拟合一系列数据点,并可能满足一些约束。曲线拟合既可以是插值(需要对数据进行精确拟合),也可以是平滑(构造一个“平滑”函数来近似拟合数据)。更多详细信息,请参阅 Wikipedia。
在我们这里考虑的曲线拟合问题中,我们希望为一个已定义的函数找到最优参数,以使该函数能最好地将一组输入映射为一组输出。例如,假设映射函数具有如下形式:
$$f(x) = a\sin(b-x) + cx^2 + d$$
我们希望找到参数 a、b、c 和 d,使映射函数能够最佳地拟合观测数据。
学到的要点¶
- 添加浮点型 决策变量
- 使用
sin和pow算子 构造一个非线性表达式 - 最小化一个 非线性目标
Python 实现¶
from pathlib import Path
from optagent import OptModel, solve
def read_float(filename):
return [
float(value)
for value in Path(filename).read_text(encoding="utf-8").split()
]
def read_instance(instance_file):
file_it = iter(read_float(instance_file))
nb_observations = int(next(file_it))
inputs = []
outputs = []
for _ in range(nb_observations):
inputs.append(next(file_it))
outputs.append(next(file_it))
return nb_observations, inputs, outputs
def main(instance_file, output_file=None, time_limit=3):
nb_observations, inputs, outputs = read_instance(instance_file)
model = OptModel()
a = model.float(-100.0, 100.0)
b = model.float(-100.0, 100.0)
c = model.float(-100.0, 100.0)
d = model.float(-100.0, 100.0)
predictions = [
a * model.sin(b - inputs[i]) + c * inputs[i] ** 2 + d
for i in range(nb_observations)
]
errors = [
predictions[i] - outputs[i] for i in range(nb_observations)
]
square_error = model.sum(
model.pow(errors[i], 2) for i in range(nb_observations)
)
model.minimize(square_error)
solution = solve(model, time_limit_s=float(time_limit))
values = {'a': a.value, 'b': b.value, 'c': c.value, 'd': d.value}
result = "\n".join(
[
"Optimal mapping function",
f"a = {values['a']}",
f"b = {values['b']}",
f"c = {values['c']}",
f"d = {values['d']}",
]
)
print(result)
if output_file is not None:
Path(output_file).write_text(result + "\n", encoding="utf-8")
return solution
本地运行¶
INSTANCE_DIR = Path.cwd() / "instances"
solution = main(INSTANCE_DIR / "observations.in", time_limit=3)