Classes for handling vectors and matrices with associated units

NOTES:

One should view a QuantMatrix as a regular matrix where each element has a dimension calculated from the outer product of two vectors. E.g.

   kg  mol 
m 1.0  2.0 
s 3.0  4.0

represents the matrix

1.0 m kg  2.0 m mol
3.0 s kg  4.0 s mol

Defines the classes

and the following functions:

  • qidentity(), qrandom(), qzeros() - create a dimensionless QuantMatrix of the given shape similar to the sage.matrix.constructor functions identity_matrix, random_matrix and zero_matrix
  • qhomogeneous() - creates a list of Quantities with the given dimensions and flydims. Input can be any dimensional object (any numerical value associated with the object will be ignored)
  • qmatrix() - converts a Sage matrix, QuantVector, list of lists of quantities or PrintMatrix to a QuantMatrix
  • qvector() - converts one-dimensional matrices, lists of quantities, or Sage vectors to QuantVectors

AUTHORS:

  • David Bate (2008): initial version
  • Miriam Backens (2009): QuantMatrix now uses Sage matrices, added QuantVector and PrintMatrix, support for Flydims, more functionality

EXAMPLE:

sage: QuantMatrix([[1.2, 3], [5, 6.7]], [[meter, second], [second/meter, Dimension()]])
  m^-1 s   1  
m   1.2   3.0 
s   5.0   6.7
sage: _.eigenvalues()
[-0.8 s, 8.7 s]
class sage.dimpy.quant_matrix.PrintMatrix(quant_object)

A class that simplifies nice formatting of vectors and matrices for printing and allows item assignment.

INPUT:
  • quant_object - a QuantVector, QuantMatrix, list of lists or a tuple of two integers (the shape of the empty PrintMatrix to be created)

NOTES:

In a PrintMatrix quantities are stored directly and not split up into values and dimensions; that way they can be rounded and assigned preferred units. PrintMatrices have no methods for calculations.

Can also be used to create a matrix, assign quantities to different positions and then convert it to a QuantMatrix. Either create a QuantMatrix, convert it to a PrintMatrix and then modify it, make a list of lists of quantities and use that as input, or call PrintMatrix on a tuple specifying the shape of the PrintMatrix. In the latter two cases, there are two types of zero elements: 0 * unit is a zero with specified dimensions whereas None is a zero whose dimensions may change during conversion.

When creating an empty PrintMatrix, all elements will initially be set to None and during conversion their dimensions will be determined by the other elements of the matrix (see example).

Elements can be set one at a time using name[row][col] = value or in rows using name[row] = vector where vector can be a vector or a list.

STRING REPRESENTATION of a PrintMatrix:

If the PrintMatrix is of type ‘vector’, the string will be formatted like a QuantVector. If it is of type ‘matrix’, the output will look like a list of lists, but with spacing that makes it easily readable.

The user can assign preferred units to quantities (see documentation for PrintMatrix.set_preferred() and quantity.Quantity.set_preferred()).

LaTeX REPRESENTATION of a PrintMatrix
The output is identical to that produced by QuantVector._latex_() or QuantMatrix._latex_(), except that the PrintMatrix allows unit assignment for elements.

EXAMPLES:

We create an empty PrintMatrix, assign values to some elements and then convert it to a QuantMatrix:

sage: M = PrintMatrix((2,2))
sage: M
[[ None  None ]
 [ None  None ]]
sage: M[0][1] = 3*meter
sage: M
[[ None   3 m ]
 [ None  None ]]
sage: M.to_qmatrix()
   1   m  
1 0.0 3.0 
1 0.0 0.0

None elements (see above) are zeroes of indeterminate dimensions, the dimensions of actual zeroes are fixed:

sage: A = PrintMatrix(qzeros(2))
sage: A
[[ 0  0 ]
 [ 0  0 ]]
sage: A[0][1] = 3*meter
sage: A
[[ 0  3 m ]
 [ 0   0  ]]
sage: A.to_qmatrix()
...
QuantMatrixError: Cannot convert to QuantMatrix, dimensions are not homogeneous (rows 0, 1)

PrintMatrices allow unit assignment, which QuantMatrices don’t. The two matrix types print differently, but the LaTeX output is the same (except possibly for the user-determined units):

sage: N = QuantMatrix([[3,4],[5,6]], [[joule/kilogram, joule/litre], [1/kilogram, 1/litre]])
sage: N
             kg^-1     m^-3   
 m^2 s^-2     3.0     4000.0  
