ddg.math.symmetric_matrices module

Symmetric matrix and signature utilities.

Includes diagonalization, projective/affine normalization and signature classes.

class ddg.math.symmetric_matrices.Signature(plus: int, minus: int, zero: int = 0)[source]

Bases: object

Projective signature class.

Two projective signatures are equal if and only if quadrics with those signatures are related by a projective transformation.

We want to identify:

  • Signatures

  • Quadrics up to projective transformation

  • “Normalized matrices” up to nonzero scalar multiplication (-1 in particular), which will be the result of e.g. projective_normalization().

To achieve this, we define a normalized matrix as a diagonal matrix

 I_n |      |
-----|------|---
     | -I_m |
-----|------|---
     |      | 0

or

 -I_n |     |
------|-----|---
      | I_m |
------|-----|---
      |     | 0

where I_n is the (n x n)-identity matrix, 0 means a 0 matrix and n >= m.

Parameters:
plusint
minusint
zeroint (default=0)

These three arguments mean the number of 1, -1, 0 on the diagonal.

Notes

This class implements the equals relation ==, with the meaning explained above.

It is also hashable.

plus: int
minus: int
zero: int = 0
property matrix

Returns the normalized matrix corresponding to the signature.

See the class docstring for how this is defined.

This method respects the global sign the signature is initialized with, even though the equality operator does not.

Returns:
numpy.ndarray of shape (n, n)
property is_degenerate

Whether this is the signature of a degenerate quadric.

Returns:
bool
property rank

Rank of associated matrix.

Returns:
int
property is_positive_definite

Whether the signature is positive definite.

Meaning, if q is a quadratic form with this signature, q(p,p) > 0 for all p != 0.

Returns:
bool
property is_negative_definite

Whether the signature is negative definite.

Meaning, if q is a quadratic form with this signature, q(p,p) < 0 for all p != 0.

Returns:
bool
property is_positive_semi_definite

Whether the signature is positive semi-definite.

Meaning, if q is a quadratic form with this signature, q(p,p) >= 0 for all p.

Returns:
bool
property is_negative_semi_definite

Whether the signature is negative semi-definite.

Meaning, if q is a quadratic form with this signature, q(p,p) <= 0 for all p.

Returns:
bool
property is_indefinite

Whether the signature is indefinite.

Meaning, that a quadratic form with this signature, can have both positive and negative values.

Returns:
bool
property is_definite

Whether the signature is either positive or negative definite.

Returns:
bool
property is_semi_definite

Whether the signature is either positive or negative semi-definite.

Returns:
bool
class ddg.math.symmetric_matrices.AffineSignature(plus: int, minus: int, zero: int = 0, last_entry: Literal[0, 1, -1, 'parabolic']] = None)[source]

Bases: Signature

Affine signature class.

Two affine signatures are equal if and only if quadrics with those signatures are related by an affine transformation.

We want to identify:

  • Affine signatures

  • Quadrics up to affine transformation

  • “Normalized matrices” up to nonzero scalar multiplication (-1 in particular), which will be the result of e.g. affine_normalization().

To achieve this, we define what a normalized matrix is as follows:

In the non-parabolic case: A diagonal matrix with only 1, -1 and 0 on the diagonal. The diagonal looks as follows (where s is either 1, -1 or 0):

  • If the last entry on the diagonal is 0: (s,...,s, -s,...,-s, 0,...,0), and the number of s’s is greater than or equal to the number of -s’s.

  • If the last entry on the diagonal is s != 0: (s,...,s, -s,...,-s, 0,...,0, s).

In the parabolic case: a matrix of the form

D |
--+-----
  | 0 s
  | s 0

where D is a diagonal matrix with only 1, -1 and 0 on the diagonal. The diagonal is sorted in the order s, -s, 0 and the number of s’s is greater than or equal to the number of -s’s.

Note that for parabolic cases, flipping the sign of the diagonal is the same as flipping the sign of the off-diagonal entries, which as an affine transformation is a reflection about the plane x[-2] = 0.

Parameters:
plusint
minusint
zeroint (default=0)

These three arguments mean the number of 1, -1 or 0 on the diagonal of the diagonalized matrix. Note that for parabolic cases, these will not be the counts on the diagonal: A 1 and a -1 will be replaced by a 0 and entries on the off-diagonal, see above.

last_entry1, -1, 0 or “parabolic” (default=None)

The last entry on the diagonal. A value of “parabolic” means the matrix

0 1
1 0

See above for details. This can be omitted (left as None) if only one of plus, minus or zero is nonzero.

Raises:
ValueError

Notes

This class implements the equals relation ==, with the meaning explained above.

It is also hashable.

plus: int
minus: int
zero: int = 0
last_entry: Literal[0, 1, -1, 'parabolic']] = None
property matrix

Return normalized matrix corresponding to the signature.

See the class docstring for how this is defined.

Returns:
numpy.ndarray of shape (n, n)

Notes

This method respects the sign the signature is initialized with, even though the equality operator does not.

property is_definite

Whether the signature is either positive or negative definite.

Returns:
bool
property is_degenerate

Whether this is the signature of a degenerate quadric.

Returns:
bool
property is_indefinite

Whether the signature is indefinite.

Meaning, that a quadratic form with this signature, can have both positive and negative values.

Returns:
bool
property is_negative_definite

Whether the signature is negative definite.

Meaning, if q is a quadratic form with this signature, q(p,p) < 0 for all p != 0.

Returns:
bool
property is_negative_semi_definite

Whether the signature is negative semi-definite.

Meaning, if q is a quadratic form with this signature, q(p,p) <= 0 for all p.

