| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034 |
- from collections import defaultdict
- from operator import index as index_
- from sympy.core.expr import Expr
- from sympy.core.kind import Kind, NumberKind, UndefinedKind
- from sympy.core.numbers import Integer, Rational
- from sympy.core.sympify import _sympify, SympifyError
- from sympy.core.singleton import S
- from sympy.polys.domains import ZZ, QQ, GF, EXRAW
- from sympy.polys.matrices import DomainMatrix
- from sympy.polys.matrices.exceptions import DMNonInvertibleMatrixError
- from sympy.polys.polyerrors import CoercionFailed, NotInvertible
- from sympy.utilities.exceptions import sympy_deprecation_warning
- from sympy.utilities.iterables import is_sequence
- from sympy.utilities.misc import filldedent, as_int
- from .exceptions import ShapeError, NonSquareMatrixError, NonInvertibleMatrixError
- from .matrixbase import classof, MatrixBase
- from .kind import MatrixKind
- class RepMatrix(MatrixBase):
- """Matrix implementation based on DomainMatrix as an internal representation.
- The RepMatrix class is a superclass for Matrix, ImmutableMatrix,
- SparseMatrix and ImmutableSparseMatrix which are the main usable matrix
- classes in SymPy. Most methods on this class are simply forwarded to
- DomainMatrix.
- """
- #
- # MatrixBase is the common superclass for all of the usable explicit matrix
- # classes in SymPy. The idea is that MatrixBase is an abstract class though
- # and that subclasses will implement the lower-level methods.
- #
- # RepMatrix is a subclass of MatrixBase that uses DomainMatrix as an
- # internal representation and delegates lower-level methods to
- # DomainMatrix. All of SymPy's standard explicit matrix classes subclass
- # RepMatrix and so use DomainMatrix internally.
- #
- # A RepMatrix uses an internal DomainMatrix with the domain set to ZZ, QQ
- # or EXRAW. The EXRAW domain is equivalent to the previous implementation
- # of Matrix that used Expr for the elements. The ZZ and QQ domains are used
- # when applicable just because they are compatible with the previous
- # implementation but are much more efficient. Other domains such as QQ[x]
- # are not used because they differ from Expr in some way (e.g. automatic
- # expansion of powers and products).
- #
- _rep: DomainMatrix
- def __eq__(self, other):
- # Skip sympify for mutable matrices...
- if not isinstance(other, RepMatrix):
- try:
- other = _sympify(other)
- except SympifyError:
- return NotImplemented
- if not isinstance(other, RepMatrix):
- return NotImplemented
- return self._rep.unify_eq(other._rep)
- def to_DM(self, domain=None, **kwargs):
- """Convert to a :class:`~.DomainMatrix`.
- Examples
- ========
- >>> from sympy import Matrix
- >>> M = Matrix([[1, 2], [3, 4]])
- >>> M.to_DM()
- DomainMatrix({0: {0: 1, 1: 2}, 1: {0: 3, 1: 4}}, (2, 2), ZZ)
- The :meth:`DomainMatrix.to_Matrix` method can be used to convert back:
- >>> M.to_DM().to_Matrix() == M
- True
- The domain can be given explicitly or otherwise it will be chosen by
- :func:`construct_domain`. Any keyword arguments (besides ``domain``)
- are passed to :func:`construct_domain`:
- >>> from sympy import QQ, symbols
- >>> x = symbols('x')
- >>> M = Matrix([[x, 1], [1, x]])
- >>> M
- Matrix([
- [x, 1],
- [1, x]])
- >>> M.to_DM().domain
- ZZ[x]
- >>> M.to_DM(field=True).domain
- ZZ(x)
- >>> M.to_DM(domain=QQ[x]).domain
- QQ[x]
- See Also
- ========
- DomainMatrix
- DomainMatrix.to_Matrix
- DomainMatrix.convert_to
- DomainMatrix.choose_domain
- construct_domain
- """
- if domain is not None:
- if kwargs:
- raise TypeError("Options cannot be used with domain parameter")
- return self._rep.convert_to(domain)
- rep = self._rep
- dom = rep.domain
- # If the internal DomainMatrix is already ZZ or QQ then we can maybe
- # bypass calling construct_domain or performing any conversions. Some
- # kwargs might affect this though e.g. field=True (not sure if there
- # are others).
- if not kwargs:
- if dom.is_ZZ:
- return rep.copy()
- elif dom.is_QQ:
- # All elements might be integers
- try:
- return rep.convert_to(ZZ)
- except CoercionFailed:
- pass
- return rep.copy()
- # Let construct_domain choose a domain
- rep_dom = rep.choose_domain(**kwargs)
- # XXX: There should be an option to construct_domain to choose EXRAW
- # instead of EX. At least converting to EX does not initially trigger
- # EX.simplify which is what we want here but should probably be
- # considered a bug in EX. Perhaps also this could be handled in
- # DomainMatrix.choose_domain rather than here...
- if rep_dom.domain.is_EX:
- rep_dom = rep_dom.convert_to(EXRAW)
- return rep_dom
- @classmethod
- def _unify_element_sympy(cls, rep, element):
- domain = rep.domain
- element = _sympify(element)
- if domain != EXRAW:
- # The domain can only be ZZ, QQ or EXRAW
- if element.is_Integer:
- new_domain = domain
- elif element.is_Rational:
- new_domain = QQ
- else:
- new_domain = EXRAW
- # XXX: This converts the domain for all elements in the matrix
- # which can be slow. This happens e.g. if __setitem__ changes one
- # element to something that does not fit in the domain
- if new_domain != domain:
- rep = rep.convert_to(new_domain)
- domain = new_domain
- if domain != EXRAW:
- element = new_domain.from_sympy(element)
- if domain == EXRAW and not isinstance(element, Expr):
- sympy_deprecation_warning(
- """
- non-Expr objects in a Matrix is deprecated. Matrix represents
- a mathematical matrix. To represent a container of non-numeric
- entities, Use a list of lists, TableForm, NumPy array, or some
- other data structure instead.
- """,
- deprecated_since_version="1.9",
- active_deprecations_target="deprecated-non-expr-in-matrix",
- stacklevel=4,
- )
- return rep, element
- @classmethod
- def _dod_to_DomainMatrix(cls, rows, cols, dod, types):
- if not all(issubclass(typ, Expr) for typ in types):
- sympy_deprecation_warning(
- """
- non-Expr objects in a Matrix is deprecated. Matrix represents
- a mathematical matrix. To represent a container of non-numeric
- entities, Use a list of lists, TableForm, NumPy array, or some
- other data structure instead.
- """,
- deprecated_since_version="1.9",
- active_deprecations_target="deprecated-non-expr-in-matrix",
- stacklevel=6,
- )
- rep = DomainMatrix(dod, (rows, cols), EXRAW)
- if all(issubclass(typ, Rational) for typ in types):
- if all(issubclass(typ, Integer) for typ in types):
- rep = rep.convert_to(ZZ)
- else:
- rep = rep.convert_to(QQ)
- return rep
- @classmethod
- def _flat_list_to_DomainMatrix(cls, rows, cols, flat_list):
- elements_dod = defaultdict(dict)
- for n, element in enumerate(flat_list):
- if element != 0:
- i, j = divmod(n, cols)
- elements_dod[i][j] = element
- types = set(map(type, flat_list))
- rep = cls._dod_to_DomainMatrix(rows, cols, elements_dod, types)
- return rep
- @classmethod
- def _smat_to_DomainMatrix(cls, rows, cols, smat):
- elements_dod = defaultdict(dict)
- for (i, j), element in smat.items():
- if element != 0:
- elements_dod[i][j] = element
- types = set(map(type, smat.values()))
- rep = cls._dod_to_DomainMatrix(rows, cols, elements_dod, types)
- return rep
- def flat(self):
- return self._rep.to_sympy().to_list_flat()
- def _eval_tolist(self):
- return self._rep.to_sympy().to_list()
- def _eval_todok(self):
- return self._rep.to_sympy().to_dok()
- @classmethod
- def _eval_from_dok(cls, rows, cols, dok):
- return cls._fromrep(cls._smat_to_DomainMatrix(rows, cols, dok))
- def _eval_values(self):
- return list(self._eval_iter_values())
- def _eval_iter_values(self):
- rep = self._rep
- K = rep.domain
- values = rep.iter_values()
- if not K.is_EXRAW:
- values = map(K.to_sympy, values)
- return values
- def _eval_iter_items(self):
- rep = self._rep
- K = rep.domain
- to_sympy = K.to_sympy
- items = rep.iter_items()
- if not K.is_EXRAW:
- items = ((i, to_sympy(v)) for i, v in items)
- return items
- def copy(self):
- return self._fromrep(self._rep.copy())
- @property
- def kind(self) -> MatrixKind:
- domain = self._rep.domain
- element_kind: Kind
- if domain in (ZZ, QQ):
- element_kind = NumberKind
- elif domain == EXRAW:
- kinds = {e.kind for e in self.values()}
- if len(kinds) == 1:
- [element_kind] = kinds
- else:
- element_kind = UndefinedKind
- else: # pragma: no cover
- raise RuntimeError("Domain should only be ZZ, QQ or EXRAW")
- return MatrixKind(element_kind)
- def _eval_has(self, *patterns):
- # if the matrix has any zeros, see if S.Zero
- # has the pattern. If _smat is full length,
- # the matrix has no zeros.
- zhas = False
- dok = self.todok()
- if len(dok) != self.rows*self.cols:
- zhas = S.Zero.has(*patterns)
- return zhas or any(value.has(*patterns) for value in dok.values())
- def _eval_is_Identity(self):
- if not all(self[i, i] == 1 for i in range(self.rows)):
- return False
- return len(self.todok()) == self.rows
- def _eval_is_symmetric(self, simpfunc):
- diff = (self - self.T).applyfunc(simpfunc)
- return len(diff.values()) == 0
- def _eval_transpose(self):
- """Returns the transposed SparseMatrix of this SparseMatrix.
- Examples
- ========
- >>> from sympy import SparseMatrix
- >>> a = SparseMatrix(((1, 2), (3, 4)))
- >>> a
- Matrix([
- [1, 2],
- [3, 4]])
- >>> a.T
- Matrix([
- [1, 3],
- [2, 4]])
- """
- return self._fromrep(self._rep.transpose())
- def _eval_col_join(self, other):
- return self._fromrep(self._rep.vstack(other._rep))
- def _eval_row_join(self, other):
- return self._fromrep(self._rep.hstack(other._rep))
- def _eval_extract(self, rowsList, colsList):
- return self._fromrep(self._rep.extract(rowsList, colsList))
- def __getitem__(self, key):
- return _getitem_RepMatrix(self, key)
- @classmethod
- def _eval_zeros(cls, rows, cols):
- rep = DomainMatrix.zeros((rows, cols), ZZ)
- return cls._fromrep(rep)
- @classmethod
- def _eval_eye(cls, rows, cols):
- rep = DomainMatrix.eye((rows, cols), ZZ)
- return cls._fromrep(rep)
- def _eval_add(self, other):
- return classof(self, other)._fromrep(self._rep + other._rep)
- def _eval_matrix_mul(self, other):
- return classof(self, other)._fromrep(self._rep * other._rep)
- def _eval_matrix_mul_elementwise(self, other):
- selfrep, otherrep = self._rep.unify(other._rep)
- newrep = selfrep.mul_elementwise(otherrep)
- return classof(self, other)._fromrep(newrep)
- def _eval_scalar_mul(self, other):
- rep, other = self._unify_element_sympy(self._rep, other)
- return self._fromrep(rep.scalarmul(other))
- def _eval_scalar_rmul(self, other):
- rep, other = self._unify_element_sympy(self._rep, other)
- return self._fromrep(rep.rscalarmul(other))
- def _eval_Abs(self):
- return self._fromrep(self._rep.applyfunc(abs))
- def _eval_conjugate(self):
- rep = self._rep
- domain = rep.domain
- if domain in (ZZ, QQ):
- return self.copy()
- else:
- return self._fromrep(rep.applyfunc(lambda e: e.conjugate()))
- def equals(self, other, failing_expression=False):
- """Applies ``equals`` to corresponding elements of the matrices,
- trying to prove that the elements are equivalent, returning True
- if they are, False if any pair is not, and None (or the first
- failing expression if failing_expression is True) if it cannot
- be decided if the expressions are equivalent or not. This is, in
- general, an expensive operation.
- Examples
- ========
- >>> from sympy import Matrix
- >>> from sympy.abc import x
- >>> A = Matrix([x*(x - 1), 0])
- >>> B = Matrix([x**2 - x, 0])
- >>> A == B
- False
- >>> A.simplify() == B.simplify()
- True
- >>> A.equals(B)
- True
- >>> A.equals(2)
- False
- See Also
- ========
- sympy.core.expr.Expr.equals
- """
- if self.shape != getattr(other, 'shape', None):
- return False
- rv = True
- for i in range(self.rows):
- for j in range(self.cols):
- ans = self[i, j].equals(other[i, j], failing_expression)
- if ans is False:
- return False
- elif ans is not True and rv is True:
- rv = ans
- return rv
- def inv_mod(M, m):
- r"""
- Returns the inverse of the integer matrix ``M`` modulo ``m``.
- Examples
- ========
- >>> from sympy import Matrix
- >>> A = Matrix(2, 2, [1, 2, 3, 4])
- >>> A.inv_mod(5)
- Matrix([
- [3, 1],
- [4, 2]])
- >>> A.inv_mod(3)
- Matrix([
- [1, 1],
- [0, 1]])
- """
- if not M.is_square:
- raise NonSquareMatrixError()
- try:
- m = as_int(m)
- except ValueError:
- raise TypeError("inv_mod: modulus m must be an integer")
- K = GF(m, symmetric=False)
- try:
- dM = M.to_DM(K)
- except CoercionFailed:
- raise ValueError("inv_mod: matrix entries must be integers")
- if K.is_Field:
- try:
- dMi = dM.inv()
- except DMNonInvertibleMatrixError as exc:
- msg = f'Matrix is not invertible (mod {m})'
- raise NonInvertibleMatrixError(msg) from exc
- else:
- dMadj, det = dM.adj_det()
- try:
- detinv = 1 / det
- except NotInvertible:
- msg = f'Matrix is not invertible (mod {m})'
- raise NonInvertibleMatrixError(msg)
- dMi = dMadj * detinv
- return dMi.to_Matrix()
- def lll(self, delta=0.75):
- """LLL-reduced basis for the rowspace of a matrix of integers.
- Performs the Lenstra–Lenstra–Lovász (LLL) basis reduction algorithm.
- The implementation is provided by :class:`~DomainMatrix`. See
- :meth:`~DomainMatrix.lll` for more details.
- Examples
- ========
- >>> from sympy import Matrix
- >>> M = Matrix([[1, 0, 0, 0, -20160],
- ... [0, 1, 0, 0, 33768],
- ... [0, 0, 1, 0, 39578],
- ... [0, 0, 0, 1, 47757]])
- >>> M.lll()
- Matrix([
- [ 10, -3, -2, 8, -4],
- [ 3, -9, 8, 1, -11],
- [ -3, 13, -9, -3, -9],
- [-12, -7, -11, 9, -1]])
- See Also
- ========
- lll_transform
- sympy.polys.matrices.domainmatrix.DomainMatrix.lll
- """
- delta = QQ.from_sympy(_sympify(delta))
- dM = self._rep.convert_to(ZZ)
- basis = dM.lll(delta=delta)
- return self._fromrep(basis)
- def lll_transform(self, delta=0.75):
- """LLL-reduced basis and transformation matrix.
- Performs the Lenstra–Lenstra–Lovász (LLL) basis reduction algorithm.
- The implementation is provided by :class:`~DomainMatrix`. See
- :meth:`~DomainMatrix.lll_transform` for more details.
- Examples
- ========
- >>> from sympy import Matrix
- >>> M = Matrix([[1, 0, 0, 0, -20160],
- ... [0, 1, 0, 0, 33768],
- ... [0, 0, 1, 0, 39578],
- ... [0, 0, 0, 1, 47757]])
- >>> B, T = M.lll_transform()
- >>> B
- Matrix([
- [ 10, -3, -2, 8, -4],
- [ 3, -9, 8, 1, -11],
- [ -3, 13, -9, -3, -9],
- [-12, -7, -11, 9, -1]])
- >>> T
- Matrix([
- [ 10, -3, -2, 8],
- [ 3, -9, 8, 1],
- [ -3, 13, -9, -3],
- [-12, -7, -11, 9]])
- The transformation matrix maps the original basis to the LLL-reduced
- basis:
- >>> T * M == B
- True
- See Also
- ========
- lll
- sympy.polys.matrices.domainmatrix.DomainMatrix.lll_transform
- """
- delta = QQ.from_sympy(_sympify(delta))
- dM = self._rep.convert_to(ZZ)
- basis, transform = dM.lll_transform(delta=delta)
- B = self._fromrep(basis)
- T = self._fromrep(transform)
- return B, T
- class MutableRepMatrix(RepMatrix):
- """Mutable matrix based on DomainMatrix as the internal representation"""
- #
- # MutableRepMatrix is a subclass of RepMatrix that adds/overrides methods
- # to make the instances mutable. MutableRepMatrix is a superclass for both
- # MutableDenseMatrix and MutableSparseMatrix.
- #
- is_zero = False
- def __new__(cls, *args, **kwargs):
- return cls._new(*args, **kwargs)
- @classmethod
- def _new(cls, *args, copy=True, **kwargs):
- if copy is False:
- # The input was rows, cols, [list].
- # It should be used directly without creating a copy.
- if len(args) != 3:
- raise TypeError("'copy=False' requires a matrix be initialized as rows,cols,[list]")
- rows, cols, flat_list = args
- else:
- rows, cols, flat_list = cls._handle_creation_inputs(*args, **kwargs)
- flat_list = list(flat_list) # create a shallow copy
- rep = cls._flat_list_to_DomainMatrix(rows, cols, flat_list)
- return cls._fromrep(rep)
- @classmethod
- def _fromrep(cls, rep):
- obj = super().__new__(cls)
- obj.rows, obj.cols = rep.shape
- obj._rep = rep
- return obj
- def copy(self):
- return self._fromrep(self._rep.copy())
- def as_mutable(self):
- return self.copy()
- def __setitem__(self, key, value):
- """
- Examples
- ========
- >>> from sympy import Matrix, I, zeros, ones
- >>> m = Matrix(((1, 2+I), (3, 4)))
- >>> m
- Matrix([
- [1, 2 + I],
- [3, 4]])
- >>> m[1, 0] = 9
- >>> m
- Matrix([
- [1, 2 + I],
- [9, 4]])
- >>> m[1, 0] = [[0, 1]]
- To replace row r you assign to position r*m where m
- is the number of columns:
- >>> M = zeros(4)
- >>> m = M.cols
- >>> M[3*m] = ones(1, m)*2; M
- Matrix([
- [0, 0, 0, 0],
- [0, 0, 0, 0],
- [0, 0, 0, 0],
- [2, 2, 2, 2]])
- And to replace column c you can assign to position c:
- >>> M[2] = ones(m, 1)*4; M
- Matrix([
- [0, 0, 4, 0],
- [0, 0, 4, 0],
- [0, 0, 4, 0],
- [2, 2, 4, 2]])
- """
- rv = self._setitem(key, value)
- if rv is not None:
- i, j, value = rv
- self._rep, value = self._unify_element_sympy(self._rep, value)
- self._rep.rep.setitem(i, j, value)
- def _eval_col_del(self, col):
- self._rep = DomainMatrix.hstack(self._rep[:,:col], self._rep[:,col+1:])
- self.cols -= 1
- def _eval_row_del(self, row):
- self._rep = DomainMatrix.vstack(self._rep[:row,:], self._rep[row+1:, :])
- self.rows -= 1
- def _eval_col_insert(self, col, other):
- other = self._new(other)
- return self.hstack(self[:,:col], other, self[:,col:])
- def _eval_row_insert(self, row, other):
- other = self._new(other)
- return self.vstack(self[:row,:], other, self[row:,:])
- def col_op(self, j, f):
- """In-place operation on col j using two-arg functor whose args are
- interpreted as (self[i, j], i).
- Examples
- ========
- >>> from sympy import eye
- >>> M = eye(3)
- >>> M.col_op(1, lambda v, i: v + 2*M[i, 0]); M
- Matrix([
- [1, 2, 0],
- [0, 1, 0],
- [0, 0, 1]])
- See Also
- ========
- col
- row_op
- """
- for i in range(self.rows):
- self[i, j] = f(self[i, j], i)
- def col_swap(self, i, j):
- """Swap the two given columns of the matrix in-place.
- Examples
- ========
- >>> from sympy import Matrix
- >>> M = Matrix([[1, 0], [1, 0]])
- >>> M
- Matrix([
- [1, 0],
- [1, 0]])
- >>> M.col_swap(0, 1)
- >>> M
- Matrix([
- [0, 1],
- [0, 1]])
- See Also
- ========
- col
- row_swap
- """
- for k in range(0, self.rows):
- self[k, i], self[k, j] = self[k, j], self[k, i]
- def row_op(self, i, f):
- """In-place operation on row ``i`` using two-arg functor whose args are
- interpreted as ``(self[i, j], j)``.
- Examples
- ========
- >>> from sympy import eye
- >>> M = eye(3)
- >>> M.row_op(1, lambda v, j: v + 2*M[0, j]); M
- Matrix([
- [1, 0, 0],
- [2, 1, 0],
- [0, 0, 1]])
- See Also
- ========
- row
- zip_row_op
- col_op
- """
- for j in range(self.cols):
- self[i, j] = f(self[i, j], j)
- #The next three methods give direct support for the most common row operations inplace.
- def row_mult(self,i,factor):
- """Multiply the given row by the given factor in-place.
- Examples
- ========
- >>> from sympy import eye
- >>> M = eye(3)
- >>> M.row_mult(1,7); M
- Matrix([
- [1, 0, 0],
- [0, 7, 0],
- [0, 0, 1]])
- """
- for j in range(self.cols):
- self[i,j] *= factor
- def row_add(self,s,t,k):
- """Add k times row s (source) to row t (target) in place.
- Examples
- ========
- >>> from sympy import eye
- >>> M = eye(3)
- >>> M.row_add(0, 2,3); M
- Matrix([
- [1, 0, 0],
- [0, 1, 0],
- [3, 0, 1]])
- """
- for j in range(self.cols):
- self[t,j] += k*self[s,j]
- def row_swap(self, i, j):
- """Swap the two given rows of the matrix in-place.
- Examples
- ========
- >>> from sympy import Matrix
- >>> M = Matrix([[0, 1], [1, 0]])
- >>> M
- Matrix([
- [0, 1],
- [1, 0]])
- >>> M.row_swap(0, 1)
- >>> M
- Matrix([
- [1, 0],
- [0, 1]])
- See Also
- ========
- row
- col_swap
- """
- for k in range(0, self.cols):
- self[i, k], self[j, k] = self[j, k], self[i, k]
- def zip_row_op(self, i, k, f):
- """In-place operation on row ``i`` using two-arg functor whose args are
- interpreted as ``(self[i, j], self[k, j])``.
- Examples
- ========
- >>> from sympy import eye
- >>> M = eye(3)
- >>> M.zip_row_op(1, 0, lambda v, u: v + 2*u); M
- Matrix([
- [1, 0, 0],
- [2, 1, 0],
- [0, 0, 1]])
- See Also
- ========
- row
- row_op
- col_op
- """
- for j in range(self.cols):
- self[i, j] = f(self[i, j], self[k, j])
- def copyin_list(self, key, value):
- """Copy in elements from a list.
- Parameters
- ==========
- key : slice
- The section of this matrix to replace.
- value : iterable
- The iterable to copy values from.
- Examples
- ========
- >>> from sympy import eye
- >>> I = eye(3)
- >>> I[:2, 0] = [1, 2] # col
- >>> I
- Matrix([
- [1, 0, 0],
- [2, 1, 0],
- [0, 0, 1]])
- >>> I[1, :2] = [[3, 4]]
- >>> I
- Matrix([
- [1, 0, 0],
- [3, 4, 0],
- [0, 0, 1]])
- See Also
- ========
- copyin_matrix
- """
- if not is_sequence(value):
- raise TypeError("`value` must be an ordered iterable, not %s." % type(value))
- return self.copyin_matrix(key, type(self)(value))
- def copyin_matrix(self, key, value):
- """Copy in values from a matrix into the given bounds.
- Parameters
- ==========
- key : slice
- The section of this matrix to replace.
- value : Matrix
- The matrix to copy values from.
- Examples
- ========
- >>> from sympy import Matrix, eye
- >>> M = Matrix([[0, 1], [2, 3], [4, 5]])
- >>> I = eye(3)
- >>> I[:3, :2] = M
- >>> I
- Matrix([
- [0, 1, 0],
- [2, 3, 0],
- [4, 5, 1]])
- >>> I[0, 1] = M
- >>> I
- Matrix([
- [0, 0, 1],
- [2, 2, 3],
- [4, 4, 5]])
- See Also
- ========
- copyin_list
- """
- rlo, rhi, clo, chi = self.key2bounds(key)
- shape = value.shape
- dr, dc = rhi - rlo, chi - clo
- if shape != (dr, dc):
- raise ShapeError(filldedent("The Matrix `value` doesn't have the "
- "same dimensions "
- "as the in sub-Matrix given by `key`."))
- for i in range(value.rows):
- for j in range(value.cols):
- self[i + rlo, j + clo] = value[i, j]
- def fill(self, value):
- """Fill self with the given value.
- Notes
- =====
- Unless many values are going to be deleted (i.e. set to zero)
- this will create a matrix that is slower than a dense matrix in
- operations.
- Examples
- ========
- >>> from sympy import SparseMatrix
- >>> M = SparseMatrix.zeros(3); M
- Matrix([
- [0, 0, 0],
- [0, 0, 0],
- [0, 0, 0]])
- >>> M.fill(1); M
- Matrix([
- [1, 1, 1],
- [1, 1, 1],
- [1, 1, 1]])
- See Also
- ========
- zeros
- ones
- """
- value = _sympify(value)
- if not value:
- self._rep = DomainMatrix.zeros(self.shape, EXRAW)
- else:
- elements_dod = {i: dict.fromkeys(range(self.cols), value) for i in range(self.rows)}
- self._rep = DomainMatrix(elements_dod, self.shape, EXRAW)
- def _getitem_RepMatrix(self, key):
- """Return portion of self defined by key. If the key involves a slice
- then a list will be returned (if key is a single slice) or a matrix
- (if key was a tuple involving a slice).
- Examples
- ========
- >>> from sympy import Matrix, I
- >>> m = Matrix([
- ... [1, 2 + I],
- ... [3, 4 ]])
- If the key is a tuple that does not involve a slice then that element
- is returned:
- >>> m[1, 0]
- 3
- When a tuple key involves a slice, a matrix is returned. Here, the
- first column is selected (all rows, column 0):
- >>> m[:, 0]
- Matrix([
- [1],
- [3]])
- If the slice is not a tuple then it selects from the underlying
- list of elements that are arranged in row order and a list is
- returned if a slice is involved:
- >>> m[0]
- 1
- >>> m[::2]
- [1, 3]
- """
- if isinstance(key, tuple):
- i, j = key
- try:
- return self._rep.getitem_sympy(index_(i), index_(j))
- except (TypeError, IndexError):
- if (isinstance(i, Expr) and not i.is_number) or (isinstance(j, Expr) and not j.is_number):
- if ((j < 0) is True) or ((j >= self.shape[1]) is True) or\
- ((i < 0) is True) or ((i >= self.shape[0]) is True):
- raise ValueError("index out of boundary")
- from sympy.matrices.expressions.matexpr import MatrixElement
- return MatrixElement(self, i, j)
- if isinstance(i, slice):
- i = range(self.rows)[i]
- elif is_sequence(i):
- pass
- else:
- i = [i]
- if isinstance(j, slice):
- j = range(self.cols)[j]
- elif is_sequence(j):
- pass
- else:
- j = [j]
- return self.extract(i, j)
- else:
- # Index/slice like a flattened list
- rows, cols = self.shape
- # Raise the appropriate exception:
- if not rows * cols:
- return [][key]
- rep = self._rep.rep
- domain = rep.domain
- is_slice = isinstance(key, slice)
- if is_slice:
- values = [rep.getitem(*divmod(n, cols)) for n in range(rows * cols)[key]]
- else:
- values = [rep.getitem(*divmod(index_(key), cols))]
- if domain != EXRAW:
- to_sympy = domain.to_sympy
- values = [to_sympy(val) for val in values]
- if is_slice:
- return values
- else:
- return values[0]
|