m^-1 kg s^-2 5000.0  6000000.0
sage: N2 = PrintMatrix(N)
sage: N2
[[ 3.0 m^2 kg^-1 s^-2     4000.0 m^-1 s^-2    ]
[  5000.0 m^-1 s^-2   6000000.0 m^-4 kg s^-2 ]]
sage: N2._latex_() == N._latex_()
True

sage: N2.set_preferred([['J/kg^2', 'J/(l kg)'], ['J/(l kg)', 'J/l^2']])
sage: N2
[[ 3.0 J/kg^2    4.0 J/(l kg) ]
 [ 5.0 J/(l kg)  6.0 J/l^2 ]]
sage: N._latex_()
'\\left( \\begin{array}{cc}\n3 \\, \\mathrm{m}^{2} \\, \\mathrm{kg}^{-1} \\, \\mathrm{s}^{-2} & 4.00 \\times 10^{3} \\, \\mathrm{m}^{-1} \\, \\mathrm{s}^{-2} \\\\\n5.00 \\times 10^{3} \\, \\mathrm{m}^{-1} \\, \\mathrm{s}^{-2} & 6.00 \\times 10^{6} \\, \\mathrm{m}^{-4} \\, \\mathrm{kg} \\, \\mathrm{s}^{-2} \n\\end{array} \\right)'
sage: N2._latex_()
'\\left( \\begin{array}{cc}\n3 \\, \\mathrm{J}/\\mathrm{kg}^{2} & 4 \\, \\mathrm{J}/(\\mathrm{l} \\, \\mathrm{kg}) \\\\\n5 \\, \\mathrm{J}/(\\mathrm{l} \\, \\mathrm{kg}) & 6 \\, \\mathrm{J}/\\mathrm{l}^{2} \n\\end{array} \\right)'
ncols()

Return the number of columns of the PrintMatrix if it has type ‘matrix’.

EXAMPLES:

sage: A = PrintMatrix(QuantVector([1, 2], [meter, second]))
sage: A.ncols()
...
QuantMatrixError: PrintMatrix of type 'vector' has no columns, use len() instead.
sage: PrintMatrix((3, 4)).ncols()
4
nrows()

Return the number of rows of the PrintMatrix if it has type ‘matrix’.

EXAMPLES:

sage: PrintMatrix((3, 4)).nrows()
3
sage: A = PrintMatrix(QuantVector([1, 2], [meter, second]))
sage: A.nrows()
...
QuantMatrixError: PrintMatrix of type 'vector' has no rows, use len() instead.
set_preferred(*args, **kwargs)

Set the preferred unit for one or all elements of the PrintMatrix.

INPUT:
  • *args - either two integers giving a position and a unit for the element at that position or a list of lists of units of the same size as the PrintMatrix. All units must have the same dimensions as the corresponding elements of the PrintMatrix. None leaves the unit for that element unchanged.
  • **kwargs - the keyword arguments which may be required; see documentation for quantity.Quantity.set_preferred()

EXAMPLE:

sage: A = PrintMatrix([[5*mile, 8*kWh/day], [10000*second, 2*newton*metre]])
sage: A
[[    8.04672 km    333.333333333 W ]
 [ 2.77777777778 h        2 J       ]]
sage: A.set_preferred([[mile, 'kWh/d'], [second, 'N m']])
sage: A
[[  5.0 mi   8.0 kWh/d ]
 [ 10000 s     2 N m   ]]
to_qmatrix()

Convert the PrintMatrix to a QuantMatrix.

See documentation for qmatrix().

EXAMPLES:

sage: PrintMatrix([[None, kelvin, None, kelvin], [ampere, ampere, ampere, ampere], [second, None, second, None], [metre, None, metre, None]]).to_qmatrix()
        m    m    m    m  
m^-1 K 0.0  1.0  0.0  1.0 
m^-1 A 1.0  1.0  1.0  1.0 
m^-1 s 1.0  0.0  1.0  0.0 
   1   1.0  0.0  1.0  0.0

sage: PrintMatrix([[None, kelvin, None, kelvin], [ampere, ampere, volt, ampere], [second, None, second, None], [metre, None, metre, None]]).to_qmatrix()
...
QuantMatrixError: Cannot convert to QuantMatrix, dimensions are not homogeneous (row 1 and already set dimensions [1.0 m, None, 1.0 m, None])
to_qvector()

Convert the PrintMatrix to a QuantVector.

NOTES:

Causes an exception if the PrintMatrix is not one-dimensional.

EXAMPLE:

sage: z = QuantVector([1, 2, 3], [foot, litre, day])
sage: PrintMatrix(z)
(0.3048 m  2.0 l  72.0 h)
sage: _.to_qvector() == z
True

