How to substitute values in matrix operation without solving?

Question:

Literally what it says in the title. Let’s pretend the operation is addition of matrices.

from sympy import Matrix, latex
A = Matrix([[-7, 0], [4, 0]]) 
B = Matrix([[2, 0], [-3, -3]])

print( (A+B).a_method_that_evaluates_but_does_not_solve() )

I would like to get the following output.

[[-7 + 2, 0 + 0], [4 - 3, 0 - 3]]

I will use this with various matrix operations, including addition, multiplication and scalar multiplication. And my goal is to be able to print the working as one or more of this operations is performed. Ultimately, having the control to decide when to substitute only, and when to solve.

So far, the closest I have gotten is to print the symbolic working. Here is the 2×2 matrix example. But this is not good, I really want the actual numbers printed. And using the subs method, substitutes AND solves the operations. Which is the same as print(A+B).

symA = MatrixSymbol('A', 2, 2)
symB = MatrixSymbol('B', 2, 2)
print(Matrix(symA+symB))
print((symA+symB).subs(symA,A).subs(symB,B))

With output:

Matrix([[A[0, 0] + B[0, 0], A[0, 1] + B[0, 1]], [A[1, 0] + B[1, 0], A[1, 1] + B[1, 1]]])
Matrix([[-5, 0], [1, -3]])

Any help is appreciated. Thanks.

Asked By: MetalMathician

||

Answers:

You can work with sympy and replace every constant by a different variable. After performing the symbolic computation, replace the variables by the initial constants.

Only substitute the absolute value of the constants, not their signs, to avoid having to wrap them in parenthesis.


Hint:

import sympy

V0, V1, V2, V3, V4, V5, V6, V7= sympy.symbols('V0 V1 V2 V3 V4 V5 V6 V7')
Map= { "V0": "7", "V1": "0", "V2": "4", "V3": "0", "V4": "2", "V5": "0", "V6": "3", "V7": "3" }

A = sympy.Matrix([[-V0, V1], [V2, V3]]) 
B = sympy.Matrix([[V4, V5], [-V6, -V7]])
C= A * B - B * A

Text= str(C)
for Token in Map:
    Text= Text.replace(Token, Map[Token])
print(Text)


Matrix([[-0*3 - 4*0, -7*0 - 0*2 - 0*3 - 0*0], [-7*3 + 4*2 + 4*3 - 0*3, 0*3 + 4*0]])
Answered By: Yves Daoust

You can do this by using an evaluate(False) context if you do the operations manually within the context (and I don’t know why it doesn’t work for simply adding the matrices):

A = Matrix([[-7, 0], [4, 0]]) 
B = Matrix([[2, 0], [-3, -3]])
with evaluate(False):
    C = Matrix(2,2, [i+j for i,j in zip(A,B)])
    D = Matrix([[sum([A[i,k]*B[k,j] for k in range(2)]) for j in range(2)] for i in range(2)])

>>> C
Matrix([
[-7 + 2, 0 + 0], 
[-3 + 4, -3 + 0]])
>>> C.doit()
Matrix([
[-5, 0], 
[1, -3]])
>>> D
Matrix([
[-(7*2 + 0) + 0*(-3), (0 - 7*0) + 0*(-3)], 
[0*(-3) + (0 + 4*2), (0 + 4*0) + 0*(-3)]])
>>> D.doit() == A*B
True

You can always write helpers if you think that would be more convenient:

def add(A, B):
    assert A.shape == B.shape
    with evaluate(False):
        return Matrix(*A.shape, [i+j for i,j in zip(A,B)])

def mul(A, B):
    assert A.cols == B.rows
    with evaluate(False):
        return Matrix([[sum([A[i,k]*B[k,j] for k in range(A.cols)]) for j in range(B.cols)] for i in range(A.rows)])

>>> add(A,B).doit() == A+B and mul(A,B).doit() == A*B
True
Answered By: smichr
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.