【问题标题】:Symbolic matrix and numpy usage error "TypeError: ufunc 'isfinite' not supported for the input types.."符号矩阵和 numpy 使用错误“TypeError: ufunc 'isfinite' not supported for the input types..”
【发布时间】:2018-01-02 12:55:46
【问题描述】:

我试图使用最小化功能执行 scipy.opimization。我正在寻找像Iz,Iy,J,kz,ky,Yc,Yg 这样的所有变量,以使向量 K_P_X 和 f 之间的误差最小。那就是objective function K_P_X-f应该是最低限度的。我认为我的错误与涉及numpy.linalg.norm(sol-f)的计算有关,其中sol 被分配了一个符号向量(K_P_X)。由于数据类型冲突,我收到此错误。如果是这样的话,Q1。任何人都可以建议一种更好的方法来表示等式约束方程(即 constr1()),从而可以避免这个错误。完整代码如下,

import scipy.optimize as optimize
from sympy import symbols,zeros,Matrix,Transpose
import numpy


#Symobolic K matrix
Zc,Yc,Zg,Yg=symbols("Zc Yc Zg Yg",real=True)
A,Iz,Iy,J,kz,ky,E,G,L=symbols("A Iz Iy J kz ky E G L",real=True,positive=True)
E=10400000;G=3909800;L=5

def phi_z():
    phi_z=(12*E*Iy)/(kz*A*G*L**2)
    return phi_z
def phi_y():
    phi_y=(12*E*Iz)/(ky*A*G*L**2)
    return phi_y

K_P=zeros(12,12)
K1=Matrix(([E*A/L,0,0],[0,(12*E*Iz)/((1+phi_y())*L**3),0],[0,0,(12*E*Iy)/((1+phi_z())*L**3)]))
K2=Matrix(([G*J/L,0,0],[0,E*Iy/L,0],[0,0,E*Iz/L]))
Q1=Matrix(([0,Zg,-Yg],[-Zc,0,L/2],[Yc,-L/2,0]))
Q1_T=Transpose(Q1)
Q2=Matrix(([0,Zg,-Yg],[-Zc,0,-L/2],[Yc,L/2,0]))
Q2_T=Transpose(Q2)
K11=K1; K12=K1*Q1; K13=-K1; K14=-K1*Q2; K22=Q1_T*K1*Q1+K2; K23=-Q1_T*K1; K24=-Q1_T*K1*Q2-K2; K33=K1; K34=K1*Q2; K44=Q2_T*K1*Q2+K2

K_P[0:3,0:3]=K11; K_P[0:3,3:6]=K12; K_P[0:3,6:9]=K13; K_P[0:3,9:12]=K14; K_P[3:6,3:6]=K22; K_P[3:6,6:9]=K23; K_P[3:6,9:12]=K24 ;K_P[6:9,6:9]=K33; K_P[6:9,9:12]=K34; K_P[9:12,9:12]=K44

##Converting Upper triangular stiffness matrix to Symmetric stiffness matrix##           
for i in range(0,12):           
    for j in range(0,12):
        K_P[j,i]=K_P[i,j]

K_P = K_P.subs({A: 7.55})
K_P = K_P.subs({Zc: 0})
K_P = K_P.subs({Zg: 0})

X= numpy.matrix([[1],[1],[1],[1],[1],[1],[1],[1],[1],[1],[1],[1]])
K_P_X=K_P*X
f= numpy.matrix([[-9346.76033789],[1595512.77906],[-1596283.83112],[274222.872543],[4234010.18889],[4255484.3549],[9346.76033789],[-1595512.77906],[1596283.83112],[-275173.513088],[3747408.91068],[3722085.0499]])
function=K_P_X-f

def Obj_func(variables):
    Iz,Iy,J,kz,ky,Yc,Yg=variables
    function=K_P_X-f #K_P_X matrix contains the variables like Iz,Iy,J,kz,ky,Yc,Yg.
    return function