sage: PrintMatrix((2,3)).to_qvector()
...
QuantMatrixError: PrintMatrix must be one-dimensional, shape found (2, 3)
class sage.dimpy.quant_matrix.QuantMatrix(raw_numbers, quantities, unsafe=False)

A matrix with quantities.

INPUT:

  • raw_numbers - a list of lists of numbers or a Sage matrix
  • quantities - a list of lists of dimensional objects, the first list must have a length corresponding to the number of rows in raw_numbers, the second list must have a length equal to the number of columns in raw_numbers
  • unsafe - a bool, option True is used by the program internally to speed up QuantMatrix creation when it is certain that the input is legal and all quantities already have value 1

OUTPUT: a QuantMatrix with the given numerical values and dimensions; the numbers are modified so that we need only save Quantities with a numerical value of 1 in the.

NOTES:

The numerical_matrix and quantities may be changed using

QuantMatrix_instance.raw_numbers = new_matrix
QuantMatrix_quantities = new_quantities

and the type and size of each will be checked against the existing values.

EXAMPLES:

sage: from sage.dimpy import *
sage: raw_numbers = [[1,2],[3,4]]
sage: vertical_dimensions = [meter,second]
sage: horizontal_dimensions = [kilogram, mole]
sage: QuantMatrix(raw_numbers, [vertical_dimensions, horizontal_dimensions])
   kg  mol 
m 1.0  2.0 
s 3.0  4.0

The dimensions may be given as Dimension, Flydim or Quantity types and the numerical_matrix will be configured so that we display in SI units (and a Quantity instance with value 1 is stored).

sage: non_basic_vertical = [mile, hour]
sage: non_basic_horizontal = [yard, foot]
sage: A = QuantMatrix(raw_numbers, [non_basic_vertical, non_basic_horizontal])
sage: A
        m            m      
m 1471.5841536  981.0561024 
s    9875.52      4389.12  

Elements or slices of the QuantMatrix can be displayed. Slicing returns QuantMatrices, elements are returned as Quantities.

sage: A[0,0]
1471.5841536 m^2
sage: A[0]
        m            m      
m 1471.5841536  981.0561024 
sage: A[:,0]
        m        
m 1471.5841536 
s    9875.52  
commutator(other)

Return, if legal, the commutator of two matrices, i.e. A B - B A for two matrices A and B.

INPUT:

  • other - a QuantMatrix or Sage matrix

EXAMPLE:

sage: E = QuantMatrix([[1, 2], [3, 4]], [[meter, second], [second, meter]])
sage: F = QuantMatrix([[5, 6], [7, 8]], [[meter, second], [second, meter]])
sage: F.commutator(E)
  m s^2  m^2 s 
m  4.0    12.0 
s -12.0   -4.0
conjugate()

Take the complex conjugate of each element in the matrix.

NOTES:

If all elements of the QuantMatrix are real, it returns the matrix. To get the Hermitian conjugate of a matrix M use M.conjugate().transpose().

EXAMPLES:

sage: M = qrandom(4)
sage: M.conjugate() == M
True
sage: QuantMatrix([[1, 2+I], [7-I, 8*I]], [[kelvin, gray], [coulomb, pascal]])
             s A      m^-1 kg s^-2 
    K        1.0       2.0 + 1.0*I 
m^2 s^-2 7.0 - 1.0*I      8.0*I   
sage: _.conjugate()
             s A      m^-1 kg s^-2 
    K        1.0       2.0 - 1.0*I 
m^2 s^-2 7.0 + 1.0*I     -8.0*I   
determinant()

Return the determinant of this QuantMatrix.

NOTES:

This is well-defined for any square QuantMatrix.

EXAMPLE:

sage: M = QuantMatrix([[5, 6], [7, 8]], [[newton, gray], [coulomb, mole/second]])
sage: M.determinant()
-2.0 m^3 kg s^-4 A mol
eigenmatrix_left()

Return a diagonal matrix of eigenvalues and a matrix of eigenvectors, D and P, such that P \cdot self = D \cdot P and D is diagonal.

OUTPUT: a tuple of two QuantMatrices, the first one is a diagonal matrix of eigenvalues, the second one has the corresponding eigenvectors as its rows

NOTES:

See also documentation for QuantMatrix.eigenvalues().

EXAMPLE:

sage: H = QuantMatrix([[1, 2], [3, 4]], [[metre, radian], [radian, metre]])
sage: H
   1    m  
m 1.0  2.0 
1 3.0  4.0
sage: H.eigenmatrix_left()
(         m               m       
1 -0.372281323269        0       
1        0         5.37228132327,
          1                m        
1 -0.909376709132   0.415973557919 
1 -0.565767464969  -0.824564840132)
eigenmatrix_right()

