如何转换类' sympy.core'到&#39'或' float'为了优化? [英] How to convert class 'sympy.core' to 'number' or 'float' for optimization?

查看:79
本文介绍了如何转换类' sympy.core'到&#39'或' float'为了优化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Python的发起者,我想解决以下问题,但我不知道是什么原因.我使用解决"优化工具解决了这个问题.

I'm a Python initiator and I'd like to solve the following problems, but I don't know what the cause is.I approached the problem using 'fsolve' an optimization tool.

首先,我试图求解一个非线性方程,但在两种情况下都采用了这种方法.有一个案例很奏效.但是我找不到其他情况.

First of all, I'm trying to solve a nonlinear equation, but I've approached it in two cases. One case worked out well. But I can't find another case.

第一种情况(完整情况)

First case (complete case)

from sympy import *
from scipy.optimize import fsolve
import numpy as np


y= symbols('y')
b_1, b_2 = symbols ('b_1,b_2')

b = 1                     
  
f = b_1 + b_2*(y/b)**2

K1 = integrate(f**2,(y,0,b))


eq1 = diff(K1,b_1)
eq2 = diff(K1,b_2)

    
def function(v):
       
    b_1 = v[0]     
    b_2 = v[1]    
    
    return (2*b_1 + 2*b_2/3,2*b_1/3 + 2*b_2/5)

x0 = [1,1]
       
solutions = fsolve(function,x0)

sol = np.zeros(2)

sol[0] = solutions[0]

sol[1] = solutions[1]

sol
Out[413]: array([-5.e-324,  1.e-323])

第二种情况(失败情况)

Second case (Fail case)

from sympy import *
from scipy.optimize import fsolve
import numpy as np


y= symbols('y')
b_1, b_2 = symbols ('b_1,b_2')

b = 1                     
  
f = b_1 + b_2*(y/b)**2

K1 = integrate(f**2,(y,0,b))


eq1 = diff(K1,b_1)
eq2 = diff(K1,b_2)

    
def function(v):
       
    b_1 = v[0]     
    b_2 = v[1]    
    
    return (eq1,eq2)

x0 = [1,1]
       
solutions = fsolve(function,x0)

sol = np.zeros(2)

sol[0] = solutions[0]

sol[1] = solutions[1]

失败的消息如下.

runfile('C:/Users/user/Desktop/******/untitled0.py', wdir='C:/Users/user/Desktop/******')
Traceback (most recent call last):

  File "C:\Users\user\AppData\Roaming\Python\Python37\site-packages\sympy\core\expr.py", line 327, in __float__
    raise TypeError("can't convert expression to float")

TypeError: can't convert expression to float

Traceback (most recent call last):

  File "C:\Users\user\Desktop\*******\untitled0.py", line 29, in <module>
    solutions = fsolve(function,x0)

  File "C:\Users\user\anaconda3\lib\site-packages\scipy\optimize\minpack.py", line 147, in fsolve
    res = _root_hybr(func, x0, args, jac=fprime, **options)

  File "C:\Users\user\anaconda3\lib\site-packages\scipy\optimize\minpack.py", line 225, in _root_hybr
    ml, mu, epsfcn, factor, diag)

error: Result from function call is not a proper array of floats.

只需将数学表达式eq1,eq2直接输入到返回"中,但结果与手动输入表达式不同.

Simply enter mathematical expressions eq1,eq2 directly into the 'Return', But the results is different from manually input the expressions.

我尝试了很多将符号函数"转换为浮点数组"的方法,但是效果不佳.

I tried many things for converting 'sympy function' into 'float array', but it didn't go well.

我尝试了"lambdify","lambda" ...这些也都失败了.

I tried 'lambdify','lambda'... These were also failed.

如何输入以float形式定义为'sympy'的函数,以使用优化工具'fsolve'进行计算?

How can i enter a function defined as 'sympy' in the form of float to calculate with the optimization tool 'fsolve'?

实际上,以上代码不是我的情况.因为这只是简化的情况.但是在我的情况下,不可能像上述那样手动输入所有函数,因为我要求解一个十分复杂的非线性方程,该方程具有十分或更高阶的数百个项.

Actually, The codes above are not my cases. As it is Just simplified situation. But in my cases it's not possible to manually input all functions like above that because i am going to solve a very complex non-linear equation that has hundreds of terms in the tenth or higher order.

有没有人可以解决这个问题?

Is there anyone who can solve this problem?

