Help on module matrix: NAME matrix - Complete solution for the CS101 Programming Project about matrices. FILE /home/lilian/teach/mec-cs101-matrices/matrix.py DESCRIPTION This file defines a class :class:`Matrix`, designed to be as complete as possible. *Do not worry, I was not asking you to do as much.* Examples -------- Importing the module: >>> from matrix import * >>> from matrix import Matrix as M # shortcut Defining a matrix by giving its list of rows: >>> A = M([[1, 0], [0, 1]]) >>> A == eye(A.n) True >>> B = 2*(A**2) + 4*A + eye(A.n) >>> B [[7, 0], [0, 7]] >>> B == 7 * eye(A.n) True Indexing and slicing: >>> A[1,:] = 2; A [[1, 0], [2, 2]] >>> A[0, 0] = -5; A [[-5, 0], [2, 2]] Addition, multiplication, power etc: >>> C = eye(2); C [[1, 0], [0, 1]] >>> C + (3 * C) - C [[3, 0], [0, 3]] >>> (4 * C) ** 2 [[16, 0], [0, 16]] Many more examples are given below: ----------------------------------------------------------------------------- Things that could still be worked on for this solution ------------------------------------------------------ .. todo:: Implement the **QR**, **SVD** and other **matrix decompositions**. .. todo:: Try to add a randomized matrix decomposition (or any *less-original* matrix decomposition method)? Note: I worked on this aspect, for a project in January 2016 for my M.Sc. : ``_. .. todo:: Implement a nice wrapper for a linear equations solver (with LU). .. todo:: More doctests for :py:func:`PLUdecomposition`, and implement the non-permuted LU decomposition? .. todo:: Add more doctests and examples for Gauss, Gauss-Jordan, Gram-Schmidt (:py:func:`gauss`, :py:func:`gauss_jordan`, :py:func:`gram_schmidt`)? .. note:: Interactive examples? See the other file `tests.py `_ for *many* examples. - *Date:* Saturday 18 juin 2016, 10:31:25. - *Author:* `Lilian Besson `_ for the `CS101 course `_ at `Mahindra Ecole Centrale `_, 2015, - *Licence:* `MIT Licence `_. .. seealso:: I also wrote a complete solution for the other project I was in charge of, `about numerical algorithms to compute integrals `_. CLASSES __builtin__.object Matrix decimal.Decimal(__builtin__.object) Decimal fractions.Fraction(numbers.Rational) Fraction class Decimal(decimal.Decimal) | Extended :class:`decimal.Decimal` class to improve the ``str`` and ``repr`` methods. | | If there is not digit after the comma, print it as an integer. | | Method resolution order: | Decimal | decimal.Decimal | __builtin__.object | | Methods defined here: | | __repr__ = __str__(self, *args, **kwargs) | | __str__(self, *args, **kwargs) | | ---------------------------------------------------------------------- | Data descriptors defined here: | | __dict__ | dictionary for instance variables (if defined) | | __weakref__ | list of weak references to the object (if defined) | | ---------------------------------------------------------------------- | Methods inherited from decimal.Decimal: | | __abs__(self, round=True, context=None) | Returns the absolute value of self. | | If the keyword argument 'round' is false, do not round. The | expression self.__abs__(round=False) is equivalent to | self.copy_abs(). | | __add__(self, other, context=None) | Returns self + other. | | -INF + INF (or the reverse) cause InvalidOperation errors. | | __complex__(self) | | __copy__(self) | | __deepcopy__(self, memo) | | __div__ = __truediv__(self, other, context=None) | Return self / other. | | __divmod__(self, other, context=None) | Return (self // other, self % other) | | __eq__(self, other, context=None) | | __float__(self) | Float representation. | | __floordiv__(self, other, context=None) | self // other | | __format__(self, specifier, context=None, _localeconv=None) | Format a Decimal instance according to the given specifier. | | The specifier should be a standard format specifier, with the | form described in PEP 3101. Formatting types 'e', 'E', 'f', | 'F', 'g', 'G', 'n' and '%' are supported. If the formatting | type is omitted it defaults to 'g' or 'G', depending on the | value of context.capitals. | | __ge__(self, other, context=None) | | __gt__(self, other, context=None) | | __hash__(self) | x.__hash__() <==> hash(x) | | __int__(self) | Converts self to an int, truncating if necessary. | | __le__(self, other, context=None) | | __long__(self) | Converts to a long. | | Equivalent to long(int(self)) | | __lt__(self, other, context=None) | | __mod__(self, other, context=None) | self % other | | __mul__(self, other, context=None) | Return self * other. | | (+-) INF * 0 (or its reverse) raise InvalidOperation. | | __ne__(self, other, context=None) | | __neg__(self, context=None) | Returns a copy with the sign switched. | | Rounds, if it has reason. | | __nonzero__(self) | Return True if self is nonzero; otherwise return False. | | NaNs and infinities are considered nonzero. | | __pos__(self, context=None) | Returns a copy, unless it is a sNaN. | | Rounds the number (if more then precision digits) | | __pow__(self, other, modulo=None, context=None) | Return self ** other [ % modulo]. | | With two arguments, compute self**other. | | With three arguments, compute (self**other) % modulo. For the | three argument form, the following restrictions on the | arguments hold: | | - all three arguments must be integral | - other must be nonnegative | - either self or other (or both) must be nonzero | - modulo must be nonzero and must have at most p digits, | where p is the context precision. | | If any of these restrictions is violated the InvalidOperation | flag is raised. | | The result of pow(self, other, modulo) is identical to the | result that would be obtained by computing (self**other) % | modulo with unbounded precision, but is computed more | efficiently. It is always exact. | | __radd__ = __add__(self, other, context=None) | Returns self + other. | | -INF + INF (or the reverse) cause InvalidOperation errors. | | __rdiv__ = __rtruediv__(self, other, context=None) | Swaps self/other and returns __truediv__. | | __rdivmod__(self, other, context=None) | Swaps self/other and returns __divmod__. | | __reduce__(self) | # Support for pickling, copy, and deepcopy | | __rfloordiv__(self, other, context=None) | Swaps self/other and returns __floordiv__. | | __rmod__(self, other, context=None) | Swaps self/other and returns __mod__. | | __rmul__ = __mul__(self, other, context=None) | Return self * other. | | (+-) INF * 0 (or its reverse) raise InvalidOperation. | | __rpow__(self, other, context=None) | Swaps self/other and returns __pow__. | | __rsub__(self, other, context=None) | Return other - self | | __rtruediv__(self, other, context=None) | Swaps self/other and returns __truediv__. | | __sub__(self, other, context=None) | Return self - other | | __truediv__(self, other, context=None) | Return self / other. | | __trunc__ = __int__(self) | Converts self to an int, truncating if necessary. | | adjusted(self) | Return the adjusted exponent of self | | as_tuple(self) | Represents the number as a triple tuple. | | To show the internals exactly as they are. | | canonical(self, context=None) | Returns the same Decimal object. | | As we do not have different encodings for the same number, the | received object already is in its canonical form. | | compare(self, other, context=None) | Compares one to another. | | -1 => a < b | 0 => a = b | 1 => a > b | NaN => one is NaN | Like __cmp__, but returns Decimal instances. | | compare_signal(self, other, context=None) | Compares self to the other operand numerically. | | It's pretty much like compare(), but all NaNs signal, with signaling | NaNs taking precedence over quiet NaNs. | | compare_total(self, other) | Compares self to other using the abstract representations. | | This is not like the standard compare, which use their numerical | value. Note that a total ordering is defined for all possible abstract | representations. | | compare_total_mag(self, other) | Compares self to other using abstract repr., ignoring sign. | | Like compare_total, but with operand's sign ignored and assumed to be 0. | | conjugate(self) | | copy_abs(self) | Returns a copy with the sign set to 0. | | copy_negate(self) | Returns a copy with the sign inverted. | | copy_sign(self, other) | Returns self with the sign of other. | | exp(self, context=None) | Returns e ** self. | | fma(self, other, third, context=None) | Fused multiply-add. | | Returns self*other+third with no rounding of the intermediate | product self*other. | | self and other are multiplied together, with no rounding of | the result. The third operand is then added to the result, | and a single final rounding is performed. | | is_canonical(self) | Return True if self is canonical; otherwise return False. | | Currently, the encoding of a Decimal instance is always | canonical, so this method returns True for any Decimal. | | is_finite(self) | Return True if self is finite; otherwise return False. | | A Decimal instance is considered finite if it is neither | infinite nor a NaN. | | is_infinite(self) | Return True if self is infinite; otherwise return False. | | is_nan(self) | Return True if self is a qNaN or sNaN; otherwise return False. | | is_normal(self, context=None) | Return True if self is a normal number; otherwise return False. | | is_qnan(self) | Return True if self is a quiet NaN; otherwise return False. | | is_signed(self) | Return True if self is negative; otherwise return False. | | is_snan(self) | Return True if self is a signaling NaN; otherwise return False. | | is_subnormal(self, context=None) | Return True if self is subnormal; otherwise return False. | | is_zero(self) | Return True if self is a zero; otherwise return False. | | ln(self, context=None) | Returns the natural (base e) logarithm of self. | | log10(self, context=None) | Returns the base 10 logarithm of self. | | logb(self, context=None) | Returns the exponent of the magnitude of self's MSD. | | The result is the integer which is the exponent of the magnitude | of the most significant digit of self (as though it were truncated | to a single digit while maintaining the value of that digit and | without limiting the resulting exponent). | | logical_and(self, other, context=None) | Applies an 'and' operation between self and other's digits. | | logical_invert(self, context=None) | Invert all its digits. | | logical_or(self, other, context=None) | Applies an 'or' operation between self and other's digits. | | logical_xor(self, other, context=None) | Applies an 'xor' operation between self and other's digits. | | max(self, other, context=None) | Returns the larger value. | | Like max(self, other) except if one is not a number, returns | NaN (and signals if one is sNaN). Also rounds. | | max_mag(self, other, context=None) | Compares the values numerically with their sign ignored. | | min(self, other, context=None) | Returns the smaller value. | | Like min(self, other) except if one is not a number, returns | NaN (and signals if one is sNaN). Also rounds. | | min_mag(self, other, context=None) | Compares the values numerically with their sign ignored. | | next_minus(self, context=None) | Returns the largest representable number smaller than itself. | | next_plus(self, context=None) | Returns the smallest representable number larger than itself. | | next_toward(self, other, context=None) | Returns the number closest to self, in the direction towards other. | | The result is the closest representable number to self | (excluding self) that is in the direction towards other, | unless both have the same value. If the two operands are | numerically equal, then the result is a copy of self with the | sign set to be the same as the sign of other. | | normalize(self, context=None) | Normalize- strip trailing 0s, change anything equal to 0 to 0e0 | | number_class(self, context=None) | Returns an indication of the class of self. | | The class is one of the following strings: | sNaN | NaN | -Infinity | -Normal | -Subnormal | -Zero | +Zero | +Subnormal | +Normal | +Infinity | | quantize(self, exp, rounding=None, context=None, watchexp=True) | Quantize self so its exponent is the same as that of exp. | | Similar to self._rescale(exp._exp) but with error checking. | | radix(self) | Just returns 10, as this is Decimal, :) | | remainder_near(self, other, context=None) | Remainder nearest to 0- abs(remainder-near) <= other/2 | | rotate(self, other, context=None) | Returns a rotated copy of self, value-of-other times. | | same_quantum(self, other) | Return True if self and other have the same exponent; otherwise | return False. | | If either operand is a special value, the following rules are used: | * return True if both operands are infinities | * return True if both operands are NaNs | * otherwise, return False. | | scaleb(self, other, context=None) | Returns self operand after adding the second value to its exp. | | shift(self, other, context=None) | Returns a shifted copy of self, value-of-other times. | | sqrt(self, context=None) | Return the square root of self. | | to_eng_string(self, context=None) | Convert to engineering-type string. | | Engineering notation has an exponent which is a multiple of 3, so there | are up to 3 digits left of the decimal place. | | Same rules for when in exponential and when as a value as in __str__. | | to_integral = to_integral_value(self, rounding=None, context=None) | Rounds to the nearest integer, without raising inexact, rounded. | | to_integral_exact(self, rounding=None, context=None) | Rounds to a nearby integer. | | If no rounding mode is specified, take the rounding mode from | the context. This method raises the Rounded and Inexact flags | when appropriate. | | See also: to_integral_value, which does exactly the same as | this method except that it doesn't raise Inexact or Rounded. | | to_integral_value(self, rounding=None, context=None) | Rounds to the nearest integer, without raising inexact, rounded. | | ---------------------------------------------------------------------- | Class methods inherited from decimal.Decimal: | | from_float(cls, f) from __builtin__.type | Converts a float to a decimal number, exactly. | | Note that Decimal.from_float(0.1) is not the same as Decimal('0.1'). | Since 0.1 is not exactly representable in binary floating point, the | value is stored as the nearest representable value which is | 0x1.999999999999ap-4. The exact equivalent of the value in decimal | is 0.1000000000000000055511151231257827021181583404541015625. | | >>> Decimal.from_float(0.1) | Decimal('0.1000000000000000055511151231257827021181583404541015625') | >>> Decimal.from_float(float('nan')) | Decimal('NaN') | >>> Decimal.from_float(float('inf')) | Decimal('Infinity') | >>> Decimal.from_float(-float('inf')) | Decimal('-Infinity') | >>> Decimal.from_float(-0.0) | Decimal('-0') | | ---------------------------------------------------------------------- | Static methods inherited from decimal.Decimal: | | __new__(cls, value='0', context=None) | Create a decimal point instance. | | >>> Decimal('3.14') # string input | Decimal('3.14') | >>> Decimal((0, (3, 1, 4), -2)) # tuple (sign, digit_tuple, exponent) | Decimal('3.14') | >>> Decimal(314) # int or long | Decimal('314') | >>> Decimal(Decimal(314)) # another decimal instance | Decimal('314') | >>> Decimal(' 3.14 \n') # leading and trailing whitespace okay | Decimal('3.14') | | ---------------------------------------------------------------------- | Data descriptors inherited from decimal.Decimal: | | imag | | real class Fraction(fractions.Fraction) | Extended :class:`fractions.Fraction` class to improve the ``str`` and ``repr`` methods. | | If the denominator is 1, print it as an integer. | | Method resolution order: | Fraction | fractions.Fraction | numbers.Rational | numbers.Real | numbers.Complex | numbers.Number | __builtin__.object | | Methods defined here: | | __repr__ = __str__(self, *args, **kwargs) | | __str__(self, *args, **kwargs) | | ---------------------------------------------------------------------- | Data descriptors defined here: | | __dict__ | dictionary for instance variables (if defined) | | __weakref__ | list of weak references to the object (if defined) | | ---------------------------------------------------------------------- | Data and other attributes defined here: | | __abstractmethods__ = frozenset([]) | | ---------------------------------------------------------------------- | Methods inherited from fractions.Fraction: | | __abs__(a) | abs(a) | | __add__(a, b) | a + b | | __copy__(self) | | __deepcopy__(self, memo) | | __div__(a, b) | a / b | | __eq__(a, b) | a == b | | __floordiv__(a, b) | a // b | | __ge__(a, b) | a >= b | | __gt__(a, b) | a > b | | __hash__(self) | hash(self) | | Tricky because values that are exactly representable as a | float must have the same hash as that float. | | __le__(a, b) | a <= b | | __lt__(a, b) | a < b | | __mod__(a, b) | a % b | | __mul__(a, b) | a * b | | __neg__(a) | -a | | __nonzero__(a) | a != 0 | | __pos__(a) | +a: Coerces a subclass instance to Fraction | | __pow__(a, b) | a ** b | | If b is not an integer, the result will be a float or complex | since roots are generally irrational. If b is an integer, the | result will be rational. | | __radd__(b, a) | a + b | | __rdiv__(b, a) | a / b | | __reduce__(self) | | __rfloordiv__(b, a) | a // b | | __rmod__(b, a) | a % b | | __rmul__(b, a) | a * b | | __rpow__(b, a) | a ** b | | __rsub__(b, a) | a - b | | __rtruediv__(b, a) | a / b | | __sub__(a, b) | a - b | | __truediv__(a, b) | a / b | | __trunc__(a) | trunc(a) | | limit_denominator(self, max_denominator=1000000) | Closest Fraction to self with denominator at most max_denominator. | | >>> Fraction('3.141592653589793').limit_denominator(10) | Fraction(22, 7) | >>> Fraction('3.141592653589793').limit_denominator(100) | Fraction(311, 99) | >>> Fraction(4321, 8765).limit_denominator(10000) | Fraction(4321, 8765) | | ---------------------------------------------------------------------- | Class methods inherited from fractions.Fraction: | | from_decimal(cls, dec) from abc.ABCMeta | Converts a finite Decimal instance to a rational number, exactly. | | from_float(cls, f) from abc.ABCMeta | Converts a finite float to a rational number, exactly. | | Beware that Fraction.from_float(0.3) != Fraction(3, 10). | | ---------------------------------------------------------------------- | Static methods inherited from fractions.Fraction: | | __new__(cls, numerator=0, denominator=None) | Constructs a Fraction. | | Takes a string like '3/2' or '1.5', another Rational instance, a | numerator/denominator pair, or a float. | | Examples | -------- | | >>> Fraction(10, -8) | Fraction(-5, 4) | >>> Fraction(Fraction(1, 7), 5) | Fraction(1, 35) | >>> Fraction(Fraction(1, 7), Fraction(2, 3)) | Fraction(3, 14) | >>> Fraction('314') | Fraction(314, 1) | >>> Fraction('-35/4') | Fraction(-35, 4) | >>> Fraction('3.1415') # conversion from numeric string | Fraction(6283, 2000) | >>> Fraction('-47e-2') # string may include a decimal exponent | Fraction(-47, 100) | >>> Fraction(1.47) # direct construction from float (exact conversion) | Fraction(6620291452234629, 4503599627370496) | >>> Fraction(2.25) | Fraction(9, 4) | >>> Fraction(Decimal('1.47')) | Fraction(147, 100) | | ---------------------------------------------------------------------- | Data descriptors inherited from fractions.Fraction: | | denominator | | numerator | | ---------------------------------------------------------------------- | Methods inherited from numbers.Rational: | | __float__(self) | float(self) = self.numerator / self.denominator | | It's important that this conversion use the integer's "true" | division rather than casting one side to float before dividing | so that ratios of huge integers convert without overflowing. | | ---------------------------------------------------------------------- | Methods inherited from numbers.Real: | | __complex__(self) | complex(self) == complex(float(self), 0) | | __divmod__(self, other) | divmod(self, other): The pair (self // other, self % other). | | Sometimes this can be computed faster than the pair of | operations. | | __rdivmod__(self, other) | divmod(other, self): The pair (self // other, self % other). | | Sometimes this can be computed faster than the pair of | operations. | | conjugate(self) | Conjugate is a no-op for Reals. | | ---------------------------------------------------------------------- | Data descriptors inherited from numbers.Real: | | imag | Real numbers have no imaginary component. | | real | Real numbers are their real component. | | ---------------------------------------------------------------------- | Methods inherited from numbers.Complex: | | __ne__(self, other) | self != other | | ---------------------------------------------------------------------- | Data and other attributes inherited from numbers.Number: | | __metaclass__ = | Metaclass for defining Abstract Base Classes (ABCs). | | Use this metaclass to create an ABC. An ABC can be subclassed | directly, and then acts as a mix-in class. You can also register | unrelated concrete classes (even built-in classes) and unrelated | ABCs as 'virtual subclasses' -- these and their descendants will | be considered subclasses of the registering ABC by the built-in | issubclass() function, but the registering ABC won't show up in | their MRO (Method Resolution Order) nor will method | implementations defined by the registering ABC be callable (not | even via super()). class Matrix(__builtin__.object) | A class to represent matrices of size ``(n, m)``. | | ``M = Matrix(listrows)`` will have three attributes: | | - :py:data:`M.listrows` list of rows vectors (as list), | - :py:data:`M.n` or :py:data:`M.rows` number of rows, | - :py:data:`M.` or :py:data:`M.cols` number of columns (ie. length of the rows). | | All the required special methods are implemented, so :class:`Matrix` objects can be used as numbers, with a very natural syntax. | | .. warning:: All the rows should have the same size. | | Methods defined here: | | __abs__(self) | ``abs(A)`` <-> ``A.abs()`` <-> ``A.__abs__()`` computes the absolute value / modulus of ``A`` coefficient-wise. | | >>> A = Matrix([[-4, 2+2j], [0, 4j]]) | >>> abs(A) # doctest: +ELLIPSIS | [[4, 2.828427...], [0, 4.0]] | >>> B = -eye(2) | >>> B.abs() | [[1, 0], [0, 1]] | | __add__(self, B) | ``A + B`` <-> ``A.__add__(B)`` computes the sum of the matrix ``A`` and ``B``. | | - Returns a new matrix! | - Time and memory complexity is :math:`\mathcal{O}(n m)` for matrices of size ``(n, m)``. | - If ``B`` is a number, the sum is done coefficient wise. | | >>> A = Matrix([[1, 2, 3], [4, 5, 6]]) | >>> A + A | [[2, 4, 6], [8, 10, 12]] | >>> B = ones(A.n, A.m); B | [[1, 1, 1], [1, 1, 1]] | >>> A + B | [[2, 3, 4], [5, 6, 7]] | >>> B + A | [[2, 3, 4], [5, 6, 7]] | >>> B + B + B + B + B + B + B | [[7, 7, 7], [7, 7, 7]] | >>> B + 4 # Coefficient wise! | [[5, 5, 5], [5, 5, 5]] | >>> B + (-2) # Coefficient wise! | [[-1, -1, -1], [-1, -1, -1]] | >>> B + (-1.0) # Coefficient wise! | [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]] | | __contains__(self, value) | ``value in A`` <-> ``A.__contains__(value)`` tells if the element ``value`` is present in the matrix ``A``. | | >>> 4 in Matrix([[1, 2], [3, 4]]) | True | >>> 4 in Matrix([[1, 2], [1, 2]]) | False | >>> O, I = zeros(7), eye(7) | >>> 3 * I**2 + 2 * I + O ** 0 | [[6, 0, 0, 0, 0, 0, 0], [0, 6, 0, 0, 0, 0, 0], [0, 0, 6, 0, 0, 0, 0], [0, 0, 0, 6, 0, 0, 0], [0, 0, 0, 0, 6, 0, 0], [0, 0, 0, 0, 0, 6, 0], [0, 0, 0, 0, 0, 0, 6]] | >>> 6 in (3 * I**2 + 2 * I + O ** 0) | True | | __div__(self, B) | ``A / B`` <-> ``A * (B ** (-1))`` computes the division of the matrix ``A`` by ``B``. | | - Returns a new matrix! | - Performs **true division**! | - Time and memory complexity is :math:`\mathcal{O}(n m p \max(m, p)^2)` for a matrix ``A`` of size ``(n, m)`` and ``B`` of size ``(m, p)``. | - If ``B`` is a number, the division is done coefficient wise. | | >>> A = Matrix([[1, 2], [3, 4]]) | >>> B = eye(A.n) | >>> B.almosteq(A / A) | True | >>> C = B.map(float) | >>> A / C == A * C == A | True | >>> A / B == A * B == A | True | >>> A / 2 # Coefficient wise! | [[0.5, 1.0], [1.5, 2.0]] | >>> A / 2.0 # Coefficient wise! | [[0.5, 1.0], [1.5, 2.0]] | | __eq__(self, B) | ``A == B`` <-> ``A.__eq__(B)`` compares the matrix ``A`` with ``B``. | | - Time complexity is :math:`\mathcal{O}(n m)` for matrices of size ``(n, m)``. | | >>> B = Matrix([[1, 4], [2, 5], [3, 6]]) | >>> B == B | True | >>> B + B + B == 3*B == B + 2*B == 2*B + B | True | >>> B - B + B == 1*B == -B + 2*B == 2*B - B == 2*B + (-B) | True | >>> B != B | False | | __floordiv__(self, B) | ``A // B`` <-> ``A * (B ** (-1))`` computes the division of the matrix ``A`` by ``B``. | | - Returns a new matrix! | - Time and memory complexity is :math:`\mathcal{O}(n m p)` for a matrix ``A`` of size ``(n, m)`` and ``B`` of size ``(m, p)``. | - If ``B`` is a number, the division is done coefficient wise with an **integer division** ``//``. | | >>> A = Matrix([[1, 2], [3, 4]]) | >>> B = eye(A.n); C = B.map(float) | >>> A // C == A * C == A | True | >>> A // B == A * B == A | True | >>> A // 2 # Coefficient wise! | [[0, 1], [1, 2]] | >>> A // 2.0 # Coefficient wise! | [[0.0, 1.0], [1.0, 2.0]] | | __getitem__(self, ij) | ``A[i, j]`` <-> ``A.listrows[i][j]`` reads the (``i, j``) element of the matrix ``A``. | | - *Experimental* support of slices: ``A[a:b:k, j]``, or ``A[i, c:d:l]`` or ``A[a:b:k, c:d:l]``. | - Default values for ``a`` and ``c`` is a **start point** of ``0``, ``b`` and ``d`` is a **end point** of maximum size, and ``k`` and ``l`` is a **step** of ``1``. | | >>> A = Matrix([[1, 2, 3], [4, 5, 6]]) | >>> A[0, 0] | 1 | >>> A[0, :] | [[1, 2, 3]] | >>> A[-1, :] | [[4, 5, 6]] | >>> A[:, 0] | [[1], [4]] | >>> A[1:, 1:] | [[5, 6]] | >>> A[:, ::2] | [[1, 3], [4, 6]] | | __init__(self, listrows) | Create a :class:`Matrix` object from the list of row vectors ``M``. | | >>> A = Matrix([[1, 2, 3], [4, 5, 6]]) | >>> A.listrows | [[1, 2, 3], [4, 5, 6]] | | __iter__(self) | ``iter(A)`` <-> ``A.__iter__()`` is used to create an iterator from the matrix ``A``. | | - The values are looped rows by rows, then columns then columns. | - This method is called when an iterator is required for a container. This method should return a new iterator object that can iterate over all the objects in the container. | | >>> A = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) | >>> list(A) | [1, 2, 3, 4, 5, 6, 7, 8, 9] | | __len__(self) | ``len(A)`` returns ``A.n * A.m``, the number of values in the matrix. | | >>> A = Matrix([[1, 2, 3], [4, 5, 6]]) | >>> len(A) | 6 | >>> len(A) == A.n * A.m | True | | __lt__(self, B) | ``A < B`` <-> :math:`A_{i,j} < B_{i,j} \forall i,j` compares the matrix ``A`` with ``B``. | | - Time complexity is :math:`\mathcal{O}(n m)` for matrices of size ``(n, m)``. | - Time complexity is :math:`\mathcal{O}(n m)` for matrices of size ``(n, m)``. | - ``A > B``, ``A <= B``, ``A >= B`` are all computed automatically with :py:meth:`__eq__` and :py:meth:`__lt__`. | | >>> B = Matrix([[1, 4], [2, 5], [3, 6]]) | >>> B < B | False | >>> B < B + 4 | True | >>> B > B | False | >>> B > B - 12 | True | | __mod__(self, b) | ``A % b`` <-> ``A.__mod__(b)`` computes the modulus coefficient-wise of the matrix ``A`` by ``b``. | | - Returns a new matrix! | - Time and memory complexity is :math:`\mathcal{O}(n m)` for a matrix ``A`` of size ``(n, m)``. | | >>> A = Matrix([[1, 2], [3, 4]]) | >>> A % 2 | [[1, 0], [1, 0]] | >>> (A*100) % 31 | [[7, 14], [21, 28]] | >>> (A*100) % 33 == A # Curious property | True | >>> (A*100) % 35 | [[30, 25], [20, 15]] | | .. warning:: ``A % B`` for two matrices means the coefficient-wise modulus. | | >>> A = Matrix([[1, 2], [3, 4]]) | >>> B = Matrix([[2, 3], [2, 2]]) | >>> A % B | [[1, 2], [1, 0]] | | __mul__(self, B) | ``A * B`` <-> ``A.__mul__(B)`` computes the product of the matrix ``A`` and ``B``. | | - Returns a new matrix! | - Time and memory complexity is :math:`\mathcal{O}(n m p)` for a matrix ``A`` of size ``(n, m)`` and ``B`` of size ``(m, p)``. | - If ``B`` is a number, the product is done coefficient wise. | | .. warning:: Matrix product is not commutative! | | >>> A = Matrix([[1, 2], [3, 4]]) | >>> B = eye(A.n); B | [[1, 0], [0, 1]] | >>> A * B == B * A == A | True | >>> A * A | [[7, 10], [15, 22]] | >>> A * (A * A) == (A * A) * A | True | >>> A * 1 == A # Coefficient wise! | True | >>> A * 12.011993 # Coefficient wise! | [[12.011993, 24.023986], [36.035979, 48.047972]] | | __neg__(self) | ``-A`` <-> ``A.__neg__()`` computes the opposite of the matrix ``A``. | | - Returns a new matrix! | - Time and memory complexity is :math:`\mathcal{O}(n m)` for a matrix of size ``(n, m)``. | | >>> A = Matrix([[1, 2, 3], [4, 5, 6]]) | >>> -A | [[-1, -2, -3], [-4, -5, -6]] | >>> A - A == A + (-A) | True | >>> -(-A) == A | True | >>> -------A == -A # Crazy syntax! | True | >>> s = '-------' | >>> len(s) % 2 == 1 # We check that we had an od number of minus symbol | True | | __next__(self) | For Python 3 compatibility. | | __pos__(self) | ``+`` <-> ``A.__pos__()`` computes the positive of the matrix A. | | - Returns a new matrix! | - Useless? | - Time and memory complexity is :math:`\mathcal{O}(n m)` for a matrix of size ``(n, m)``. | | >>> A = Matrix([[1, 2, 3], [4, 5, 6]]) | >>> +A == A | True | >>> +-+-+-+-+++----+-+-+----++++A == A # Crazy syntax, again! | True | >>> s = '+-+-+-+-+++----+-+-+----++++' | >>> s.count('-') % 2 == 0 # We check that we had an even number of minus symbol | True | | __pow__(self, k) | ``A ** k`` <-> ``A.__pow__(k)`` to compute the product of the square matrix ``A`` (with the quick exponentation trick). | | - Returns a new matrix! | - ``k`` has to be an integer (``ValueError`` will be returned otherwise). | - Time complexity is :math:`\mathcal{O}(n^3 \log(k))` for a matrix ``A`` of size (n, n). | - Memory complexity is :math:`\mathcal{O}(n^2)`. | - It uses ``A.inv()`` (:py:meth:`inv`) to (try to) compute the inverse if ``k < 0``. | - More details are in `the solution for the Problem II of the 2nd Mid-Term Exam for CS101 `_. | | >>> A = Matrix([[1, 2], [3, 4]]) | >>> A ** 1 == A | True | >>> A ** 2 | [[7, 10], [15, 22]] | >>> A * A == A ** 2 | True | >>> B = eye(A.n) | >>> B == B ** 1 == A ** 0 == B ** 0 | True | >>> divmod(2015, 2) | (1007, 1) | >>> 2015 == 1007*2 + 1 | True | >>> A ** 2015 == ((A ** 1007) ** 2 ) * A | True | >>> C = diag([1, 4]) | >>> C ** 100 | [[1, 0], [0, 1606938044258990275541962092341162602522202993782792835301376]] | >>> C ** 100 == diag([1**100, 4**100]) | True | | It also accept negative integers: | | >>> A ** (-1) == A.inv() | True | >>> C = (A ** (-1)); C | [[-2.0, 1.0], [1.5, -0.5]] | >>> C * A == eye(A.n) == A * C | True | >>> C.listrows # Rounding mistakes can happen (but not here) | [[-2.0, 1.0], [1.5, -0.5]] | >>> D = C.round(); D.listrows | [[-2.0, 1.0], [1.5, -0.5]] | >>> D * A == eye(A.n) == A * D # No rounding mistake! | True | >>> (C * A).almosteq(eye(A.n)) | True | >>> (A ** (-5)) == (A ** 5).inv() == (A.inv()) ** 5 | False | >>> (A ** (-5)).round() == ((A ** 5).inv()).round() == ((A.inv()) ** 5).round() # No rounding mistake! | True | | __radd__(self, B) | ``B + A`` <-> ``A.__radd__(B)`` computes the sum of ``B`` and the matrix ``A``. | | - Returns a new matrix! | - Time and memory complexity is :math:`\mathcal{O}(n m)` for matrices of size ``(n, m)``. | - If ``B`` is a number, the sum is done coefficient wise. | | >>> A = Matrix([[1, 2, 3], [4, 5, 6]]) | >>> 1 + A | [[2, 3, 4], [5, 6, 7]] | >>> B = ones(A.n, A.m) | >>> 4 + B # Coefficient wise! | [[5, 5, 5], [5, 5, 5]] | >>> (-2) + B # Coefficient wise! | [[-1, -1, -1], [-1, -1, -1]] | >>> (-1.0) + B # Coefficient wise! | [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]] | | __rdiv__(self, B) | ``B / A`` <-> ``A.__rdiv__(B)`` computes the division of ``B`` by ``A``. | | .. warning:: If ``B`` is ``1`` (``B == 1``), ``1 / A`` is ``A.inv()`` (special case!) | | - If ``B`` is a number, the division is done coefficient wise. | - Returns a new matrix! | - Time and memory complexity is :math:`\mathcal{O}(n m p)` for a matrix ``A`` of size ``(n, m)`` and ``B`` of size ``(m, p)``. | | >>> A = Matrix([[1, 2], [3, 4]]) | >>> Ainv = Matrix([[-2.0, 1.0], [1.5, -0.5]]) | >>> B = eye(A.n) | >>> B == A * Ainv == Ainv * A | True | >>> 1 / B == B == B / 1 | True | >>> C = B.map(float) | >>> 1 / B == B == B / 1 | True | >>> A.inv() == 1 / A # special case! | True | >>> 1 / A # This is like 1 / A | [[-2.0, 1.0], [1.5, -0.5]] | >>> 2 / (2*A) # Warning This is coefficient wise ! # doctest: +ELLIPSIS | [[1.0, 0.5], [0.333333..., 0.25]] | | __repr__(self) | ``repr(A)`` <-> ``A.__repr__()`` converts the matrix A to a string (showing the list of rows vectors). | | >>> B = Matrix([[1, 4], [2, 5], [3, 6]]) | >>> repr(B) | '[[1, 4], [2, 5], [3, 6]]' | | __rfloordiv__(self, B) | ``B // A`` <-> ``A.__rdiv__(B)`` computes the division of ``B`` by ``A``. | | .. warning:: If ``B`` is ``1`` (``B == 1``), ``1 / A`` is ``A.inv()`` (special case!) | | - If ``B`` is a number, the division is done coefficient wise. | - Returns a new matrix! | - Time and memory complexity is :math:`\mathcal{O}(n m p)` for a matrix ``A`` of size ``(n, m)`` and ``B`` of size ``(m, p)``. | | >>> A = Matrix([[1, 2], [3, 4]]) | >>> B = eye(A.n) | >>> 1 // B == B == B // 1 | True | >>> C = B.map(float) | >>> 1 // B == B == B // 1 | True | >>> A.inv() == 1 // A # special case! | True | >>> 2 // (2*A) # XXX This is coefficient wise ! | [[1, 0], [0, 0]] | | __rmul__(self, B) | ``B * A`` <-> ``A.__rmul__(B)`` computes the product of ``B`` and the matrix ``A``. | | - Returns a new matrix! | - Time and memory complexity is :math:`\mathcal{O}(n m p)` for a matrix ``A`` of size ``(n, m)`` and ``B`` of size ``(m, p)``. | - If B is a number, the product is done coefficient wise. | - If ``B`` is a :class:`Matrix` object, ``B * A`` will in fact be ``B.__mul__(A)`` and not ``A.__rmul__(B)``. | | .. warning:: Matrix product is not commutative! | | >>> A = Matrix([[1, 2], [3, 4]]) | >>> 1 * A == A # Coefficient wise! | True | >>> 12.011993 * A # Coefficient wise! | [[12.011993, 24.023986], [36.035979, 48.047972]] | | __rsub__(self, B) | ``B - A`` <-> ``A.__rsub__(B)`` computes the difference of ``B`` and the matrix ``A``. | | - Returns a new matrix! | - Time and memory complexity is :math:`\mathcal{O}(n m)` for matrices of size ``(n, m)``. | - If ``B`` is a number, the sum is done coefficient wise. | - If ``B`` is a :class:`Matrix` object, ``B - A`` will in fact be ``B.__sub__(A)`` and not ``A.__rsub__(B)``. | | >>> A = Matrix([[1, 2, 3], [4, 5, 6]]) | >>> 1 - A # Coefficient wise! | [[0, -1, -2], [-3, -4, -5]] | >>> B = ones(A.n, A.m) | >>> (-1) - B # Coefficient wise! | [[-2, -2, -2], [-2, -2, -2]] | >>> ((-1) - B) == -(1 + B) == -(B + B) | True | | __rtruediv__ = __rdiv__(self, B) | | __setitem__(self, ij, value) | ``A[i, j] = value``: will update the ``(i, j)`` element of the matrix ``A``. | | - Support for slice arguments: ``A[a:b:k, j] = sub_row``, or ``A[i, c:d:l] = sub_column`` or ``A[a:b:k, c:d:l] = submatrix``. | - Default values for ``a`` and ``c`` is a **start point** of ``0``, ``b`` and ``d`` is a **end point** of maximum size, and ``k`` and ``l`` is a **step** of ``1``. | | >>> A = Matrix([[1, 2, 3], [4, 5, 6]]) | >>> A[0, 0] = 4; A | [[4, 2, 3], [4, 5, 6]] | >>> A[:, 0] | [[4], [4]] | >>> A[-1, :] = 9; A | [[4, 2, 3], [9, 9, 9]] | >>> A[1, 1] = 3; A | [[4, 2, 3], [9, 3, 9]] | >>> A[0, :] = [3, 2, 1]; A | [[3, 2, 1], [9, 3, 9]] | >>> A[1:, 1:] = -1; A | [[3, 2, 1], [9, -1, -1]] | >>> A[1:, 1:] *= -8; A | [[3, 2, 1], [9, 8, 8]] | | __str__(self) | ``str(A)`` <-> ``A.__str__()`` converts the matrix ``A`` to a string (showing the list of rows vectors). | | >>> B = Matrix([[1, 4], [2, 5], [3, 6]]) | >>> str(B) | '[[1, 4], [2, 5], [3, 6]]' | | __sub__(self, B) | ``A - B`` <-> ``A.__sub__(B)`` computes the difference of the matrix ``A`` and ``B``. | | - Returns a new matrix! | - Time and memory complexity is :math:`\mathcal{O}(n m)` for matrices of size ``(n, m)``. | - If ``B`` is a number, the sum is done coefficient wise. | | >>> A = Matrix([[1, 2, 3], [4, 5, 6]]) | >>> B = ones(A.n, A.m) | >>> A - B | [[0, 1, 2], [3, 4, 5]] | >>> B - A | [[0, -1, -2], [-3, -4, -5]] | >>> A - 1 # Coefficient wise! | [[0, 1, 2], [3, 4, 5]] | >>> B - 2 # Coefficient wise! | [[-1, -1, -1], [-1, -1, -1]] | >>> (A - 3.14).round() # Coefficient wise! | [[-2.14, -1.14, -0.14], [0.86, 1.86, 2.86]] | | __truediv__ = __div__(self, B) | | abs = __abs__(self) | | adjugate(self) | ``A.adjugate()`` <-> ``adjugate(A)`` returns the **adjugate matrix** of ``A``. | | - Reference is https://en.wikipedia.org/wiki/Adjugate_matrix#Inverses. | - Complexities: memory is :math:`\mathcal{O}(n^2)`, time is :math:`\mathcal{O}(n^5)` (:math:`n^2` determinants of size ``n - 1``). | - Using the adjugate matrix for computing the inverse is a BAD method : too time-consuming ! LU or Gauss-elimination is only :math:`\mathcal{O}(n^3)`. | | >>> A = Matrix([[2, 0], [3, 4]]) | >>> A.adjugate() | [[4, -3], [0, 2]] | >>> A * A.adjugate() == A.det * eye(A.n) | False | >>> A * A.adjugate().T == A.det * eye(A.n) | True | | almosteq(self, B, epsilon=1e-10) | ``A.almosteq(B)`` compares the matrix ``A`` with ``B``, numerically with an error threshold of ``epsilon``. | | - Default epsilon is :math:`10^{-10}`. | - Time complexity is :math:`\mathcal{O}(n m)` for matrices of size ``(n, m)``. | | >>> B = Matrix([[1, 4], [2, 5], [3, 6]]) | >>> C = B.copy(); C[0,0] += 4*1e-6 | >>> B == C | False | >>> B.almosteq(C) | False | >>> B.almosteq(C, epsilon=1e-4) | True | >>> B.almosteq(C, epsilon=1e-5) | True | >>> B.almosteq(C, epsilon=1e-6) | False | | cofactor(self, i, j) | ``A.cofactor(i, j)`` <-> ``cofactor(A, i, j)`` returns the ``(i, j)`` cofactor of ``A``, defined as the ``(-1)**(i + j)`` times to ``(i, j)`` minor of ``A`` (cf. :py:meth:`minor`). | | - Complexities: memory is :math:`\mathcal{O}(n^2)`, time is :math:`\mathcal{O}(n^3)` (1 determinant of size ``n - 1``). | | >>> A = Matrix([[1, 2], [3, 4]]) | >>> A.cofactor(0, 0) | 4 | >>> A = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) | >>> A.cofactor(0, 0) # (-1)**0 * | 5 6 8 9 | = 5 * 9 - 6 * 8 = -3 | -3.000000000000007 | >>> A.cofactor(1, 0) # (-1)**1 * | 2 3 8 9 | = -(2 * 9 - 3 * 8) = 6 | 6 | | col(self, j) | ``A.col(j)`` <-> *extracts* the ``j``-th column of ``A``, as a new matrix. | | .. warning:: Modifying ``A.col(j)`` does NOT modify the matrix A. | | >>> A = Matrix([[1, 2, 3], [4, 5, 6]]) | >>> A.col(0) | [[1], [4]] | >>> A.col(2) | [[3], [6]] | >>> c = A.col(1); c *= 6 | >>> A # it has not been modified! | [[1, 2, 3], [4, 5, 6]] | | conjugate(self) | Conjugate part of the matrix ``A``, coefficient wise. | | >>> A = Matrix([[-1j, -2j], [-2j, -1j]]) | >>> A.conjugate() | [[1j, 2j], [2j, 1j]] | | copy(self) | ``A.copy()`` <-> a shallow copy of the matrix ``A`` (ie. a new and fresh matrix with same values). | | >>> A = Matrix([[1, 2, 3], [4, 5, 6]]) | >>> B = A.copy() | >>> A[0, 0] = -10; A | [[-10, 2, 3], [4, 5, 6]] | >>> B # It has not been modified! | [[1, 2, 3], [4, 5, 6]] | | count(self, value) | ``A.count(value)`` counts how many times the element ``value`` is in the matrix ``A``. | | >>> Matrix([[1, 2], [3, 4]]).count(2) | 1 | >>> Matrix([[1, 2], [1, 2]]).count(2) | 2 | >>> zeros(7).count(2) | 0 | >>> zeros(7).count(0) | 49 | >>> eye(19).count(1) | 19 | >>> eye(19).count(0) | 342 | | dot(self, v) | ``A.dot(v)`` computes the dot multiplication of the matrix ``A`` and the vector ``v`` (:math:`A \dot v`). | | - ``v`` can be a matrix (:class:`Matrix`) of size ``(m, 1)``, or a list of size ``m``. | | >>> A = Matrix([[1, 1], [1, -1]]) | >>> v = [2, 3] | >>> A.dot(v) | [[5], [-1]] | >>> v = Matrix([[2], [-3]]) | >>> A.dot(v) | [[-1], [5]] | | .. warning:: An exception ``ValueError`` is raised if the sizes does not allow the dot product: | | >>> A.dot(v.T) # v.T is not a column vector! | Traceback (most recent call last): | ... | ValueError: A.dot(v): the vector v = [[2, -3]] is not a vector: v.m = 2 != 1. | >>> v = Matrix([[2], [-3], [7]]) | >>> A.dot(v) | Traceback (most recent call last): | ... | ValueError: A.dot(v): the size of the vector v = [[2], [-3], [7]] should be compatible with the size of the matrix self = [[1, 1], [1, -1]]. Here self.m = 2 and v.n = 3, are different. | >>> v = [1, 2, 3, 4, 5] | >>> A.dot(v) | Traceback (most recent call last): | ... | ValueError: A.dot(v): the size of the vector v = [[1], [2], [3], [4], [5]] should be compatible with the size of the matrix self = [[1, 1], [1, -1]]. Here self.m = 2 and v.n = 5, are different. | | exp(self, limit=30) | ``A.exp()`` computes a numerical approximation of the exponential of the square matrix ``A``. | | - Raise a ValueError exception if ``A`` is not square. | - Note: :math:`\exp(A) = \mathrm{e}^A` is defined as the series :math:`\sum\limits_{k=0}^{+\infty} \frac{A^k}{k!}`. | - We only compute the first ``limit`` terms of this series, hopping that the partial sum will be close to the entire series. | - Default value for ``limit`` is 30 (it should be enough for any matrix). | | >>> import math | >>> e = math.e | >>> I = eye(10); I[0, :] | [[1, 0, 0, 0, 0, 0, 0, 0, 0, 0]] | >>> I * e == I.exp() == diag([e] * I.n) # Rounding mistakes! | False | >>> (I * e).round() == I.exp().round() == diag([e] * I.n).round() # No more rounding mistakes! | True | >>> C = diag([1, 4]) | >>> C.exp() == diag([e ** 1, e ** 4]) == diag([math.exp(1), math.exp(4)]) # Rounding mistakes! | False | >>> C.exp().almosteq(diag([e ** 1, e ** 4])) # No more rounding mistakes! | True | >>> diag([e ** 1, e ** 4]).almosteq(diag([math.exp(1), math.exp(4)])) | True | | gauss(self, det=False, verb=False, mode=None, maxpivot=False) | ``A.gauss()`` implements the Gauss elimination process on matrix ``A``. | | When possible, the Gauss elimination process produces a row echelon form by applying linear operations to ``A``. | | - If ``maxpivot`` is True, we look for the pivot with higher absolute value (can help reducing rounding mistakes). | - If ``verb`` is True, some details are printed at each steps of the algorithm. | - ``mode`` can be ``None`` (default), or ``'f'`` for fractions (:class:`Fraction`) or ``'d'`` for decimal numbers (:class:`Decimal`). | | - Reference is https://en.wikipedia.org/wiki/Gaussian_elimination#Definitions_and_example_of_algorithm | - We chosed to apply rows operations only: it uses elementary operations on lines/rows: :math:`L_i' \longrightarrow L_i - \gamma \times L_k` (method :py:meth:`swap_rows`). | - Can swap two columns in order to select the bigger pivot (increases the numerical stability). | - The function will raise a ``ValueError`` if the matrix ``A`` is singular (ie. Gauss process cannot conclude). | - If ``det`` is ``True``, the returned value is ``c, d`` with ``c`` the row echelon form, and ``d`` the determinant. Reference for this part is `this wikipedia page `_. | | >>> Matrix([[1, 2], [3, 4]]).gauss() | [[1, 2], [0, -2]] | >>> Matrix([[1, 2], [1, 2]]).gauss() | [[1, 2], [0, 0]] | >>> Matrix([[1, 2], [-1, -0.5]]).gauss() | [[1, 2], [0, 1.5]] | >>> Matrix([[1, 2], [3, 4]]).gauss(maxpivot=True) | [[2, 1], [0, 1]] | >>> Matrix([[1, 2], [1, 2]]).gauss(maxpivot=True) | [[2, 1], [0, 0]] | >>> Matrix([[1, 2], [3, 4]]).gauss(det=True) | ([[1, 2], [0, -2]], -2) | >>> Matrix([[1, 2], [1, 2]]).gauss(det=True) | ([[1, 2], [0, 0]], 0) | | gauss_jordan(self, inv=False, verb=False, mode=None, maxpivot=False) | ``A.gauss_jordan()`` implements the Gauss elimination process on matrix ``A``. | | - If ``inv`` is ``True``, the returned value is ``J_n, A**(-1)`` with ``J_n`` the reduced row echelon form of ``A``, and ``A**(-1)`` the computed inverse of A. | - If ``maxpivot`` is ``True``, we look for the pivot with higher absolute value (can help reducing rounding mistakes). | | inv(self) | ``A.inv()`` computes the inverse of the square matrix ``A`` (if possible), with the Gauss-Jordan algorithm. | | - Raise a ``ValueError`` exception if ``A`` is not square. | - Raise a ``ValueError`` exception if ``A`` is singular. | | >>> A = Matrix([[1, 2], [3, 4]]) | >>> A.inv() | [[-2.0, 1.0], [1.5, -0.5]] | >>> A * A.inv() == A.inv() * A == eye(A.n) # Rounding mistake can happen (but not here) | True | >>> Ai = A.inv().round() # No more rounding mistake! | >>> A * Ai == Ai * A == eye(A.n) | True | >>> A.det | -2 | >>> O = Matrix([[1, 2], [0, 0]]) # O and not 0 | >>> O.is_singular | True | >>> O.inv() # O is singular! | Traceback (most recent call last): | ... | ValueError: A.inv() on a singular matrix (ie. non inversible). | >>> O.det | 0 | | map(self, f, *args, **kwargs) | Apply the function ``f`` to each of the coefficient of the matrix ``A`` (returns a new matrix). | | >>> O, I = zeros(2), eye(2) | >>> I.map(lambda x: x * 4) | [[4, 0], [0, 4]] | >>> O.map(lambda x: x + 6) | [[6, 6], [6, 6]] | >>> A = Matrix([[-1j, -2j], [-2j, -1j]]) | >>> A.map(lambda z: abs(z)) | [[1.0, 2.0], [2.0, 1.0]] | >>> A.map(lambda z: int(abs(z))) | [[1, 2], [2, 1]] | >>> A.map(lambda z: z + 1j) | [[0j, -1j], [-1j, 0j]] | >>> A.map(lambda z: '"%s"' % str(z)) | [["-1j", "-2j"], ["-2j", "-1j"]] | >>> A.map(lambda z: "Look: %s" % str(z)) | [[Look: -1j, Look: -2j], [Look: -2j, Look: -1j]] | | | - If ``f`` needs arguments or key-words arguments, use the ``*args`` and ``**kwargs`` : | | >>> def f(x, n, offset=0): | ... return (x ** n) + offset | >>> A = Matrix([[1, 2], [2, 1]]) | >>> A.map(f, 2) | [[1, 4], [4, 1]] | >>> A.map(f, 2, offset=4) | [[5, 8], [8, 5]] | | minor(self, i, j) | ``A.minor(i, j)`` <-> ``minor(A, i, j)`` returns the ``(i, j)`` minor of ``A``, defined as the determinant of the submatrix ``A[i0, j0]`` for ``i0 != i`` and ``j0 != j``. | | - Complexities: memory is :math:`\mathcal{O}(n^2)`, time is :math:`\mathcal{O}(n^3)` (1 determinant of size ``n - 1``). | | >>> A = Matrix([[1, 2], [3, 4]]) | >>> A.minor(0, 0) | 4 | >>> A = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) | >>> A.minor(0, 0) # | 5 6 8 9 | = 5 * 9 - 6 * 8 = -3 | -3.000000000000007 | >>> A.minor(1, 0) # | 2 3 8 9 | = 2 * 9 - 3 * 8 = -6 | -6 | | multiply_elementwise(self, B) | ``A.multiply_elementwise(B)`` computes the product of the matrix ``A`` and ``B``, element-wise (it is called a **Hadamard product**). | | - Returns a new matrix! | - Time and memory complexity is :math:`\mathcal{O}(n m p)` for a matrix ``A`` of size ``(n, m)`` and ``B`` of size ``(m, p)``. | | >>> A = Matrix([[1, 2], [3, 4]]) | >>> B = eye(A.n) | >>> A.multiply_elementwise(B) | [[1, 0], [0, 4]] | >>> A.multiply_elementwise(A) # A .^ 2 in Matlab? | [[1, 4], [9, 16]] | | next(self) | Generator for iterating the matrix ``A``. | | - The values are looped rows by rows, then columns then columns. | | >>> A = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) | >>> for x in A: | ... print(x) | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | >>> for i, x in enumerate(A): | ... print(i, "th value of A is", x) | 0 th value of A is 1 | 1 th value of A is 2 | 2 th value of A is 3 | 3 th value of A is 4 | 4 th value of A is 5 | 5 th value of A is 6 | 6 th value of A is 7 | 7 th value of A is 8 | 8 th value of A is 9 | | norm(self, p=2) | ``A.norm(p)`` computes the p-norm of the matrix ``A``, default is ``p = 2``. | | - Mathematically defined as p-root of the sum of the p-power of *modulus* of its coefficients : | | .. math:: \|A\|_{p} := \left( \sum\limits_{1 \leq i \leq n, 1 \leq j \leq m} {|A_{i,j}|}^p \right)^{\frac{1}{p}} | | - If ``p = 'inf'``, the max norm is returned (ie. infinity norm), defined by :math:`\|A\|_{\infty} := \max_{i,j} |A_{i,j}|`. | - Reference is `Matrix norm (on Wikipedia) `_. | | >>> A = Matrix([[1, 2], [-3, -1]]) | >>> A.norm() # (1)**2 + (2)**2 + (-3)**2 + (-1)**2 | 3.872983346207417 | >>> 15**0.5 | 3.872983346207417 | >>> A.norm('inf') | 3 | >>> A.norm(1) == 7 # (1) + (2) + (3) + (1) | True | >>> A.norm(3) | 3.332221851645953 | | normalized(self, fnorm=None, *args, **kwargs) | ``A.normalized()`` return a new matrix, which **columns vectors are normalized** by using the norm ``2`` (or the given function ``fnorm``). | | - Will **not fail** if a vector has norm ``0`` (it is just not modified). | - Reference is `Orthogonalization (on Wikipedia) `_. | - Any extra arguments ``args``, ``kwargs`` are given to the function ``fnorm``. | | >>> A = Matrix([[1, 2], [-3, -1]]) | >>> A.normalized(p='inf') # doctest: +ELLIPSIS | [[0.333333..., 1.0], [-1.0, -0.5]] | >>> eye(5).normalized(p='inf').map(int) # normalize then round to an int | [[1, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 1, 0], [0, 0, 0, 0, 1]] | >>> B = -eye(5) | >>> (2*B).normalized() # each vector is divided by its norm = 2 | [[-1.0, 0.0, 0.0, 0.0, 0.0], [0.0, -1.0, 0.0, 0.0, 0.0], [0.0, 0.0, -1.0, 0.0, 0.0], [0.0, 0.0, 0.0, -1.0, 0.0], [0.0, 0.0, 0.0, 0.0, -1.0]] | >>> B.normalized(p='inf') | [[-1.0, 0.0, 0.0, 0.0, 0.0], [0.0, -1.0, 0.0, 0.0, 0.0], [0.0, 0.0, -1.0, 0.0, 0.0], [0.0, 0.0, 0.0, -1.0, 0.0], [0.0, 0.0, 0.0, 0.0, -1.0]] | | It works also for a simple vector: | | >>> v = Matrix([[1], [-2], [3]]) | >>> v.normalized() # doctest: +ELLIPSIS | [[0.267261...], [-0.534522...], [0.801783...]] | >>> v.normalized(p=2) # doctest: +ELLIPSIS | [[0.267261...], [-0.534522...], [0.801783...]] | >>> v.normalized() * (14**0.5) | [[1.0], [-2.0], [3.0]] | >>> v.normalized(p=1) # doctest: +ELLIPSIS | [[0.166666...], [-0.333333...], [0.5]] | >>> v.normalized(p=1) * 6 | [[1.0], [-2.0], [3.0]] | >>> 6 * v.normalized(p=1) | [[1.0], [-2.0], [3.0]] | | round(self, ndigits=8) | ``A.round([ndigits=8])`` <-> rounds every coefficient of ``A`` to ``ndigits`` digits after the comma. | | >>> A = (1. / 3.) * eye(2) + 4 | >>> A.round(0) | [[4.0, 4.0], [4.0, 4.0]] | >>> A.round(2) | [[4.33, 4.0], [4.0, 4.33]] | >>> A.round(7) | [[4.3333333, 4.0], [4.0, 4.3333333]] | | row(self, i) | ``A.row(i)`` <-> *extracts* the ``i``-th row of ``A``, as a *new* matrix. | | .. warning:: Modifying ``A.row(i)`` does NOT modify the matrix ``A``. | | >>> A = Matrix([[1, 2, 3], [4, 5, 6]]) | >>> A.row(0) | [[1, 2, 3]] | >>> A.row(1) | [[4, 5, 6]] | >>> r = A.row(0); r *= 3 | >>> A # it has not been modified! | [[1, 2, 3], [4, 5, 6]] | | swap_cols(self, j1, j2) | ``A.swap_cols(j1, j2)`` changes *in place* the ``j1``-th and ``j2``-th *columns* of the matrix ``A``. | | >>> A = Matrix([[2, 0], [3, 4]]); A | [[2, 0], [3, 4]] | >>> A.swap_cols(0, 1); A | [[0, 2], [4, 3]] | | swap_rows(self, i1, i2) | ``A.swap_rows(i1, i2)`` changes *in place* the ``i1``-th and ``i2``-th *rows* of the matrix ``A``. | | >>> A = Matrix([[2, 0], [3, 4]]); A | [[2, 0], [3, 4]] | >>> A.swap_rows(0, 1); A | [[3, 4], [2, 0]] | | trace(self) | ``A.trace()`` computes the trace of ``A`` : | | .. math:: \mathrm{Tr}(A) := \sum\limits_{1 \leq i \leq \min(n, m)} A_{i, i} | | >>> A = Matrix([[-4, 2+2j], [0, 4j]]) | >>> A.trace() | (-4+4j) | >>> eye(19).trace() | 19 | >>> zeros(20).trace() | 0 | >>> ones(100).trace() | 100 | | transpose(self) | ``A.transpose()`` is the transposition of the matrix ``A``. | | - Returns a new matrix! | - Definition: if ``B = A.transpose()``, then ``B[i, j] is A[j, i]``. | | >>> A = Matrix([[1, 2, 3], [4, 5, 6]]) | >>> A.transpose() | [[1, 4], [2, 5], [3, 6]] | >>> A.transpose().transpose() == A | True | | type(self) | ``A.type()`` returns the matrix of types of coefficients of ``A``. | | ---------------------------------------------------------------------- | Data descriptors defined here: | | T | ``A.T`` <-> ``A.transpose()`` is the transposition of the matrix ``A``, useful shortcut as in NumPy. | | >>> B = Matrix([[1, 4], [2, 5], [3, 6]]) | >>> B.T | [[1, 2, 3], [4, 5, 6]] | >>> B == B.T.T | True | | __dict__ | dictionary for instance variables (if defined) | | __weakref__ | list of weak references to the object (if defined) | | cols | Getter for the read-only attribute ``A.m`` (size of the rows, ie. number of columns). | | >>> A = Matrix([[1, 2, 3], [4, 5, 6]]) | >>> A.m | 3 | >>> A.cols == A.m | True | | det | ``A.det`` uses the Gauss elimination process to compute the determinant of the matrix ``A``. | | .. note:: Because it depends of the number of elementary operations performed in the Gauss method, we had to modify the :py:meth:`gauss` method... | | >>> Matrix([[1, 2], [3, 4]]).det | -2 | >>> Matrix([[1, 2], [1, 2]]).det | 0 | >>> zeros(7).det | 0 | >>> eye(19).det | 1 | | imag | Imaginary part of the matrix ``A``, coefficient wise. | | >>> A = Matrix([[-1j, -2j], [-2j, -1j]]) | >>> A.imag | [[-1.0, -2.0], [-2.0, -1.0]] | | is_anti_symetric | ``A.is_anti_symetric`` tests if ``A`` is **anti-symetric** or not. | | >>> A = Matrix([[0, 1], [-1, 0]]) | >>> A.is_anti_symetric | True | >>> eye(30).is_anti_symetric | False | | is_diagonal | ``A.is_diagonal`` tests if A is **diagonal** or not. | | >>> eye(40).is_diagonal | True | >>> A = Matrix([[0, 1], [-1, 0]]) | >>> A.is_diagonal | False | >>> A = diag(range(30)) | >>> A.is_diagonal | True | | is_hermitian | ``A.is_hermitian`` tests if ``A`` is **Hermitian** or not (tests if :math:`A^{*} = A`, ie. ``conjugate(A.T) == A)``). | | >>> A = Matrix([[1, 2j], [-2j, 1]]) | >>> A.is_hermitian | True | >>> eye(30).is_hermitian | True | >>> (1j * ones(3)).is_hermitian | False | | is_lower | ``A.is_lower`` tests if ``A`` is **lower triangular** or not. | | >>> A = Matrix([[8, 1], [0, 7]]) | >>> A.is_lower | False | >>> A.T.is_lower | True | | is_singular | ``A.is_singular`` tests if ``A`` is **singular** (ie. non-invertible) or not. | | .. note:: It computes the determinant by using the Gauss elimination process (:py:meth:`det`). | | >>> A = Matrix([[2, 0], [3, 4]]) | >>> A.is_singular | False | >>> zeros(3).is_singular | True | >>> (0 * A).is_singular | True | >>> Matrix([[2, 0], [4, 0]]).is_singular | True | | is_square | ``A.is_square`` tests if ``A`` is **square** or not. | | >>> A = Matrix([[-4, 2+2j], [0, 4j]]) | >>> A.is_square | True | >>> v = Matrix([[-4], [0]]) | >>> v.is_square | False | | is_symetric | ``A.is_symetric`` tests if ``A`` is **symetric** or not. | | >>> A = Matrix([[-4, 2+2j], [0, 4j]]) | >>> A.is_symetric | False | >>> eye(30).is_symetric | True | | is_upper | ``A.is_upper`` tests if ``A`` is **upper triangular** or not. | | >>> A = Matrix([[2, 0], [3, 4]]) | >>> A.is_upper | False | >>> A.T.is_upper | True | | is_zero | ``A.is_zero`` tests if ``A`` is the **zero matrix** or not. | | >>> A = Matrix([[2, 0], [3, 4]]) | >>> A.is_zero | False | >>> zeros(30).is_zero | True | >>> (0 * A).is_zero | True | | m | Getter for the read-only attribute ``A.m`` (size of the rows, ie. number of columns). | | >>> A = Matrix([[1, 2, 3], [4, 5, 6]]) | >>> A.m | 3 | >>> A.cols == A.m | True | | n | Getter for the read-only attribute ``A.n`` (number of rows). | | >>> A = Matrix([[1, 2, 3], [4, 5, 6]]) | >>> A.n | 2 | >>> A.rows == A.n | True | | rank | ``A.rank`` uses the Gauss elimination process to compute the rank of the matrix ``A``, by simply counting the number of non-zero elements on the diagonal of the echelon form. | | .. todo:: The Gauss process (:py:meth:`gauss`) has to be changed, and improved for singular matrices (when the rank is not maximum!). | | >>> Matrix([[1, 2], [3, 4]]).rank | 2 | >>> Matrix([[1, 2], [1, 2]]).rank | 1 | >>> zeros(7).rank | 0 | >>> eye(19).rank | 19 | | real | Real part of the matrix ``A``, coefficient wise. | | >>> A = Matrix([[1j, 2j], [2j, 1j]]) | >>> A.real | [[0.0, 0.0], [0.0, 0.0]] | >>> A = Matrix([[1+6j, 2], [-1+2j, 1+9j]]) | >>> A.real | [[1.0, 2], [-1.0, 1.0]] | | rows | Getter for the read-only attribute ``A.n`` (number of rows). | | >>> A = Matrix([[1, 2, 3], [4, 5, 6]]) | >>> A.n | 2 | >>> A.rows == A.n | True | | shape | ``A.shape`` is ``(A.n, A.m)`` (similar to the shape attribute of NumPy arrays). | | >>> A = Matrix([[1, 2, 3], [4, 5, 6]]) | >>> A.shape | (2, 3) FUNCTIONS PLUdecomposition(A, mode=None) ``PLUdecomposition(A)`` computes the **permuted LU decomposition** for the matrix ``A``. - Operates in time complexity of :math:`\mathcal{O}(n^3)`, memory of :math:`\mathcal{O}(n^2)`. - ``mode`` can be ``None`` (default), or ``'f'`` for fractions (:class:`Fractions`) or ``'d'`` for decimal (:class:`Decimal`) numbers. - Returned ``P, L, U`` that satisfies ``P*A = L*U``, with ``P`` being a permutation matrix, ``L`` a lower triangular matrix, ``U`` an upper triangular matrix. - Will raise a ``ValueError`` exception if ``A`` is singular. - Reference is `Gauss elimination (on Wikipedia) `_. - We chosed to apply rows operations only: it uses elementary operations on lines/rows: :math:`L_i' \longrightarrow L_i - \gamma \times L_k` (method swap_rows). - Can swap two columns in order to select the bigger pivot (increases the numerical stability). adjugate(A) ``adjugate(A)`` <-> ``A.adjugate()`` returns the adjugate matrix of ``A``. - Reference is `Adjugate matrix (on Wikipedia) `_. - Complexities: memory is :math:`\mathcal{O}(n^2)`, time is :math:`\mathcal{O}(n^5)` (n^2 determinants of size ``n - 1``). - Using the adjugate matrix for computing the inverse is a BAD method : too time-consuming ! LU or Gauss-elimination is only :math:`\mathcal{O}(n^3)`. cofactor(A, i, j) ``cofactor(A, i, j)`` <-> ``A.cofactor(i, j)`` returns the ``(i, j)`` cofactor of ``A``, defined as the ``(-1)**(i + j)`` times to ``(i, j)`` minor of ``A`` (cf. :py:func:`minor`). - Complexities: memory is :math:`\mathcal{O}(n^2)`, time is :math:`\mathcal{O}(n^3)` (1 determinant of size ``n - 1``). det(A) ``det(A)`` <-> ``A.det`` computes the determinant of ``A`` (in :math:`\mathcal{O}(n^3)`). >>> det(eye(2)) 1 >>> det((-1) * eye(4)) 1 >>> det((-1) * eye(5)) -1 diag(d, n=None) ``diag(d)`` creates a matrix from a list ``d`` (or iterator) of diagonal values, or with ``n``-times the value ``d`` if ``d`` is not an iterator and ``n`` is an integer. >>> D = diag(range(1,6)) >>> D[2, :] [[0, 0, 3, 0, 0]] We can check the usual properties of diagonal matrices: >>> D.trace() 15 >>> D.trace() == sum(range(1,6)) True >>> D.det 120 >>> from math import factorial >>> D.det == factorial(5) True Other examples: >>> diag([-1, 1]) [[-1, 0], [0, 1]] >>> diag([-4, 1]) + 3 [[-1, 3], [3, 4]] We can also use the optional argument ``n``: >>> diag(3.14, 3) [[3.14, 0, 0], [0, 3.14, 0], [0, 0, 3.14]] >>> diag([3.14]*3) # Same ! [[3.14, 0, 0], [0, 3.14, 0], [0, 0, 3.14]] exp(A, *args, **kwargs) ``exp(A)`` <-> ``A.exp()`` computes an approximation of the exponential of ``A`` (in :math:`\mathcal{O}(n^3 * limit)`). >>> import math >>> e = math.exp(1.0) >>> C = diag([1, 4]) >>> exp(C) == diag([e ** 1, e ** 4]) == diag([math.exp(1), math.exp(4)]) # Rounding mistakes! False >>> exp(C).almosteq(diag([e ** 1, e ** 4])) # No more rounding mistakes! True >>> diag([e ** 1, e ** 4]).almosteq(diag([math.exp(1), math.exp(4)])) True eye(n) ``eye(n)`` is the (square) identity matrix of size ``(n, n)`` (``1`` on the diagonal, ``0`` outside). >>> eye(2) [[1, 0], [0, 1]] >>> zeros(18) == eye(18) * 0 True >>> eye(60).is_diagonal True >>> eye(40).is_square True >>> eye(20).is_singular False >>> eye(5).det 1 >>> eye(7).trace() 7 gauss(A, *args, **kwargs) ``gauss(A)`` <-> ``A.gauss()`` applies the Gauss elimination process on ``A`` (in :math:`\mathcal{O}(n^3)`). gauss_jordan(A, *args, **kwargs) ``gauss_jordan(A)`` <-> ``A.gauss_jordan()`` applies the Gauss-Jordan elimination process on ``A`` (in :math:`\mathcal{O}(n^3)`). gram_schmidt(V, normalized=False) Basic implementation of the Gram-Schmidt process for the column vectors of the matrix ``V``, in the easy case of :math:`\mathbb{R}^n` with the usual dot product. - The matrix is interpreted as a family of *column* vectors. - Reference for notations, concept and proof is `Gram-Schmidt process (on Wikipedia) `_. - If ``normalized`` is ``True``, the vectors are normalized before being returned. >>> V = Matrix([[1, 2, 3], [-1, 0, 4]]) >>> gram_schmidt(V) [[1, 2, 3], [-1, 0, 4]] innerproduct(vx, vy) (Hermitian) dot product of the two vectors ``vx`` and ``vy`` (sum of ``conjugate(vx[i]) * vy[i]``) : .. math:: \mathbf{x} . \mathbf{y} = \langle \mathbf{x}, \mathbf{y} \rangle := \sum_{1 \leq i \leq n} \overline{x_i} \times y_i. >>> vx = [1, 2, 3]; vy = [-1, 0, 4] >>> innerproduct(vx, vy) 11 .. warning:: The conjugate is on the first vector, as always for Hermite spaces and Hermitian inner product. >>> vx = [1j, 2j, 3j]; vy = [-1, 0, 4] >>> (-1j) * (-1) + (-2j) * (0) + (-3j) * (4) -11j >>> innerproduct(vx, vy) -11j inv(A) ``inv(A)`` <-> ``A.inv()`` **tries** to compute the inverse of ``A`` (in :math:`\mathcal{O}(n^3)`). >>> inv(eye(2)) == eye(2) True mat_from_f(f, n, m=None, *args, **kwargs) ``mat_from_f(f, n, m=None)`` creates a matrix of size ``(n, m)`` initialized with the function ``f`` : ``A[i, j] = f(i, j)``. - Default value for ``m`` is ``n`` (square matrix). .. warning:: ``f`` has to accept (at least) two arguments ``i, j``. >>> mat_from_f(lambda i, j: 1 if i == j else 0, 3) == eye(3) True >>> mat_from_f(lambda i, j: 1, 3) == ones(3) True >>> mat_from_f(lambda i, j: i+j, 3) [[0, 1, 2], [1, 2, 3], [2, 3, 4]] >>> mat_from_f(lambda i, j: i*j, 3) [[0, 0, 0], [0, 1, 2], [0, 2, 4]] - Any extra arguments ``args``, ``kwargs`` are given to the function ``f``. >>> def f(i, j, e, offset=0): ... return (i * e) + offset >>> mat_from_f(f, 2, 2, 4) # n = 2, m = 2, e = 4 [[0, 0], [4, 4]] >>> mat_from_f(f, 2, 2, 4, offset=10) # n = 2, m = 2, e = 4, offset = 10 [[10, 10], [14, 14]] - Remark: it is similar to ``Array.make`` (or ``Array.init``) in OCaml (v3.12+) or ``String.create`` (or ``String.make``). minor(A, i, j) ``minor(A, i, j)`` <-> ``A.minor(i, j)`` returns the ``(i, j)`` minor of ``A``, defined as the determinant of the submatrix ``A[i0,j0]`` for ``i0 != i`` and ``j0 != j``. - Complexities: memory is :math:`\mathcal{O}(n^2)`, time is :math:`\mathcal{O}(n^3)` (1 determinant of size ``n - 1``). norm(A, p=2, *args, **kwargs) ``norm(A, p)`` <-> ``A.norm(p)`` computes the p-norm of ``A`` (default is ``p = 2``). norm2(u) Shortcut for the canonical norm of the vector ``u``: .. math: \| u \| = \sqrt{\langle u, u \rangle}. >>> u = [1, 2, 3] >>> norm2(u) 3.7416573867739413 - It works for imaginary valued vectors: >>> u = [1j, -2j, 3j] >>> norm2(u) 3.7416573867739413 - And it also works for complex valued vectors: >>> u = [1+1j, 2-2j, 3+3j] >>> norm2(u) 5.291502622129181 norm_square(u) Shortcut for the square of the norm of the vector ``u``: .. math:: \| u \|^2 := \langle u, u \rangle. >>> u = [1, 2, 3] >>> norm_square(u) 14 - It works for imaginary valued vectors: >>> u = [1j, -2j, 3j] >>> norm_square(u) 14.0 - And it also works for complex valued vectors: >>> u = [1+1j, 2-2j, 3+3j] >>> norm_square(u) 28.0 ones(n, m=None) ``ones(n, m)`` is a matrix of size ``(n, m)`` filled with ``1``. >>> ones(3, 2) [[1, 1], [1, 1], [1, 1]] >>> ones(2, 3) [[1, 1, 1], [1, 1, 1]] - It works with only one dimension, or with a tuple ``(n, m)`` : >>> ones(2) [[1, 1], [1, 1]] >>> ones((2, 3)) [[1, 1, 1], [1, 1, 1]] proj(u, v) Projection of the vector ``v`` into the vector ``u`` (:math:`\mathrm{proj}_u(v)` as written on Wikipedia). >>> u = [1, 2, 3]; v = [-1, 0, 4] >>> proj(u, v) # 11/14 * u [0.7857142857142857, 1.5714285714285714, 2.357142857142857] >>> proj(u, v) == [(11/14) * x for x in u] True rand_matrix(n=1, m=1, k=10) ``rand_matrix(n, m, k)`` generates a new random matrix of size ``(n, m)`` with each coefficients being integers, randomly taken between ``-k`` and ``k`` (bound *included*). >>> from random import seed >>> seed(0) # We want the examples to always be the same >>> rand_matrix(2, 3) [[7, 5, -2], [-5, 0, -2]] >>> rand_matrix(3, 2, 40) [[23, -16], [-2, 7], [33, 0]] >>> rand_matrix(4, 4, 100) [[-44, 51, 24, -50], [82, 97, 62, 81], [-38, 46, 80, 37], [-6, -80, -13, 22]] rand_matrix_float(n=1, m=1, k=10) ``rand_matrix_float(n, m, k)`` generates a new random matrix of size ``(n, m)`` with each coefficients being float numbers, randomly taken between ``-k`` and ``k`` (right bound excluded). >>> from random import seed >>> seed(0) # We want the examples to always be the same >>> rand_matrix_float(2, 3) [[6.8884370305, 5.15908805881, -1.58856838338], [-4.82166499414, 0.225494427372, -1.90131725099]] >>> rand_matrix_float(3, 2, 1) [[0.56759717807, -0.393374547842], [-0.0468060916953, 0.16676407891], [0.816225770391, 0.00937371163478]] >>> rand_matrix_float(4, 4, 20) [[-8.72648622401, 10.2321681663, 4.73475986701, -9.9797463455], [16.3898502387, 19.3114190415, 12.4086894399, 16.0866380176], [-7.59409722723, 9.19326993041, 15.9535315187, 7.35935727662], [-1.11429138189, -15.9719516773, -2.63312658185, 4.43547893775]] rank(A) ``rank(A)`` <-> ``A.rank`` computes the rank of ``A`` (in :math:`\mathcal{O}(n^3)`). >>> rank(eye(2)) 2 trace(A, *args, **kwargs) ``trace(A)`` <-> ``A.trace()`` computes the trace of ``A``. vect_const_multi(vx, c) Multiply the vector ``vx`` by the constant ``c`` (scalar, ie. real or complex). >>> vx = [1, 2, 3]; vy = [-1, 0, 4] >>> vect_const_multi(vx, 2) [2, 4, 6] >>> vect_const_multi(vy, -4) [4, 0, -16] zeros(n, m=None) ``zeros(n, m)`` is a matrix of size ``(n, m)`` filled with ``0``. >>> zeros(3, 2) [[0, 0], [0, 0], [0, 0]] >>> zeros(2, 3) [[0, 0, 0], [0, 0, 0]] >>> ones(2, 3) == zeros(2, 3) + 1 True >>> zeros(2, 3) == ones(2, 3) * 0 True - It works with only one dimension, or with a tuple ``(n, m)`` : >>> zeros(2) [[0, 0], [0, 0]] >>> zeros((2, 3)) [[0, 0, 0], [0, 0, 0]] DATA absolute_import = _Feature((2, 5, 0, 'alpha', 1), (3, 0, 0, 'alpha', 0... division = _Feature((2, 2, 0, 'alpha', 2), (3, 0, 0, 'alpha', 0), 8192... print_function = _Feature((2, 6, 0, 'alpha', 2), (3, 0, 0, 'alpha', 0)...