def constr1(variables):
    sol = K_P_X     #Here the variables are in the symbolic vector K_P_X
    if numpy.allclose(sol, f):
        return 0.00 #If Error is equal to zero hence required accuracy is reached. So stop optimization
    else:
        return numpy.linalg.norm(sol-f)

initial_guess=[10,10,10,0.1,0.1,0.001,0.001]
cons = ({'type':'eq', 'fun': constr1},{'type': 'ineq', 'fun': lambda variables: -variables[3]+1},{'type': 'ineq', 'fun': lambda variables: variables[3]-0.001},{'type': 'ineq', 'fun': lambda variables: -variables[4]+1},{'type': 'ineq', 'fun': lambda variables: variables[4]-0.001},{'type': 'ineq', 'fun': lambda variables: -variables[5]+0.5},{'type': 'ineq', 'fun': lambda variables: variables[5]-0},{'type': 'ineq', 'fun': lambda variables: -variables[6]+0.5},{'type': 'ineq', 'fun': lambda variables: variables[6]-0})
bnds = ((1, 60), (1, 60),(1, 60),(0.1, 1),(0.1, 1),(0.001, 0.5),(0.001, 0.5))
res=optimize.minimize(Obj_func,initial_guess, bounds=bnds,constraints=cons)

【问题讨论】:

  • 您是否尝试过不使用sympy 的小问题minimize?作为一般规则,您不能在numpyscipy 代码中直接使用sympy 变量或函数。您必须使用 sympy lambdify 函数将 sympy 代码转换为 numpy 等效项。
  • 感谢您的回答。是的,我已经执行了一个较小的函数,但现在,我有一个符号矩阵(K_P)和两个向量(X 和 f),使得 K_PX=f 。我想找到矩阵 K_P 中的所有变量,以最小化误差函数(K_PX-f)。这里 X 和 f 是完全已知的向量。我将很快将这些矩阵 K_P 和向量 X 添加到上述问题中。我还将研究使用lambdify 创建等式约束方程。

标签: python numpy optimization scipy sympy


【解决方案1】:

我将在这里列出一些错误的地方。

  • 正如hpaulj 所说,您不能直接将 SymPy 对象传递给 SciPy 或 NumPy。但是你可以lambdify 然后在最小化例程中使用它
  • 您的最小化设置没有意义。最小化一个具有相同函数必须为零的约束的函数......这不是约束最小化的意思。约束与目标不同。
  • 最好在这里使用least_squares,它专门用于最小化差异的范数(一些向量函数 - 目标向量)。

考虑到这一点,这里是您的脚本重做:

import scipy.optimize as optimize
from sympy import symbols, Matrix, lambdify
import numpy