Returns:
bool
property is_positive_definite

Whether the signature is positive definite.

Meaning, if q is a quadratic form with this signature, q(p,p) > 0 for all p != 0.

Returns:
bool
property is_positive_semi_definite

Whether the signature is positive semi-definite.

Meaning, if q is a quadratic form with this signature, q(p,p) >= 0 for all p.

Returns:
bool
property is_semi_definite

Whether the signature is either positive or negative semi-definite.

Returns:
bool
property rank

Rank of associated matrix.

Returns:
int
ddg.math.symmetric_matrices.signature_from_diagonal(diag)[source]

Create signature from diagonal.

Parameters:
diagnumpy.ndarray of shape (n,) or list

1D array containing only 1, -1 and 0

Returns:
Signature
Raises:
ValueError

If diag contains entries other than 1, -1 or 0.

ddg.math.symmetric_matrices.affine_signature_from_diagonal(diag, parabolic=False)[source]

Create affine signature from diagonal.

Parameters:
diagnumpy.ndarray of shape (n,) or list

1D array containing only 1, -1 and 0. If parabolic is True, this must have 0 at entries -1 and -2.

parabolicbool (default=False)
Returns:
AffineSignature
Raises:
ValueError
  • If diag contains entries other than 1, -1 or 0.

  • If parabolic is True and diag does not have 0 at positions -1 and -2.

ddg.math.symmetric_matrices.projective_normalization(Q, atol=None, rtol=None)[source]

Bring quadric to normal form by projective transformation.

Returns signature sgn and transformation matrix A such that

A.T @ Q @ A == sgn.matrix

See Signature for more information.

Note that this means that the point transformation defined by A transforms sgn.matrix into Q.

Parameters:
Qnumpy.ndarray

Symmetric matrix.

atol, rtolfloat (default=None)

This function uses the global tolerance defaults if atol or rtol are set to None. See ddg.nonexact for details.

Returns:
sgnSignature
Anumpy.ndarray

Transformation matrix.

ddg.math.symmetric_matrices.affine_normalization(Q, atol=None, rtol=None)[source]

Bring quadric to normal form by affine transformation.

Returns affine signature sgn and affine transformation A such that

A.T @ Q @ A == sgn.matrix

For non-parabolic cases, this means diagonalizing Q with an affine transformation such that there is only 1, -1 or 0 on the diagonal. For parabolic cases, normalizes to a matrix of the form

      D1 |
(+/-) ---+-----
         | 0 1
         | 1 0

Where D1 is a diagonal matrix with only 1, -1 or 0 on the diagonal. For more information about the order of entries on the diagonal etc, see AffineSignature.

Parameters:
Qnumpy.ndarray of shape (n + 1, n + 1)

Symmetric matrix. Can be interpreted as a quadric in n-dim. projective space.

atol, rtolfloat (default=None)

This function uses the global tolerance defaults if atol or rtol are set to None. See ddg.nonexact for details.

Returns:
sgnAffineSignature
Anumpy.ndarray of shape (n + 1, n + 1)

Affine transformation.

Raises:
ValueError

If Q is not symmetric.

Notes

For a detailed explanation of the implementation, see supplemental material.

ddg.math.symmetric_matrices.signature_sort_key(x)[source]

Sorting key function for signatures.

Desired order of values: positive, negative, zero with each category sorted by absolute value (decreasing)

Parameters:
xfloat
Returns:
tuple(int, float)
ddg.math.symmetric_matrices.diagonalize(A, sort_key=<function signature_sort_key>, atol=0, rtol=0)[source]

Diagonalize a symmetric matrix.

Diagonalization of symmetric matrix but with customizable order of eigenvalues. Uses np.linalg.eigh, then eigenvalues and eigenvectors. Makes eigenvalues close to zero exact.

Parameters:
Anumpy.ndarray of shape (n, n)

Symmetric matrix

sort_keyCallable (default=signature_sort_key)

Sorting key function. Eigenvalues are sorted according to the result of this function for each eigenvalue.

atol, rtolfloat (default=0)

Eigenvalues close to 0 according to these tolerances are set to 0.

This function uses the global tolerance defaults if atol or rtol are set to None. See ddg.nonexact for details.

Returns:
evlist

List of n Eigenvalues, sorted according to sort_key.

Snumpy.ndarray of shape (n, n)

Columns of S are the n Eigenvectors in the order of ev.

ddg.math.symmetric_matrices.symmetrize(A)[source]

Symmetrize square matrix.

Parameters:
Anumpy.ndarary of shape (n, n)
Returns:
numpy.ndarray of shape (n, n)

(A.T + A) / 2

ddg.math.symmetric_matrices.is_symmetric(A, atol=1e-13, rtol=None)[source]

Checks whether a square matrix is symmetric.

Parameters:
Anumpy.ndarray of shape (n, n)
atolfloat (default=1e-13)
rtolfloat (default=None)

This function uses the global tolerance defaults if atol or rtol are set to None. See ddg.nonexact for details.

Returns:
bool
ddg.math.symmetric_matrices.symmetric_matrix_from_diagonal(sgn, parabolic=False)[source]

A normalized affine quadric can be reconstructed from its diagonal and the additional knowledge whether it is parabolic.

For what “parabolic” means, see the docstring of AffineSignature.

Parameters:
sgnnumpy.ndarray of shape (n,)

Diagonal of the matrix.

parabolicbool (default=False)

If this is True, sgn must have 0 at positions -1 and -2.

Raises:
ValueError

If parabolic is True and sgn does not have 0 at positions -1 and -2.

See also

AffineSignature