符号矩阵和numpy使用错误“TypeError:ufunc'isfinite'不支持输入类型..”

时间:2018-01-01 23:46:22

标签: python numpy optimization scipy sympy

我试图使用最小化函数执行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)

1 个答案:

答案 0 :(得分:3)

我列出了一些错误的地方。

  • 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等)。只有第三个变量以非活动的constaint结束。