2015-10-13 4 views
3

У меня есть вектор X который я создал так:Как заменить диагональные элементы матрицы вектором в SymPy?

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. Есть ли способ сделать это?

EDIT

@Emilien меня на правильном пути, и поэтому я принял этот ответ. На основе этого ответа, я отправил свое собственное решение, которое делает использование sympy и numpy и решает проблему в одной строке: my answer

ответ

3

Вы можете построить его с диагональными и идентификационных матриц, я не уверен, что это гораздо лучше, на точки зрения производительности вю мысли, но, возможно, это легче понять при чтении кода, если это то, что вы «Ищем.

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

Это выглядит хорошо, спасибо (я тоже его возвышаю). Есть ли какой-либо путь, что один вектор X непосредственно переходит в функцию diag? Я имею дело с гораздо большими векторами, и поэтому было бы больно печатать его так. Тогда вопрос также должен был бы заменить диагональные элементы, если в матрице есть другие значения, чем единицы. Есть идеи? – Cleb

+0

Если у вас нет только «1» по диагонали, вы можете выполнять умножение по счету с обратной матрицей «глаз» («0» по диагонали и «1» где бы то ни было). – Mathiou

+0

Да, это называется распаковкой кортежа. Кроме того, я нашел решение, если вы хотите сохранить исходные значения (не особенно). Я не мог понять, как «передать» случай, когда «i! = J» в лямбда-функции, что опять-таки не может быть суперэффективным по сравнению с циклом for. – Emilien

-2

, если вы нам какие-либо библиотеки функции для нахождения диагонали, я 100% уверены, что функция Library будет использовать петли «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 
+0

Спасибо за ваше предложение, но это не похоже на python и на самом деле не отвечает на вопрос, так как у меня уже есть версия, в которой я использую for-loop. BTW: Я не спустил вниз ... – Cleb

+0

Не имеет значения, даже если вы проиграли, я просто говорил, что если вы используете какую-либо встроенную функцию. Он будет использовать цикл «для». Так что лучший способ для цикла. Это мое мнение. Возможно, неправильно. Надеюсь, вы получите более полезный ответ. –

3

Я хотел бы предложить, чтобы преобразовать 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]]) 
0

Построение на @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]]) 

Это делает использование различных функциональных diag в sympy и numpy, соответственно; в то время как в sympydiag создает матрицу с использованием вектора в качестве входных данных, используя элементы этого вектора как диагональ матрицы

sp.diag(*X) 

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

в numpydiag возвращает диагональ матрицы:

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

Ах да молодец. Я думаю, что это должен быть принятый ответ на самом деле;) – Emilien

+0

@Emilien: Ну, я не люблю принимать мои собственные ответы, если есть хороший; ваши усилия должны окупиться :). Но я поместил Edit в свой вопрос, и тогда люди могут решить, в какую сторону они хотят пойти (например, если у них нет numpy, ваш способ создания этой матрицы будет лучше). – Cleb