Return a diagonal matrix of eigenvalues and a matrix of eigenvectors, D and P, such that self \cdot P = P \cdot D and D is diagonal.

OUTPUT: a tuple of two QuantMatrices, the first one is a diagonal matrix of eigenvalues, the second one has the corresponding eigenvectors as its columns

NOTES:

See also documentation for QuantMatrix.eigenvalues().

EXAMPLE:

sage: H = QuantMatrix([[1, 2], [3, 4]], [[metre, radian], [radian, metre]])
sage: D, P = H.eigenmatrix_right()
sage: H*P - P*D
           m                  m         
m          0          -4.4408920985e-16 
1 -5.55111512313e-17          0        
eigenvalues()

Return a list of the eigenvalues of the QuantMatrix with their multiplicities.

OUTPUT: a list of Quantities, the eigenvalues of the QuantMatrix

NOTES:

The eigenvalues are well-defined if the inner product of the quantity vectors is homogeneous.

EXAMPLE:

sage: H = QuantMatrix([[1, 2], [3, 4]], [[metre, radian], [radian, metre]])
sage: H.eigenvalues()
[-0.372281323269 m, 5.37228132327 m]
eigenvectors_left()

Return a list of the eigenvalues and left eigenvectors of the QuantMatrix, i.e. vectors and values such that v \cdot self = \lambda v.

OUTPUT: a list of tuples, each containing an eigenvalue and the corresponding left eigenvector

NOTES:

Like the length of the eigenvectors, the dimensions are only defined up to an arbitrary factor.

See also documentation for QuantMatrix.eigenvalues().

EXAMPLE:

sage: H = QuantMatrix([[1, 2], [3, 4]], [[metre, radian], [radian, metre]])
sage: l, v = H.eigenvectors_left()[0]
sage: v*H - v*l
(-1.66533453694e-16 m  -3.05311331772e-16 m^2)
eigenvectors_right()

Return a list of the eigenvalues right eigenvectors of the QuantMatrix, i.e. vectors and values such that self \cdot v = \lambda v.

OUTPUT: a list of tuples, each containing an eigenvalue and the corresponding right eigenvector

NOTES:

Like the length of the eigenvectors, the dimensions are only defined up to an arbitrary factor.

See also documentation for QuantMatrix.eigenvalues().

EXAMPLE:

sage: H = QuantMatrix([[1, 2], [3, 4]], [[metre, radian], [radian, metre]])
sage: l, v = H.eigenvectors_right()[1]
sage: H*v - l*v
(-4.4408920985e-16 m^2  0 m)
inverse()

Return, if defined, the dimensional inverse of this QuantMatrix, this is not quite the same as a normal inverse.

NOTES:

The inverse is defined if the determinant is not 0. The result of A^{-1} \cdot A is not in general equal to I unless the dimensions of the zeros are ignored ( similarly for A \cdot A^{-1}): see examples.

EXAMPLES:

Define a QuantMatrix and create its inverse:

sage: A = QuantMatrix([[1, 2], [3, 4]], [[meter, kelvin], [hertz, mole]])
sage: A
  s^-1  mol 
m  1.0  2.0 
K  3.0  4.0
sage: A.inverse()
       m^-1  K^-1 
   s   -2.0   1.0 
mol^-1  1.5  -0.5

Calculate A^{-1} \cdot A:

sage: A.inverse() * A
       s^-1  mol 
   s    1.0  0.0 
mol^-1  0.0  1.0
sage: PrintMatrix(_)
[[       1.0        0.0 s mol ]
 [ 0.0 s^-1 mol^-1     1.0    ]]

Calculate A \cdot A^{-1}:

sage: A * A.inverse()
  m^-1  K^-1 
m  1.0   0.0 
K  0.0   1.0
sage: PrintMatrix(_)
[[     1.0     0.0 m K^-1 ]
 [ 0.0 m^-1 K      1.0    ]]

The operator ~ has the same effect:

sage: A.inverse() == ~A
True

Matrices with zero determinant cannot be inverted:

sage: QuantMatrix([[1, 2], [-1, -2]], [[metre, second], [mole, kelvin]]).inverse()
...
QuantMatrixError: Cannot invert this matrix.
sage: QuantMatrix([[1, 2], [-1, -2]], [[metre, second], [mole, kelvin]]).determinant()
0.0 m s K mol
is_hermitian()

Return True if the matrix is hermitian, i.e. if M_{ij} = M^*_{ji} for all i, j where the star denotes complex conjugation.

OUTPUT: a bool

EXAMPLES:

