2016-06-11 66 views
0

我有一個價格向量和數量向量。我想象徵性地將sympy中的兩個向量分開。我甚至找不到矢量設備。所以我完全同意sympy在如何創建矢量符號以及如何操作它們。 ((x/p)** b)受到約束sum(x)= 1的影響。我可以用標量來做到這一點,但不能用矢量來做到這一點:sympy明智的向量分裂

import sympy as sp 
import sympy 
from sympy.abc import,p1, p2, l, x1, x2, b1, b2 
sp.init_printing() 
U = ((x1/p1)**b1)*((x2/p2)**b2) 
L = U - l*(x1 + x2 - 1) 
dL_dy = sp.diff(L, x1) 
dL_dx = sp.diff(L, x2) 
dL_dl = sp.diff(L, l) 
sp.solve([dL_dy, dL_dx, dL_dl], (x1, x2, l)) 

回答

2

這是一種方法。

import sympy as sp 

定義(矢量)變量和參數:

# vector size (integer, user input): 
n = 2 
# vector variables: 
x = sp.var('x0:'+str(n), positive = True) 
y = sp.var('y0:'+str(n), positive = True) 
# vector parameters: 
p = sp.var('p0:'+str(n), positive = True) 
q = sp.var('q0:'+str(n), positive = True) 
# scalar parameters 
b = sp.var('b', real = True) 
c = sp.var('c', real = True) 
# Lagrange multiplier for sum constraint: 
l = sp.var('lambda') 

目標函數:

U = reduce(lambda xi, xj: xi * xj, [(xi/pi)**b * (yi/qi)**c for xi,pi,yi,qi in zip(x,p,y,q)],1) 
U 

(X0/P0)** B *(X1/P1)** b *(y0/q0)** c *(y1/q1)** c

Lagran吉安:

L = U + l * (sum(x+y)-1) 

KKT條件(每個列表元素必須等於零):

KKT = sp.simplify([sp.numer(sp.together(sp.diff(L, xi))) for xi in x]+\ 
     [sp.numer(sp.together(sp.diff(L, xi))) for yi in y] + [sp.diff(L, l)]) 

我只考慮以幫助求解器的衍生物的分子。這意味着基於此方法的某些解決方案可能由於相應的零分母而無效(必須手動檢查它們)。

溶液現在可以得到

sp.solve(KKT,sp.flatten([x,y,l])) 

似乎爲參數bc的一般值,Sympy無法得到溶液。然而,對於這些參數的某些選擇可以獲得解決方案。例如,對於b=2c=2,給出的解決方案是

[{lambda: y0**2*y1**2*(y0 + y1 - 1)**3/(4*p0**2*p1**2*q0**2*q1**2), 
    x0: -y0/2 - y1/2 + 1/2, 
    x1: -y0/2 - y1/2 + 1/2}] 
+0

SymPy包括矩陣;我使用了列矩陣來表示向量。然而,我並不熟悉所討論的優化問題,也不熟悉足夠先進的SymPy用戶使用「矩陣」和/或「MatrixSymbol」對象成功重寫此答案。 – chrstphrchvz