Symbolic symmyetric positive definite Matrix

33 views
Skip to first unread message

koller.t...@gmail.com

unread,
Mar 11, 2019, 2:04:47 PM3/11/19
to sympy
Hi,

I was wondering how I can create symbolic symmetric positive definite (s.p.d.) Matrices.

I would like to get a symbolic (symbolic in the Q-matrix) quadratic form

def sospoly(x, varname):
N = x.shape[0]
Q = MatrixSymbol(varname, N, N)
p = (x.T * Matrix(Q) * x)[0]
return p, Q

where Q is s.p.d.
It would be enough to enforce symmetry actually ( making sure that Q[i,j] == Q[j,i]).
If there is no "SymmetricMatrixSymbol" is there an easy way to create a symbolic lower triangular matrix?

Thank you!

Aaron Meurer

unread,
Mar 11, 2019, 3:17:10 PM3/11/19
to sy...@googlegroups.com
I don't think that exists yet, aside from the assumptions in the new
assumptions Q.symmetric and Q.positive_definite. It would be useful to
be able to bind those assumptions to the matrix object itself.

Also ideally you would be able to put it under a "with
assuming(Q.symmetric(q))" block (where q is your matrix Q, not to be
confused with Q the SymPy object that hold the assumptions
predicates), but that doesn't work yet either. As far as I know, the
matrix assumptions so far only do anything for deduction (ask()).

For now, you can use replace to make the resulting matrix symmetric

>>> from sympy.matrices.expressions.matexpr import MatrixElement
>>> p, Q = sospoly(Matrix([1, 2, 3]), 'Q')
>>> p
Q[0, 0] + 2*Q[0, 1] + 3*Q[0, 2] + 2*Q[1, 0] + 4*Q[1, 1] + 6*Q[1, 2] +
3*Q[2, 0] + 6*Q[2, 1] + 9*Q[2, 2]
>>> p.replace(lambda x: isinstance(x, MatrixElement) and x.args[0] == Q, lambda x: x if x.args[1] <= x.args[2] else x.args[0][x.args[2],x.args[1]])
Q[0, 0] + 4*Q[0, 1] + 6*Q[0, 2] + 4*Q[1, 1] + 12*Q[1, 2] + 9*Q[2, 2]

Or you could use a custom MatrixSymbol subclass

>>> class SymmetricMatrixSymbol(MatrixSymbol):
... def _entry(self, i, j):
... i, j = sympify((i, j))
... if (i - j).could_extract_minus_sign():
... i, j = j, i
... return MatrixElement(self, i, j)
>>> Q = SymmetricMatrixSymbol("Q", 3, 3)
>>> Q[0, 1]
Q[1, 0]
>>> Q[1, 0]
Q[1, 0]
>>> x = Matrix([1, 2, 3])
>>> (x.T*Matrix(Q)*x)[0]
Q[0, 0] + 4*Q[1, 0] + 4*Q[1, 1] + 6*Q[2, 0] + 12*Q[2, 1] + 9*Q[2, 2]

I used could_extract_minus_sign() instead of i < j because it handles
symbolic entries as well.

>>> i, j = symbols('i j')
>>> Q[i, j]
Q[i, j]
>>> Q[j, i]
Q[i, j]

Aaron Meurer
> --
> You received this message because you are subscribed to the Google Groups "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.
> To post to this group, send email to sy...@googlegroups.com.
> Visit this group at https://groups.google.com/group/sympy.
> To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/7e3c8066-b165-4226-b690-7810a6d22472%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Aaron Meurer

unread,
Mar 11, 2019, 3:30:25 PM3/11/19
to sy...@googlegroups.com
Actually it looks like a lot of the logic is already there. For anyone
interested in fixing this, we just need to add a refine handler for
MatrixElement that handles symmetry. One already exists for Transpose

>>> X = MatrixSymbol("X", n, m)
>>> refine(Transpose(X), Q.symmetric(X))
X

I opened https://github.com/sympy/sympy/issues/16234, which should be
easy to fix.

Aaron Meurer

koller.t...@gmail.com

unread,
Mar 12, 2019, 4:55:42 AM3/12/19
to sympy
Hi Aaron,

thanks a lot for the quick reply and help.
This is exactly what I was looking for.
And good to see that there might be a general interest in having this kind of functionality!

Cheers,
Torsten
Reply all
Reply to author
Forward
0 new messages