Jas*_*pel 13 python optimization scipy
假设以下功能:
f(x) = x * cos(x-4)
有了x = [-2.5, 2.5]这个功能跨越0的f(0) = 0和f(-0.71238898) = 0.
这是通过以下代码确定的:
import math
from scipy.optimize import fsolve
def func(x):
return x*math.cos(x-4)
x0 = fsolve(func, 0.0)
# returns [0.]
x0 = fsolve(func, -0.75)
# returns [-0.71238898]
Run Code Online (Sandbox Code Playgroud)
使用fzero(或任何其他Python根查找程序)在一次调用中查找两个根的正确方法是什么?是否有不同的scipy功能呢?
hal*_*lex 14
我曾为这项任务写过一个模块.它基于Jaan Kiusalaas的"使用Python工程中的数值方法 "一书中的第4.3章:
import math
def rootsearch(f,a,b,dx):
x1 = a; f1 = f(a)
x2 = a + dx; f2 = f(x2)
while f1*f2 > 0.0:
if x1 >= b:
return None,None
x1 = x2; f1 = f2
x2 = x1 + dx; f2 = f(x2)
return x1,x2
def bisect(f,x1,x2,switch=0,epsilon=1.0e-9):
f1 = f(x1)
if f1 == 0.0:
return x1
f2 = f(x2)
if f2 == 0.0:
return x2
if f1*f2 > 0.0:
print('Root is not bracketed')
return None
n = int(math.ceil(math.log(abs(x2 - x1)/epsilon)/math.log(2.0)))
for i in range(n):
x3 = 0.5*(x1 + x2); f3 = f(x3)
if (switch == 1) and (abs(f3) >abs(f1)) and (abs(f3) > abs(f2)):
return None
if f3 == 0.0:
return x3
if f2*f3 < 0.0:
x1 = x3
f1 = f3
else:
x2 =x3
f2 = f3
return (x1 + x2)/2.0
def roots(f, a, b, eps=1e-6):
print ('The roots on the interval [%f, %f] are:' % (a,b))
while 1:
x1,x2 = rootsearch(f,a,b,eps)
if x1 != None:
a = x2
root = bisect(f,x1,x2,1)
if root != None:
pass
print (round(root,-int(math.log(eps, 10))))
else:
print ('\nDone')
break
f=lambda x:x*math.cos(x-4)
roots(f, -3, 3)
Run Code Online (Sandbox Code Playgroud)
roots找到f区间[ a,b] 中的所有根.
定义你的函数,使它可以采用标量或numpy数组作为参数:
>>> import numpy as np
>>> f = lambda x : x * np.cos(x-4)
Run Code Online (Sandbox Code Playgroud)
然后传递一个参数向量fsolve.
>>> x = np.array([0.0, -0.75])
>>> fsolve(f,x)
array([ 0. , -0.71238898])
Run Code Online (Sandbox Code Playgroud)
一般来说(即除非您的函数属于某个特定类)您无法找到所有全局解决方案 - 这些方法通常从给定的起点进行局部优化。
但是,您可以将 math.cos() 与 numpy.cos() 切换,这将对您的函数进行向量化,以便它可以一次求解多个值,例如 fsolve(func, np.arange(-10,10,0.5))。