可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have a vector X
which I created like this:
from sympy import *
x1 = Symbol('x1')
x2 = Symbol('x2')
x3 = Symbol('x3')
X = Matrix([x1, x2, x3])
Then I also have a matrix myMat
which just contains ones:
myMat = ones(3, 3)
Matrix([
[1, 1, 1],
[1, 1, 1],
[1, 1, 1]])
Now I would like to replace the diagonal of the matrix by my vector X
; my desired outcome looks like this:
Matrix([
[x1, 1, 1],
[1, x2, 1],
[1, 1, x3]])
I can of course do it in a for-loop
like this:
for ind, el in enumerate(X):
myMat[ind, ind] = el
but I am wondering whether there is a smarter way of doing that by directly accessing the diagonal of this matrix. While I can calculate the trace
of the matrix, I could not find a way to replace just the diagonal elements using something like myMat.diag = X
. Is there a way of doing that?
EDIT
@Emilien got me on the right track and therefore I accepted this answer. Building up on this answer, I also posted my own solution which makes use of sympy
and numpy
and solves the problem in one single line: my answer
回答1:
You can build it with diagonal and identity matrices, I'm not sure it's much better on a performance point of vue thought, but maybe it's easier to understand when reading the code if that's what you're looking for.
x1, x2, x3 = symbols('x1 x2 x3')
mat = diag(x1,x2,x3)-eye(3)+ones(3)
or
l = symbols('x1 x2 x3')
mat = diag(*l)-eye(3)+ones(3)
As you wish.
Another tricky solution, maybe less readable:
l = symbols('x1 x2 x3')
Matrix(3, 3, lambda i,j: l[i] if i==j else 1)
Finally, if you do not wish to modify the original
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])
回答2:
I would suggest to convert the sympy.matrices.dense.MutableDenseMatrix
to a numpy.ndarray
and reconvert after all is done. Something like:
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]])
回答3:
Building up on @Emilien answer, one could do the following:
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)
So myM
looks like this:
Matrix([
[4, 4, 4],
[4, 4, 4],
[4, 4, 4]])
Now the command
sp.diag(*X) + myM - sp.diag(*np.diag(myM))
gives the desired outcome:
Matrix([
[x1, 4, 4],
[ 4, x2, 4],
[ 4, 4, x3]])
That makes use of the different functionalities of diag
in sympy
and numpy
, respectively; while in sympy
diag
creates a matrix using a vector as an input using the elements of this vector as the diagonal of the matrix
sp.diag(*X)
Matrix([
[x1, 0, 0],
[ 0, x2, 0],
[ 0, 0, x3]])
in numpy
diag
returns the diagonal of a matrix:
np.diag(myM)
array([4, 4, 4], dtype=object)
回答4:
If you us some library function for finding the diagonal, I am 100% sure that the Library Function will use "For" loops. Just run a nested for loop with i varying from 1 to Row.Count and j varying from 1 to Columns.count. Diagonal is where i=j. Do what Ever you want there.Example below, you get the idea
for (i=1; i<= Rows.Count; i++)
for (j=1; j<= Columns.Count; j++)
if (i==j)
{
// Do your Thing
}
end
end