sage: QuantMatrix([[3, 2], [2, 4]], [[meter, radian], [meter, radian]]).is_hermitian()
True
sage: QuantMatrix([[3, 2-I], [2+I, 4]], [[meter, radian], [meter, radian]]).is_hermitian()
True
sage: QuantMatrix([[3+I, 2-I], [2+I, 4]], [[meter, radian], [meter, radian]]).is_hermitian()
False
is_invertible()

Return True if the matrix is invertible, i.e. has non-zero determinant.

OUTPUT: a bool

EXAMPLES:

sage: QuantMatrix([[1, 2], [4, 5]], [[meter, second], [mole, kelvin]]).is_invertible()
True
sage: QuantMatrix([[1, 2], [4, 8]], [[meter, second], [mole, kelvin]]).is_invertible()
False
is_real()

Return True if the matrix does not have any complex-valued elements.

OUTPUT: a bool

NOTES:

The type of the matrix of raw numbers may be the Sage complex matrix type even if this function returns True.

EXAMPLES:

sage: QuantMatrix([[1, 2], [3, 4]], [[coulomb, pascal], [litre, foot]]).is_real()
True
sage: QuantMatrix([[1, 2*I], [3, 4]], [[coulomb, pascal], [litre, foot]]).is_real()
False
sage: A = QuantMatrix(matrix(CDF, [[1, 2], [3, 4]]), [[coulomb, pascal], [litre, foot]])
sage: A.is_real()
True
sage: parent(A.raw_numbers)
Full MatrixSpace of 2 by 2 dense matrices over Complex Double Field
is_square()

Check whether the matrix is square.

OUTPUT: a bool

EXAMPLES:

sage: qrandom(3).is_square()
True
sage: qrandom(2, 4).is_square()
False
is_symmetric()

Check whether the matrix is symmetric, i.e. whether M_{ij} = M_{ji} for all i, j.

OUTPUT: a bool

EXAMPLES:

sage: qidentity(4).is_symmetric()
True
sage: qrandom(2, 3).is_symmetric()
False
legal_add(other)

Return True if it is legal to add other to self.

Otherwise raise an error or return False.

NOTES:

There are three requirements for the sum to be legal, given that the matrices have the same shape (otherwise it cannot be legal at all). Suppose we are computing A+B, let A_L and A_T be the left and top dimensions of A, similarly for B.

  1. The pointwise division A_L/B_L must give a list of dimensions which are all the same (i.e. A_L/B_L is homogeneous).
  2. Like #1 but for A_T, B_T.
  3. If \alpha and \beta are these two dimensions, \alpha\beta must be dimensionless.

EXAMPLES:

sage: A = QuantMatrix([[1, 2, 3], [4, 5, 6]], [[hertz, becquerel], [second, minute, hour]])
sage: from sage.matrix.constructor import random_matrix
sage: A.legal_add(random_matrix(RR, 2, 3))
True
sage: A.legal_add(qidentity(2))
...
QuantMatrixError: Cannot add matrices, shapes are different: (2, 3), (2, 2)
legal_mul(other)

Return a bool, whether it is legal to multiply self and other.

NOTES:

If other passes is_scalar_type or is a Quantity or Flydim we can return True directly, else there are two requirements for the product A B to be legal:

  1. We need A.ncols() == B.nrows()
  2. We require the inner product of A_T and B_L to be well defined, where A_T are the top quantities of A and B_L the left quantities of B (i.e. the sum must be allowed, which occurs if each term has the same dimension).

EXAMPLES:

sage: A = qmatrix([[7*meter, 8*knot], [9*joule, 10*watt]])
sage: A.legal_mul(3*kelvin)
True
sage: A.legal_mul(Flydim())
True
sage: A.legal_mul(qrandom(2))
False
sage: A.legal_mul(QuantMatrix([[0.1, 0.2], [0.3, 0.4]], [[radian, second], [hertz, 1/kilogram]]))
True
ncols()

Return the number of columns of the QuantMatrix.

OUTPUT: an integer

EXAMPLE:

sage: qrandom(3, 4).ncols()
4
nrows()

Return the number of rows of the QuantMatrix.

OUTPUT: an integer

EXAMPLE:

sage: qrandom(3, 4).nrows()
3
quantities
Return the dimensional objects associated with this QuantMatrix.
raw_numbers
Return the raw numbers making up the QuantMatrix.
shape()

Return the shape of the matrix.

OUTPUT: a tuple (number of rows, number of columns)

EXAMPLE:

sage: qrandom(2, 5).shape()
(2, 5)
shuffle(shuffle_dimension)

Multiply the top dimensions by shuffle_dimension and divide the left dimensions by shuffle_dimension.

INPUT:

  • shuffle_dimension - a dimensional object, any numerical value is ignored

