【问题标题】:Error with passing arguments to python optimised - Nlopt将参数传递给优化的 python 时出错 - Nlopt
【发布时间】:2022-01-27 11:45:55
【问题描述】:

我正在尝试使用 Nlopt 来解决 Python 中的优化问题。我为自己设置了一个基本示例,作为掌握如何浏览库的方法。我已经建立了如下所示的 3 个简单的联立方程,并将它们转换为矩阵形式。我现在正在努力弄清楚为什么 Nlopt 对我给它的东西不满意。

#testing nlopt
import nlopt
import numpy as np
from numpy import array as array

# create 3 simple simultaenous equations

#4x - 3y + z = -10 (1)
#2x + y + 3z = 0 (2)
#-x + 2y -5z = 17 (3)
# sol: x = 1, y = 4, z = -2

constraint_matrix = []
constraint_rhs = []

# eq 1
constraint_matrix.append([4,-3,1])
constraint_rhs.append(-10)

# eq 2
constraint_matrix.append([2,1,3])
constraint_rhs.append(0)

# eq 3
constraint_matrix.append([-1,2,-5])
constraint_rhs.append(17)

A = array(constraint_matrix)
b = np.reshape(array(constraint_rhs), (-1,))

#Ax = b represents the above equations
print(A)
print(b)

ncontrols = A.shape[1]

opt = nlopt.opt(nlopt.LD_SLSQP,ncontrols)

#defining a general function for the above
def my_fn(x):
    print('test')
    print(A)
    print(b)
    val = (A*x) - b
    return val

opt.set_min_objective(my_fn)
x0 = array([6,2,-5])
xopt = opt.optimize(x0)
opt_val = opt.last_optimum_value()
result = opt.last_optimize_result()
print('end')

上面我得到以下错误:

  File "C:\Users\sm\Anaconda3\lib\site-packages\nlopt.py", line 335, in optimize    
    return _nlopt.opt_optimize(self, *args)
TypeError: my_fn() takes 1 positional argument but 2 were given

我还试图弄清楚我实际上是如何将 A 和 b 传递给 my_fn 的,但无济于事。我尝试简单地将 A 和 b 添加为函数的参数,并执行 opt.optimize([x0,A,b]) ,但没有成功。 Nlopt 不能处理矩阵,我是否需要以某种方式将其分解为 3 个单独的等式约束?

任何帮助将不胜感激

干杯

【问题讨论】:

  • edit您的问题包含整个错误消息。

标签: python numpy optimization nlopt


【解决方案1】:

试试

def my_fn(x, grad):
    val = A.dot(x) - b
    return val[0]*val[0] + val[1]*val[1] + val[2]*val[2]

一些 NLopt 算法需要分析梯度。 LD_SLSQP 需要一个梯度。 您的函数返回一个数组。它应该返回一个标量。 我从未尝试用 NLopt 求解方程组。 它适用于我上面的目标函数,并且:

opt = nlopt.opt(nlopt.LN_NELDERMEAD, ncontrols)
opt.set_min_objective(my_fn)
opt.set_xtol_rel(1e-3)
x0 = array([6,2,-5])
xopt = opt.optimize(x0)
opt_val = opt.last_optimum_value()
print('Number of iterations:',opt.get_numevals())
print(xopt) # to see accuracy
print(xopt.round()) # rounded to ints to better check result
print('minf:', opt_val)

算法 LN_LN_NEWUOA 需要更少的迭代。 但是要解决这个方程组,您可以使用:

A = np.array([[4, -3, 1], 
              [2, 1, 3], 
              [-1, 2, -5]])
y = np.array([-10, 0, 17])

x = np.linalg.solve(A, y)
print(x)

这是另一个使用 2 个参数 x[0] 和 x[1] 以及一个约束 x[0] + x[1]

import nlopt
import numpy as np

# definition of objective function to be minimized (Minima at (5,4), (5,6), (7,4), (7,6), 
# but only first point fulfills constraint)
# grad (partial derivatives of the function) must be defined for algorithms using it
# 
def myfunc(x, grad):
    y = 3*abs(x[0] - 7)*abs(x[0] - 5) + 2*abs(x[1] - 6)*abs(x[1] - 4)
    return y

def fc(x, grad):
    y = x[0] + x[1] - 10
    return y

# setting algorithm and number of parameters 
# LN_BOBYQA is the name of the algorithm (L for local, N for no derivatives)
opt = nlopt.opt(nlopt.LN_COBYLA, 2)
opt.set_min_objective(myfunc)
opt.add_inequality_constraint(fc, 1e-8)
opt.set_xtol_rel(1e-8)
#x = opt.optimize([4, 5]) # f(5,5)=2 !!
#x = opt.optimize([0, 0]) # f(5,4)=0 correct
#x = opt.optimize([10, 0]) # f(5,4)=0 correct
#x = opt.optimize([4, 5]) # f(5,5)=2 !!
x = opt.optimize([0, 0])
minf = opt.last_optimum_value()

print('Number of iterations:',opt.get_numevals())
print('x[0]:', x[0])
print('x[1]:', x[1])
print('minf:', minf)

输出应该是:

Number of iterations: 107
x[0]: 4.999999989270988
x[1]: 3.9997967140036654
minf: 0.0008132910098052998

【讨论】:

    猜你喜欢
    • 2022-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-10
    • 1970-01-01
    • 2019-12-10
    相关资源
    最近更新 更多