推荐答案

要在 fsolve 中工作,您的函数必须与 x0 值.

To work in in fsolve your function has to run with something like the x0 value.

在第一种情况下:

In [1]: def function(v): 
   ...:         
   ...:     b_1 = v[0]      
   ...:     b_2 = v[1]     
   ...:      
   ...:     return (2*b_1 + 2*b_2/3,2*b_1/3 + 2*b_2/5) 
   ...:                                                                                              

In [3]: function([1,2])                                                                              
Out[3]: (3.333333333333333, 1.4666666666666668)

在第二种情况下:

In [4]: y= symbols('y') 
   ...: b_1, b_2 = symbols ('b_1,b_2') 
   ...:  
   ...: b = 1                      
   ...:    
   ...: f = b_1 + b_2*(y/b)**2 
   ...:  
   ...: K1 = integrate(f**2,(y,0,b)) 
   ...:  
   ...:  
   ...: eq1 = diff(K1,b_1) 
   ...: eq2 = diff(K1,b_2) 
   ...:                                                                                              

In [5]: eq1                                                                                          
Out[5]: 
       2⋅b₂
2⋅b₁ + ────
        3  

In [6]: eq2                                                                                          
Out[6]: 
2⋅b₁   2⋅b₂
──── + ────
 3      5  

In [7]: def function(v): 
   ...:         
   ...:     b_1 = v[0]      
   ...:     b_2 = v[1]     
   ...:      
   ...:     return (eq1,eq2) 
   ...:                                                                                              

In [8]: function([1,2])                                                                              
Out[8]: 
⎛       2⋅b₂  2⋅b₁   2⋅b₂⎞
⎜2⋅b₁ + ────, ──── + ────⎟
⎝        3     3      5  ⎠

这将返回一个sympy表达式的元组.与第一种情况一样, fsolve 需要数字.请注意, v 值不会更改返回的表达式.函数内部的 b_1 eq 中的b₁不同.

This returns a tuple of sympy expressions. fsolve needs numbers as in the first case. Note that the v values don't change the returned expressions. The b_1 inside the function is not the same as the b₁ in the eq.

我们可以使用 lambdify 将sympy转换为numpy函数:

We can use lambdify to convert the sympy into numpy functions:

In [15]: f1 = lambdify([b_1, b_2], eq1)                                                              

In [17]: f1(1,2)                                                                                     
Out[17]: 3.333333333333333

In [18]: f2 = lambdify([b_1, b_2], eq2)                                                              

In [19]: def function(v): 
    ...:         
    ...:     b_1 = v[0]      
    ...:     b_2 = v[1]     
    ...:      
    ...:     return (f1(b_1,b_2), f2(b_1, b_2))                                                                                              

In [20]: function([1,2])                                                                             
Out[20]: (3.333333333333333, 1.4666666666666668)

这现在应该可以在 fsolve 中使用.

This should now work in fsolve.

请注意 lambdify 产生了什么:

In [22]: print(f1.__doc__)                                                                           
Created with lambdify. Signature:
func(b_1, b_2)

Expression:

2*b_1 + 2*b_2/3

Source code:

def _lambdifygenerated(b_1, b_2):
    return (2*b_1 + (2/3)*b_2)

尝试执行类似操作时产生了您的错误:

Your error was produced when trying to do something like:

In [23]: np.array(Out[8], dtype=float)                                                               
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-23-5f2b1be0015f> in <module>
----> 1 np.array(Out[8], dtype=float)

/usr/local/lib/python3.6/dist-packages/sympy/core/expr.py in __float__(self)
    325         if result.is_number and result.as_real_imag()[1]:
    326             raise TypeError("can't convert complex to float")
--> 327         raise TypeError("can't convert expression to float")
    328 
    329     def __complex__(self):

TypeError: can't convert expression to float

(看起来您没有提供完整的追溯.在任何情况下, fsolve 都需要一个函数,该函数在给定数组输入(形状如 x0 ).

(It doesn't look like you gave the full traceback. In any case, fsolve wants a function that returns an array of floats (or equivalent) when given array input (shaped like x0).

lambdify 是将sympy表达式转换为 numpy 兼容函数的最好方法,即使不是唯一方法.

lambdify is the best, if not the only, way to convert a sympy expression into a numpy compatible function.

这篇关于如何转换类&amp;#39; sympy.core&amp;#39;到&amp;#39&amp;#39;或&amp;#39; float&amp;#39;为了优化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