NOTES:

This process does not alter the QuantMatrix itself but only its string representation. There is no output.

EXAMPLE:

sage: a = qidentity(3, RDF)
sage: a.shuffle(meter)
sage: a
      m    m    m  
m^-1 1.0  0.0  0.0 
m^-1 0.0  1.0  0.0 
m^-1 0.0  0.0  1.0
trace()

Return the trace of this QuantMatrix, if defined.

OUTPUT: a Quantity

NOTES:

The QuantMatrix has to be square and the pointwise product of the quantitiy vectors must be homogeneous.

EXAMPLES:

sage: E = QuantMatrix([[1, 2], [3, 4]], [[meter, second], [second, meter]])
sage: E
   s    m  
m 1.0  2.0 
s 3.0  4.0
sage: E.trace()
5.0 m s
sage: QuantMatrix([[1, 2], [3, 4]], [[meter, second], [kelvin, meter]]).trace()
...
QuantMatrixError: Trace: The inner product of the quantity vectors is not of a single unit
transpose()

Return the transpose of this QuantMatrix, i.e. if the original matrix is M_{ij}, the result is M_{ji} for all i, j.

OUTPUT: a QuantMatrix

EXAMPLE:

sage: F = QuantMatrix([[5, 6, 7], [8, 9, 10]], [[kilogram, joule], [hertz, second, radian]])
sage: F
            s^-1   s     1  
     kg      5.0  6.0   7.0 
m^2 kg s^-2  8.0  9.0  10.0
sage: F.transpose()
      kg  m^2 kg s^-2 
s^-1 5.0      8.0     
  s  6.0      9.0     
  1  7.0      10.0   
exception sage.dimpy.quant_matrix.QuantMatrixError
The exception raised if some operation on QuantMatrices is illegal.
class sage.dimpy.quant_matrix.QuantVector(raw_numbers, quantities, unsafe=False)

A vector with quantities, modelled on the Sage FreeModuleElement class.

INPUT:

  • raw_numbers - a list of numbers or a Sage vector
  • quantities - a list of dimensional objects, must have the same length as raw_numbers
  • unsafe - a bool, option True is used by the program internally to speed up QuantVector creation when it is certain that the input is legal and all quantities already have value 1

OUTPUT: a QuantVector having the given numbers and dimensions

EXAMPLE:

sage: raw_numbers = [1, 2, 3]        
sage: quantities = [meter, second, kilogram]
sage: QuantVector(raw_numbers, quantities)
(1.0 m  2.0 s  3.0 kg)
cross_product(other)

Calculate the cross product of two QuantVectors or a QuantVector and a Sage Vector, checking whether the dimensions allow it.

INPUT:

  • other - a QuantVector or Sage vector of the same length as self

OUTPUT: a QuantVector if self has length 3, a Quantity if length 2

NOTES:

For the cross product of two vectors x and y to be well defined, they must both have length 3. Furthermore, the vector obtained by pointwise division of the two quantity vectors must be homogeneous, i.e. its dimensions must all be the same.

For vectors of length 2, the third component of the cross product is calculated and returned as a scalar quantity.

EXAMPLE:

sage: a = QuantVector([1, 2, 3], [meter, second, kilogram])
sage: b = QuantVector([4, 5, 6], [foot, day, gram])
sage: a.cross_product(b)
(-1295999.988 kg s  3.6516 m kg  431997.5616 m s)
dot_product(other)

Calculate the dot product of two QuantVectors or a QuantVector and a Sage vector, checking whether the dimensions allow it.

INPUT:

  • other - a QuantVector or Sage vector of the same length as self

OUTPUT: a Quantity

NOTES:

For the dot product to be well defined, the vectors must have the same length and the vector obtained by pointwise multiplication of the two quantity vectors must be homogeneous.

EXAMPLE:

sage: a = QuantVector([1, 2, 3], [meter, second, kilogram])
sage: c = QuantVector([4, 5, 6], [Dimension(), meter/second, meter/kilogram])
sage: a.dot_product(c)
32.0 m
norm()

Calculate the norm of a QuantVector.

OUTPUT: a Quantity, the norm of the QuantVector

NOTES:

Computes the dot product of the vector with itself and then takes the square root of the result. The dot product must be well defined.

EXAMPLE:

sage: d = QuantVector([1, 2, 3, 4], [meter, foot, inch, yard])
sage: d.norm()
3.84128316582 m
normalize()

Normalize a QuantVector, if possible, i.e. returns a QuantVector with the same direction but unit norm.

OUTPUT: a QuantVector with norm 1 parallel to the original QuantVector

NOTES:

See documentation for QuantVector.norm().

