如何用 SymPy 中的向量替换矩阵的对角线元素?

How to replace the the diagonal elements of a matrix by a vector in SymPy?

我有一个矢量 X,我是这样创建的:

from sympy import *

x1 = Symbol('x1')
x2 = Symbol('x2')
x3 = Symbol('x3')

X = Matrix([x1, x2, x3])

然后我还有一个矩阵 myMat 其中只包含一个:

myMat = ones(3, 3)

Matrix([
[1, 1, 1],
[1, 1, 1],
[1, 1, 1]])

现在我想用我的向量替换矩阵的对角线 X;我想要的结果是这样的:

Matrix([
[x1, 1, 1],
[1, x2, 1],
[1, 1, x3]])

我当然可以像这样 for-loop:

for ind, el in enumerate(X):
    myMat[ind, ind] = el

但我想知道是否有一种更聪明的方法可以通过直接访问该矩阵的对角线来实现。虽然我可以计算矩阵的 trace,但我找不到使用 myMat.diag = X 之类的方法仅替换对角线元素的方法。有办法吗?

编辑

@Emilien 让我走上了正确的轨道,因此我接受了这个答案。在这个答案的基础上,我还发布了我自己的解决方案,它利用 sympynumpy 并在一行中解决了问题:

如果您使用一些库函数来查找对角线,我 100% 确定该库函数将使用 "For" 循环。只是 运行 一个嵌套的 for 循环,其中 i 从 1 到 Row.Count 变化,j 从 1 到 Columns.count 变化。对角线是 i=j。随心所欲 there.Example 下面,你明白了

for (i=1; i<= Rows.Count; i++)
     for (j=1; j<= Columns.Count; j++)
          if (i==j)
          {
            // Do your Thing
          }
     end
 end

我建议将 sympy.matrices.dense.MutableDenseMatrix 转换为 numpy.ndarray 并在完成后重新转换。类似于:

import numpy as np 
from sympy import *

x1 = Symbol('x1')
x2 = Symbol('x2')
x3 = Symbol('x3')

X = Matrix([x1,x2,x3])
myMat = ones(3,3)


myMat1 = np.array(myMat)
myMat1[range(3),range(3)] = np.array(X).reshape(myMat1.shape[0])

myMat = Matrix(myMat1)

>> Matrix([
[x1,  1,  1],
[ 1, x2,  1],
[ 1,  1, x3]])

您可以使用对角矩阵和单位矩阵来构建它,我不确定它在 vue 思想的性能方面是否更好,但如果您正在寻找它,那么在阅读代码时可能更容易理解。

x1, x2, x3 = symbols('x1 x2 x3')
mat = diag(x1,x2,x3)-eye(3)+ones(3)

l = symbols('x1 x2 x3')
mat = diag(*l)-eye(3)+ones(3)

如你所愿。

另一个棘手的解决方案,可能不太可读:

l = symbols('x1 x2 x3')
Matrix(3, 3, lambda i,j: l[i] if i==j else 1)

最后,如果你不想修改原来的

l = symbols('x1 x2 x3')
M = Matrix(([1,2,3],[4,5,6],[7,8,9]))
M = Matrix(3, 3, lambda i,j: l[i] if i==j else M[i,j])

根据@Emilien 的回答,可以执行以下操作:

import sympy as sp
import numpy as np

x1 = sp.Symbol('x1')
x2 = sp.Symbol('x2')
x3 = sp.Symbol('x3')
X = sp.Matrix([x1, x2, x3])

myM = 4 * sp.ones(3, 3)

所以 myM 看起来像这样:

Matrix([
[4, 4, 4],
[4, 4, 4],
[4, 4, 4]])

现在命令

sp.diag(*X) + myM - sp.diag(*np.diag(myM))

给出了想要的结果:

Matrix([
[x1,  4,  4],
[ 4, x2,  4],
[ 4,  4, x3]])

这分别利用了diagsympynumpy中的不同功能; while in sympy diag 使用向量作为输入创建一个矩阵,使用该向量的元素作为矩阵的对角线

sp.diag(*X)

Matrix([
[x1,  0,  0],
[ 0, x2,  0],
[ 0,  0, x3]])

in numpy diag returns 矩阵的对角线:

np.diag(myM)
array([4, 4, 4], dtype=object)