sympy 元素明智的向量划分 [英] sympy element wise division of vector

查看:38
本文介绍了sympy 元素明智的向量划分的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个价格向量和一个数量向量.我想在 sympy 中象征性地划分这两个向量.我什至找不到矢量设施.所以我完全失去了对如何创建矢量符号以及如何操作它们的同情.

最终我想使用拉格朗日方法最大化的是 prod((x/p) **b) 受约束的 sum(x) = 1.我可以用标量做到这一点,但不能用矢量:

import sympy as sp进口同情从 sympy.abc 导入,p1,p2,l,x1,x2,b1,b2sp.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))

解决方案

这是一种方法.

import sympy as sp

定义(向量)变量和参数:

# 向量大小(整数,用户输入):n = 2# 向量变量:x = sp.var('x0:'+str(n), positive = True)y = sp.var('y0:'+str(n), positive = True)# 向量参数:p = sp.var('p0:'+str(n), positive = True)q = sp.var('q0:'+str(n), positive = True)# 标量参数b = sp.var('b', real = True)c = sp.var('c', real = True)# 和约束的拉格朗日乘数: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)你

<块引用>

(x0/p0)**b*(x1/p1)**b*(y0/q0)**c*(y1/q1)**c

拉格朗日:

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}]

I have a price vector and a quantity vector. I would like to symbolically divide the two vectors in sympy. I can't even find a vector facility. So I am totally lost with sympy on how to create vector symbols and how to manipulate them.

Eventually what I would like use the lagrangian method to maximize is prod((x/p) **b) subjected to the constrained sum(x) = 1. I can do this with scalars, but not with vectors:

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))

解决方案

Here is one way to do this.

import sympy as sp

Define (vector) variables and parameters:

# 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')

Objective function:

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

Lagrangian:

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

KKT conditions (each list element must be equal to zero):

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)])

I have considered only the numerator of the derivatives in order to help the solver. This means that some solutions based on this approach may be invalid due to a corresponding zero denominator (they have to be manually checked).

The solution can be obtained now as

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

It appears that for general values of the parameters b and c, Sympy is unable to give a solution. However, solutions can be obtained for certain choices of these parameters. For example, for b=2 and c=2, the solution given is

[{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}]

这篇关于sympy 元素明智的向量划分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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