EXAMPLE:

sage: d = QuantVector([1, 2, 3, 4], [meter, foot, inch, yard])
sage: d.normalize()
(0.260329675484  0.158696970175  0.0198371212719  0.952181821051)
sage: d.normalize() * d.normalize()
1.0
pointwise_divide_by(other)

Divide two vectors elementwise.

INPUT:
  • other - a QuantVector or Sage vector of the same length as self

OUTPUT: a QuantVector

EXAMPLE:

sage: a = QuantVector([1, 2, 3], [meter, second, kilogram])
sage: f = QuantVector([4, 5, 6], [kelvin, mole, amp])
sage: a.pointwise_divide_by(f)
(0.25 m K^-1  0.4 s mol^-1  0.5 kg A^-1)
pointwise_multiply_by(other)

Multiply two vectors elementwise.

INPUT:

  • other - a QuantVector or Sage vector of the same length as self

OUTPUT: a QuantVector

EXAMPLE:

sage: a = QuantVector([1, 2, 3], [meter, second, kilogram])
sage: f = QuantVector([4, 5, 6], [kelvin, mole, amp])
sage: a.pointwise_multiply_by(f)
(4.0 m K  10.0 s mol  18.0 kg A)
quantities
Return the dimensional objects associated with this QuantVector.
raw_numbers
Return the underlying Sage vector for this QuantVector.
transpose()

Transpose the QuantVector, return a QuantMatrix with shape (len(self), 1)

OUTPUT: a column QuantMatrix, the transpose of this QuantVector

EXAMPLE:

sage: b = QuantVector([4, 5, 6], [foot, day, gram])
sage: b
(1.2192 m  5.0 d  0.006 kg)
sage: b.transpose()
       1    
 m  1.2192  
 s 432000.0 
kg   0.006 
sage.dimpy.quant_matrix.get_inner_product_placement()

Return the inner product placement for QuantMatrices.

OUTPUT: a string, either ‘top’ or ‘left’

EXAMPLE:

sage: get_inner_product_placement()
'top'
sage.dimpy.quant_matrix.get_white_size()

Return the number of white spaces between elements in the string representation of a QuantMatrix.

EXAMPLE:

sage: get_white_size()
1
sage.dimpy.quant_matrix.qhomogeneous(size, dimension)

Produce a list of quantities of size size where all entries have value 1 and the dimensions and flydims of the given object.

INPUT:

  • size - an integer, the length of the list
  • dimension - any dimensional object (the numerical value is ignored)

OUTPUT: a list of Quantities with value 1 and the same dimensions as the input object

EXAMPLE:

sage: qhomogeneous(4, meter)
[m, m, m, m]
sage: qhomogeneous(4, Dimension(m=1, s=2))
[1 m s^2, 1 m s^2, 1 m s^2, 1 m s^2]
sage.dimpy.quant_matrix.qidentity(size, ntype=None)

Create the identitiy matrix of size size.

INPUT:
  • size - the number of rows and columns of the matrix
  • ntype - the Sage ring determining the type of the numbers defaults to \ZZ, i.e. integers

OUTPUT: an identity QuantMatrix of the given size

EXAMPLE:

sage: qidentity(3)
  1  1  1  
1 1  0  0 
1 0  1  0 
1 0  0  1
sage.dimpy.quant_matrix.qmatrix(array)

Cast a Sage matrix, PrintMatrix, list of lists of Quantities or a QuantVector into a QuantMatrix.

INPUT:

  • array - a Sage matrix, PrintMatrix, list of lists of Quantities or QuantVector

OUTPUT: a QuantMatrix corresponding to the input array

ALGORITHM:

The conversion is straightforward except when array is a PrintMatrix of type ‘matrix’ or a list of lists.

Two different kinds of zero elements are accepted in the PrintMatrix and the list of lists:

  • elements that are 0 with some set dimension (i.e. 0*unit), and
  • elements that are None.

