简体   繁体   English

用Python中的“最小化”求解非线性联立方程

[英]Solving nonlinear simultaneous equations using `minimize` in Python

I want to solve two simultaneous equations using the scipy.optimize.minimize function in Python, specifically with the dog-leg trust-region algorithm. 我想用Python中的scipy.optimize.minimize函数解决两个联立方程,特别是狗腿信任区域算法。 This requires me to specify the Jacobian of the problem by using scipy.optimize.approx_fprime , as suggested in one solution to my other post . 这需要我通过使用scipy.optimize.approx_fprime指定问题的雅可比行列式,如我在其他帖子的一个解决方案中所建议的那样。

My MWE is: 我的MWE是:

import numpy as np
from scipy.integrate import quad
from scipy.optimize import minimize,approx_fprime

def myfunc(guess,a,b,c,d):

    # initial guesses
    x0 = guess[0]
    x1 = guess[1]

    # functions
    z0 = lambda x: c*np.sqrt(a**3*x0)*np.sin(x)/x0**b
    z1 = lambda x: np.cos(b*x0*x)/x1**a

    # numerical integration with 'quad'
    z0int = quad(z0,-200,200,epsabs=1e-8,epsrel=1e-6)[0] - 3.2*d
    z1int = quad(z1,-200,200,epsabs=1e-8,epsrel=1e-6)[0] + c

    return (z0int,z1int)

# constants
a = 0.2
b = 1.1
c = 2.5
d = 0.9

guess = np.array([0.3,0.02]) # initial guesses

myJac = approx_fprime(guess,myfunc,1e-9,a,b,c,d) # Jacobian

# minimisation, want to find x0 such that z0int=0 and z1int=0
xopt = minimize(myfunc,guess,args=(a,b,c,d),method='dogleg',jac=myJac)

print(xopt)

However I get an error TypeError: unsupported operand type(s) for -: 'tuple' and 'tuple' . 但是我得到一个错误TypeError: unsupported operand type(s) for -: 'tuple' and 'tuple' I'm not really familiar with the Python optimization functions so could you please explain what is wrong and how to correct the code? 我不是很熟悉Python优化函数,所以请你解释一下有什么问题以及如何纠正代码?

For minimisation, your function should return a single integer. 对于最小化,您的函数应返回一个整数。 You are returning a tuple, so that is the problem. 你正在返回一个元组,所以这就是问题所在。 The minimize function checks if the new value is lower then the old one (thus subtract) but it wants to subtract tuples instead of ints. minimize函数检查新值是否低于旧值(因此减去)但它想要减去元组而不是整数。

Change your code to only return a single integer from the function you wish to minimize 将代码更改为仅从要最小化的函数返回单个整数

EDIT according to comments 根据评论编辑

def myfunc(guess,a,b,c,d):

    # initial guesses
    x0 = guess[0]
    x1 = guess[1]

    # functions
    z0 = lambda x: c*np.sqrt(a**3*x0)/x0**b
    z1 = lambda x: np.cos(b*x0)/x1**a

    # numerical integration with 'quad'
    z0int = quad(z0,-200,200,epsabs=1e-8,epsrel=1e-6)[0] - 3.2*d
    z1int = quad(z1,-200,200,epsabs=1e-8,epsrel=1e-6)[0] + c

    return (z0int,z1int) # <-- This should only return 1 single integer

For solving a system of equations, you are aiming to minimize the sum of squares of left-hand sides. 为了求解方程组,您的目标是最小化左侧的平方和。 For this, you might be better off using least_squares instead of more general minimize . 为此,您可能最好使用least_squares而不是更一般的minimize There is an example in the documentation, https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.least_squares.html 文档中有一个示例, https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.least_squares.html

Under the hood it uses a trust-region type approach. 在引擎盖下,它使用信任区域类型方法。

You can rewrite the function to yield both elements, one at a time, instead of returning a tuple. 您可以重写函数以一次一个地生成两个元素,而不是返回元组。 One solution will be returned the 1st time, 3rd time, ..., odd times; 一个解决方案将在第一次,第三次,......,奇数次返回; the other solution returned every even time. 另一个解决方案每时每刻都会返回。 You can then write a new function that you minimize instead; 然后,您可以编写一个最小化的新函数; this new function will initialize 2 lists (evens + odds), using every other yielded element for each list. 这个新函数将初始化2个列表(均衡+赔率),使用每个列表的每个其他生成元素。 This new function will return some type of error metric with respect to both solutions such that its minimization yields the best 2 solutions. 这个新函数将针对两个解决方案返回某种类型的错误度量,使其最小化产生最佳的2个解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM