Symbolic matrices

i like this post (click again to cancel)
i dont like this post (click again to cancel)


is it possible to define totally symbolic matrices. Something like

N,M = var('N,M')
a = matrix(SR, N, M)
b = matrix(SR, M, N)
c =

So that c[i,j] = sum(a[i,k]*b[k,i],k,1,M) or do you really always need an non-symblic matrix size?

If you really always need a non-symblic matrix type, is it possible to define the symbolic variables automatically? Something like

a = matrix(SR, 2, 3)
print a[i,j]



asked Apr 12 '11

Manuels gravatar image Manuels
43 1 2 5

updated Apr 13 '11

niles gravatar image niles
3725 7 45 104

2 Answers:

i like this answer (click again to cancel)
i dont like this answer (click again to cancel) Manuels has selected this answer as correct

There is the Tensor module in sympy. If that is the type of thing that you're looking for (ie explicit indices).

The was some code put on the sage devel group last year: abstract matrices, which allows basic manipulation of abstract matrices and vectors. It's not complete, but it does the basics and should be easy to extend if you need more. As far as I can tell, it hasn't been worked on since the original postings. I hope it's ok if I post the code here:

from sage.structure.element import Element 
from sage.combinat.free_module import CombinatorialFreeModule 

# TODO: doc and tests for all of those 
class SymbolicMatrix(SageObject): 
    def __init__(self, name, nrows, ncols, inverted = False, transposed = False): 
        #Element.__init__(self, parent) 
        self._name = name 
        self._nrows = nrows 
        self._ncols = ncols 
        self._inverted = inverted 
        self._transposed = transposed 

    def _repr_(self): 
        result = self._name 
        if self._inverted: 
            result += "^-1" 
        if self._transposed: 
            result += "^t" 
        return result 

    def transpose(self): 
        result = copy(self) 
        result._transposed = not self._transposed 
        (result._nrows, result._ncols) = (self._ncols, self._nrows) 
        return result 

    def __invert__(self): 
        assert self._nrows == self._ncols, "Can't inverse non square matrix" 
        result = copy(self) 
        result._inverted = not self._inverted 
        return result 

class SymbolicMatrixAlgebra(CombinatorialFreeModule): 


        sage: Alg = SymbolicMatrixAlgebra(QQ) 

        sage: A = Alg.matrix("A",3,2) 
        sage: B = Alg.matrix("B",2,3) 
        sage: C = Alg.matrix("C",2,3) 
        sage: D = Alg.matrix("D",3,3) 

    Example 1: Adding/Multiplying matrices of correct size:: 

        sage: A * (B + C) 
        A B + A C 

    Example 2: Transposing a sum of matrices:: 

        sage: (B + C).transpose() 
        C^t + B^t 

    Example 3: Transposing a product of matrices:: 

        sage: (A * B).transpose() 
        B^t A^t 

    Example 4: Inverting a product of matrices:: 

        sage: (A * B)^-1 
        B^-1 A^-1 

    Example 5: Multiplying by its inverse:: 

        sage: D * D^-1 # todo: not implemented 

    TODO: decide on the best output; do we want to be able to 
    copy-paste back? do we prefer short notations? 

    .. warnings:: 

    The identity does not know it is size, so the following should 
    complain, but does not:: 

        sage: D * D^-1 * A 

    TODO: describe all the abuses 

    def __init__(self, R): 

            sage: A = AlgebrasWithBasis(QQ).example(); A 
                An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field 
            sage: TestSuite(A).run() 

        CombinatorialFreeModule.__init__(self, R, Words(), category = AlgebrasWithBasis(R)) 

    def matrix(self, name, nrows, ncols): 
        """ TODO: doctest""" 
        return self.monomial(Word([SymbolicMatrix(name, nrows, ncols)])) 

    def _repr_(self): 

            sage: SymbolicMatrixAlgebra(QQ) 
            The symbolic matrix algebra over Rational Field 
        return "The symbolic matrix algebra over %s"%(self.base_ring()) 

    def one_basis(self): 
        Returns the empty word, which index the one of this algebra, 
        as per :meth:`AlgebrasWithBasis.ParentMethods.one_basis`. 


            sage: Alg = SymbolicMatrixAlgebra(QQ) 
            sage: Alg.one_basis() 
        return self.basis().keys()([]) 

    def product_on_basis(self, w1, w2): 
        Product of basis elements, as per :meth:`AlgebrasWithBasis.ParentMethods.product_on_basis`. 


            sage: Alg = SymbolicMatrixAlgebra(QQ) 
            sage: P = Alg.matrix("P", 3, 2) 
            sage: Q = Alg.matrix("Q", 3, 2) 
            sage: R = Alg.matrix("R", 2, 2) 
            sage: S = Alg.matrix("S", 2, 3) 
            sage: P * P 
            Traceback (most recent call last): 
            AssertionError: Non-conformable matrices: matrix sizes are incompatible for multiplication 
            sage: P * R * S 
            sage: (P+Q) * R 
            P*R + Q*R 

            sage: (P+Q) * R * S 
            P*R*S + Q*R*S 
            sage: S * (P+Q) * R 
        if len(w1) == 0: 
            return self.monomial(w2) 
        if len(w2) == 0: 
            return self.monomial(w1) 
        assert w1[-1]._ncols == w2[0]._nrows, "Non-conformable matrices: matrix sizes are incompatible for multiplication" 
        # TODO: handle cancelations between w1[-1] and w2[0] 
        return self.monomial(w1 + w2) 

    # TODO: define an_element 

    def _repr_term(self, t): 

            sage: # indirect doctest 
            sage: Alg.an_element() # todo: not implemented 
        if len(t) == 0: 
            return 'I' 
            return ' '.join(repr(m) for m in t) 

    class Element(CombinatorialFreeModule.Element): 

        def transpose(self): 


                sage: Alg = SymbolicMatrixAlgebra(QQ) 
                sage: A = Alg.matrix("A", 3, 2) 
                sage: B = Alg.matrix("B", 3, 2) 
                sage: C = Alg.matrix("C", 2, 2) 
                sage: D = Alg.matrix("D", 2, 3) 
                sage: x = D * (A+B) * C 
                sage: x 
                D B C + D A C 
                sage: x.transpose() 
                C^t B^t D^t + C^t A^t D^t 

            return self.map_support(lambda w: Word(m.transpose() for m in reversed(w))) 

        def __invert__(self): 

                sage: Alg = SymbolicMatrixAlgebra(QQ) 
                sage: A = Alg.matrix("A", 2, 2) 
                sage: B = Alg.matrix("B", 2, 2) 
                sage: C = Alg.matrix("C", 2, 2) 
                sage: D = Alg.matrix("D", 3, 2) 
                sage: E = Alg.matrix("E", 2, 3) 
                sage: ~(A*B*C) 
                C^-1 B^-1 A^-1 
                sage: ~(A*B^-1*C^-1) 
                C B A^-1 
                sage: ~(D*C*E) 
                Traceback (most recent call last): 
                AssertionError: Can't inverse non square matrix 
                sage: ~(A+B) 
                Traceback (most recent call last): 
                AssertionError: Can't inverse non trivial linear combinations of matrices 
            assert len(self) == 1, "Can't inverse non trivial linear combinations of matrices" 
            (w, c) = self.leading_item() 
            return self.parent().term(Word(~m for m in reversed(w)), c)

posted Apr 12 '11

Simon gravatar image Simon flag of Australia
285 2 7 18

updated Feb 09

slelievre gravatar image slelievre
702 10 23
That's an interesting thread, which I had forgotten. Did it ever turn into a ticket? kcrisman (Apr 12 '11)
@kcrisman - I had a quick look, but couldn't find anything. Simon (Apr 13 '11)
Then open one and post the code :) kcrisman (Apr 14 '11)
@kcrisman: Remind me again in a couple of months after I've written my thesis - then I'll have a go at completing and posting the code... Simon (Apr 15 '11)
i like this answer (click again to cancel)
i dont like this answer (click again to cancel)

I'm not sure if there's a way to define a symbolic matrix the way you describe above. However, one could create a matrix populated only by distinct symbolic variables. Here's a quick, though supposedly not quickest, way to do so:

sage: N = 3
sage: s = join(['a_%d%d' %(i,j) for (i,j) in CartesianProduct(range(N),range(N))])
sage: a = var(s)
sage: A = matrix(SR,N,N,a)
sage: print A[1,2]

The second line just creates a string with the variable names $a_{ij}$ for $i,j \in \mathbb{Z}_n$ and the third parses the string and creates a list of the symbolic variables. I can now create another matrix $B$ and multiply them:

sage: s = join(['b_%d%d' %(i,j) for (i,j) in CartesianProduct(range(N),range(N))])
sage: b = var(s)
sage: B = matrix(SR,N,N,b)
sage: C = A*B
sage: print C[1,2]
a_10*b_02 + a_11*b_12 + a_12*b_22

It's not completely automatic, and perhaps not pretty, but I hope it helps.


posted Apr 12 '11

cswiercz gravatar image cswiercz
839 6 17 33

updated Apr 12 '11

This isn't a very "beautiful" method, but I can't think of anything better. :-) Anybody know of a cleaner approach? By the way, I would put an underscore between the indices, so the variables would read: "a_1_0", "b_3_5", and "c_23_829" (just an example). And would this method work for sparse matrices? Kelvin Li (Apr 12 '11)
I agree that it's not pretty, but even if Sage had the ability to define these "purely symbolic" matrices one would have to call the elements _something_. Perhaps this sort fo thing would happen in the __init__() method. Also, I use the notation "a_ij" instead of "a_i_j" because when you execute "show(a_ij)", or enable typesetting in the Sage Notebook, it looks prettier. :) cswiercz (Apr 12 '11)
Ignoring all else, I would like to reference and name the elements consistently: a[1,2] being printed exactly as "a[1,2]". Then again, I can't ignore the facts. :-) Kelvin Li (Apr 12 '11)
@cswiercz: This is basically how you have to do things in Mathematica - you then check results for a range of `N` and hope that that's enough. I was sure that sympy used to have an abstract matrix module... but I couldn't find it when I looked just now. Simon (Apr 12 '11)
You say it's not the quickest way to do this (*this* being define lots of symbolic variables and populate a matrix with them), so what is the quickest way? benjaminfjones (Apr 19 '11)
see 4 more comments

Your answer

Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!
Login/Signup to Post

Question tools

1 follower



Asked: Apr 12 '11

Seen: 1,145 times

Last updated: Feb 09

powered by ASKBOT version 0.7.22
Copyright Sage, 2010. Some rights reserved under creative commons license.