Iz,Iy,J,kz,ky,Yc,Yg = symbols("Iz Iy J kz ky Yc Yg",real=True,positive=True)
K_P_X = Matrix([[37.7776503296448*Yg + 8.23411191827681],[-340.454138522391*Iz/(21.1513673253807*Iz/ky + 125)],[-9.4135635827062*Iy*Yc/(21.1513673253807*Iy/kz + 125) - 368.454956983948*Iy/(21.1513673253807*Iy/kz + 125)],[-9.4135635827062*Iy*Yc**2/(21.1513673253807*Iy/kz + 125) - 368.454956983948*Iy*Yc/(21.1513673253807*Iy/kz + 125) - 0.0589826136148473*J],[23.5339089567655*Iy*Yc/(21.1513673253807*Iy/kz + 125) + 2.62756822555969*Iy + 921.137392459871*Iy/(21.1513673253807*Iy/kz + 125)],[-5.00660515891599*Iz - 851.135346305977*Iz/(21.1513673253807*Iz/ky + 125) - 37.7776503296448*Yg**2 - 8.23411191827681*Yg],[-37.7776503296448*Yg - 8.23411191827681],[340.454138522391*Iz/(21.1513673253807*Iz/ky + 125)],[9.4135635827062*Iy*Yc/(21.1513673253807*Iy/kz + 125) + 368.454956983948*Iy/(21.1513673253807*Iy/kz + 125)],[9.4135635827062*Iy*Yc**2/(21.1513673253807*Iy/kz + 125) + 368.454956983948*Iy*Yc/(21.1513673253807*Iy/kz + 125) + 0.0589826136148473*J],[23.5339089567655*Iy*Yc/(21.1513673253807*Iy/kz + 125) - 2.62756822555969*Iy + 921.137392459871*Iy/(21.1513673253807*Iy/kz + 125)],[5.00660515891599*Iz - 851.135346305977*Iz/(21.1513673253807*Iz/ky + 125) + 37.7776503296448*Yg**2 + 8.23411191827681*Yg]])
f = Matrix([[-1],[-1],[-1],[-1.00059553353],[3.99999996539],[-5.99940443072],[1],[1],[1],[1],[1],[1]])
obj = lambdify([Iz,Iy,J,kz,ky,Yc,Yg], tuple(K_P_X - f))
initial_guess=[10,10,10,0.1,0.1,0.001,0.001]
bnds = ((1, 60), (1, 60),(1, 60),(0.1, 1),(0.1, 1),(0.001, 0.5),(0.001, 0.5))
lower = [a for (a, b) in bnds]
upper = [b for (a, b) in bnds]
res = optimize.least_squares(lambda x: obj(x[0], x[1], x[2], x[3], x[4], x[5], x[6]), initial_guess, bounds=(lower, upper))
print(res)

变化:

  • lambdify 之前,我们应该有一个 SymPy 表达式。所以K_P_Xf 现在都是 SymPy 矩阵。
  • Lambdified 函数采用 7 个标量参数并返回一个由 K_P_X - f 组成的元组
  • 根据least_squares 的语法要求,边界分为上下两部分
  • 我们不能直接将obj 传递给least_squares,因为它将接收一个数组参数而不是7 个标量。因此,额外的lambda 步骤用于解包向量。

信不信由你,最小化是有效的。它返回res.x,最小点,为

  [  1.00000000e+00,   1.00000000e+00,   1.69406332e+01,
     1.00000000e-01,   1.00000000e-01,   1.00000000e-03,
     1.00000000e-03]

起初看起来很可疑,但这只是因为该点碰到了您放置的边界(10、1、0.1 等等)。只有第三个变量以非活动约束结束。

【讨论】:

  • 您好伊万,谢谢您的回答。我已经使用最小二乘近似比较了你得到的参数。我将这些参数与所需参数进行了比较,发现这些是非常粗略的近似值。对于这种方法,在 scipy 中使用 optimize.minimize 函数会更好吗?我已经用实际的 K_P 矩阵和向量(X 和 f)更新了这个问题。我发现很难放置等式约束,以便在最终优化的参数值处,误差函数应该是最小值 (K_P*X-f) 或零。
  • 由于 K_P 是符号矩阵并且具有所有变量。我不知道如何将这个等式约束用于最小化优化。你能帮我提出这个等式约束 K_P * X - f = 0 吗?
  • 我在上面写道:这不是最小化的工作方式。你不能说“最小化,使最小值为零”。将“objective==0”作为约束的尝试永远不会奏效。
  • 我已经看到在很多情况下,最小化一个函数最终会产生很大的负值。为了将误差函数限制为 0,我给出了等式约束。所以你的意思是在最小二乘优化的情况下,不需要给出等式约束来限制误差函数(K_P * X - f = 0)。我们能否提及优化应该停止的任何容错性?假设 0
猜你喜欢
  • 2020-07-17
  • 1970-01-01
  • 2016-07-01
  • 2022-12-27
  • 2022-12-17
  • 2020-09-29
  • 2019-12-25
  • 2016-03-26
  • 2020-08-19
相关资源
最近更新 更多