The latter will be changed into zeros during the conversion, but their dimensions are not fixed: they will be determined by the other elements in the matrix. In the following, elements that are not equal to None will be called “set elements”.

  1. Find a row with at least one set element. We will call it row1. If that fails, we have a zero matrix and the conversion is easy. This search starts at the bottom to make subsequent loops easier to write.
  2. Find a row that has set elements in some of the same columns as the first row, call it row2.
  3. Take the columnwise ratio of the two rows (this is only defined for columns where both rows have set elements, and it ignores numerical values, considering only dimensions and flydims).
  4. Check if the ratios are the same for all columns. If not, raise an error.
  5. Set the row1-element of the left quantity vector to Quantity() and the row2-element to the common ratio of the columns.
  6. Fill in the top quantity vector so that all elements of row1 and row2 get the right dimensions and flydims.
  7. Now look at the rows that haven’t been set yet in turn. For each row, first check whether it has set elements. If no, set the corresponding element of the left quantity vector to Quantity() and move on.
  8. If some of the set elements of the current row are in columns that have already been assigned dimensions, take the ratio of the dimensions of the row elements and the top quantity vector. Proceed as in 4 and 5, set the element in the left quantity vector apropriately, then fill up further elements of the top quantity vector.
  9. If none of the set elements are in columns that have already been assigned dimensions, the current row is completely independent of the ones we have considered before. Proceed as in 2, if that fails the row is independent of all others, so set the corresponding left quantity vector element to Quantity() and set the columns apropriately.
  10. If we find another row that has not yet been set and has some elements in the same columns as the current row, first check whether the new row agrees with what has already been set. If so, proceed similarly to 5 and 6.

EXAMPLES:

sage: N = QuantMatrix([[3,4],[5,6]], [[joule/kilogram, joule/litre], [1/kilogram, 1/litre]])
sage: N2 = PrintMatrix(N)
sage: N2.to_qmatrix()
          m^-1 s^-2  m^-4 kg s^-2 
m^3 kg^-1    3.0        4000.0    
    1       5000.0     6000000.0 
sage: _ == N
True

sage: a = matrix([[1, 2], [3, 4]])
sage: qmatrix(a)
  1  1 
1 1  2 
1 3  4

sage: b = QuantVector([4, 5, 6], [inch, joule, gram])
sage: qmatrix(b)
     m    m^2 kg s^-2    kg  
1 0.1016      5.0      0.006
sage.dimpy.quant_matrix.qrandom(nrows, ncols=None, ntype=None)

Produce a dimensionless QuantMatrix of the given shape with random entries.

INPUT:

  • nrows - number of rows
  • ncols - number of columns, if not specified this is set equal to nrows
  • ntype - the Sage ring determining the type of the numbers (defaults to \ZZ, i.e. integers)

OUTPUT: a QuantMatrix of the given shape with dimensionless quantities and random entries of the given number type

EXAMPLE:

sage: qrandom(3)    # random
   1   1   1 
1  1  -1  -6 
1 -1   1  -3 
1  1   1  -7
sage.dimpy.quant_matrix.qvector(array)

Cast a Sage vector or a one-dimensional matrix into a QuantVector.

INPUT:

  • array - a Sage vector, a list of quantities or a one-dimensional Sage matrix, QuantMatrix or PrintMatrix

OUTPUT: a QuantVector corresponding to the input array

EXAMPLES:

sage: qvector(matrix([1, 2, 3]))
(1  2  3)
sage: qvector(QuantMatrix([1, 2, 3], [[meter], [meter, meter**2, 1/second]]))
(1.0 m^2  2000.0 l  3.0 m s^-1)
sage: qvector([3*meter/second, 4*hour])
(3.0 m s^-1  4.0 h)
sage.dimpy.quant_matrix.qzeros(nrows, ncols=None, ntype=None)

Produce a dimensionless QuantMatrix filled with zeros.

INPUT:

  • nrows - number of rows
  • ncols - number of columns, if not specified this is set equal to nrows
  • ntype - the Sage ring determining the type of the numbers (defaults to \ZZ, i.e. integers)

OUTPUT: a QuantMatrix with dimensionless quantities and filled with zeros of the given number type

EXAMPLES:

sage: qzeros(2, 3, RDF)
   1    1    1  
1 0.0  0.0  0.0 
1 0.0  0.0  0.0
sage: qzeros(2)
  1  1  
1 0  0 
1 0  0
sage.dimpy.quant_matrix.set_inner_product_placement(position='top')

Set the inner product placement for QuantMatrices (default: ‘top’).

INPUT:
  • position - either ‘top’ or ‘left’

EXAMPLE:

sage: set_inner_product_placement('left')
sage: get_inner_product_placement()
'left'
sage: set_inner_product_placement()  # go back to default so we don't break any later doctests
sage.dimpy.quant_matrix.set_white_size(n=1)

Set the number of white spaces between elements in the string representation of a QuantMatrix (default: 1).

INPUT:
  • n - a positive integer

EXAMPLE:

sage: A = QuantMatrix([[1, 2], [3, 4]], [[kilogram, second], [mole, kelvin]])
sage: A
   mol   K  
kg 1.0  2.0 
 s 3.0  4.0
sage: set_white_size(2)
sage: A
    mol     K   
kg  1.0    2.0  
 s  3.0    4.0
sage: set_white_size()  # go back to default so we don't break any later doctests