quimb.tensor.array_ops ====================== .. py:module:: quimb.tensor.array_ops .. autoapi-nested-parse:: Backend agnostic array operations. Attributes ---------- .. autoapisummary:: quimb.tensor.array_ops._blocksparselookup quimb.tensor.array_ops._fermioniclookup Classes ------- .. autoapisummary:: quimb.tensor.array_ops.PArray Functions --------- .. autoapisummary:: quimb.tensor.array_ops.asarray quimb.tensor.array_ops.isblocksparse quimb.tensor.array_ops.isfermionic quimb.tensor.array_ops.calc_fuse_perm_and_shape quimb.tensor.array_ops.fuse quimb.tensor.array_ops.ndim quimb.tensor.array_ops.multiply_diagonal quimb.tensor.array_ops.align_axes quimb.tensor.array_ops.iscomplex quimb.tensor.array_ops.norm_fro quimb.tensor.array_ops.norm_fro_autoray quimb.tensor.array_ops.sensibly_scale quimb.tensor.array_ops._numba_find_diag_axes quimb.tensor.array_ops.find_diag_axes quimb.tensor.array_ops._numba_find_antidiag_axes quimb.tensor.array_ops.find_antidiag_axes quimb.tensor.array_ops._numba_find_columns quimb.tensor.array_ops.find_columns Module Contents --------------- .. py:function:: asarray(array) Maybe convert data for a tensor to use. If ``array`` already has a ``.shape`` attribute, i.e. looks like an array, it is left as-is. Else the elements are inspected to see which libraries' array constructor should be used, defaulting to ``numpy`` if everything is builtin or numpy numbers. .. py:data:: _blocksparselookup .. py:function:: isblocksparse(x) Check if `x` is a block-sparse array. Cached on class for speed. .. py:data:: _fermioniclookup .. py:function:: isfermionic(x) Check if `x` is a fermionic array. Cached on class for speed. .. py:function:: calc_fuse_perm_and_shape(shape, axes_groups) .. py:function:: fuse(x, *axes_groups, backend=None) Fuse the give group or groups of axes. The new fused axes will be inserted at the minimum index of any fused axis (even if it is not in the first group). For example, ``fuse(x, [5, 3], [7, 2, 6])`` will produce an array with axes like:: groups inserted at axis 2, removed beyond that. ......<-- (0, 1, g0, g1, 4, 8, ...) | | | g1=(7, 2, 6) g0=(5, 3) :param axes_groups: The axes to fuse. Each group of axes will be fused into a single axis. :type axes_groups: sequence of sequences of int .. py:function:: ndim(array) The number of dimensions of an array. .. py:function:: multiply_diagonal(x, v, axis, backend=None) Multiply v into x as if contracting in a diagonal matrix. .. py:function:: align_axes(*arrays, axes, backend=None) Prepare a set of arrays that should be contractible along ``axes``. For example, block symmetric arrays need to have aligned sectors prior to fusing. .. py:function:: iscomplex(x) Does ``x`` have a complex dtype? .. py:function:: norm_fro(x) The frobenius norm of an array. .. py:function:: norm_fro_autoray(x) .. py:function:: sensibly_scale(x) Take an array and scale it *very* roughly such that random tensor networks consisting of such arrays do not have gigantic norms. .. py:function:: _numba_find_diag_axes(x, atol=1e-12) Numba-compiled array diagonal axis finder. :param x: The array to search for diagonal axes. :type x: numpy.ndarray :param atol: The tolerance with which to compare to zero. :type atol: float :returns: **diag_axes** -- The set of pairs of axes which are diagonal. :rtype: set[tuple[int]] .. py:function:: find_diag_axes(x, atol=1e-12) Try and find a pair of axes of ``x`` in which it is diagonal. :param x: The array to search. :type x: array-like :param atol: Tolerance with which to compare to zero. :type atol: float, optional :returns: The two axes if found else None. :rtype: tuple[int] or None .. rubric:: Examples >>> x = np.array([[[1, 0], [0, 2]], ... [[3, 0], [0, 4]]]) >>> find_diag_axes(x) (1, 2) Which means we can reduce ``x`` without loss of information to: >>> np.einsum('abb->ab', x) array([[1, 2], [3, 4]]) .. py:function:: _numba_find_antidiag_axes(x, atol=1e-12) Numba-compiled array antidiagonal axis finder. :param x: The array to search for anti-diagonal axes. :type x: numpy.ndarray :param atol: The tolerance with which to compare to zero. :type atol: float :returns: **antidiag_axes** -- The set of pairs of axes which are anti-diagonal. :rtype: set[tuple[int]] .. py:function:: find_antidiag_axes(x, atol=1e-12) Try and find a pair of axes of ``x`` in which it is anti-diagonal. :param x: The array to search. :type x: array-like :param atol: Tolerance with which to compare to zero. :type atol: float, optional :returns: The two axes if found else None. :rtype: tuple[int] or None .. rubric:: Examples >>> x = np.array([[[0, 1], [0, 2]], ... [[3, 0], [4, 0]]]) >>> find_antidiag_axes(x) (0, 2) Which means we can reduce ``x`` without loss of information to: >>> np.einsum('aba->ab', x[::-1, :, :]) array([[3, 4], [1, 2]]) as long as we flip the order of dimensions on other tensors corresponding to the the same index. .. py:function:: _numba_find_columns(x, atol=1e-12) Numba-compiled single non-zero column axis finder. :param x: The array to search. :type x: array :param atol: Absolute tolerance to compare to zero with. :type atol: float, optional :returns: Set of pairs (axis, index) defining lone non-zero columns. :rtype: set[tuple[int]] .. py:function:: find_columns(x, atol=1e-12) Try and find columns of axes which are zero apart from a single index. :param x: The array to search. :type x: array-like :param atol: Tolerance with which to compare to zero. :type atol: float, optional :returns: If found, the first integer is which axis, and the second is which column of that axis, else None. :rtype: tuple[int] or None .. rubric:: Examples >>> x = np.array([[[0, 1], [0, 2]], ... [[0, 3], [0, 4]]]) >>> find_columns(x) (2, 1) Which means we can happily slice ``x`` without loss of information to: >>> x[:, :, 1] array([[1, 2], [3, 4]]) .. py:class:: PArray(fn, params, shape=None) Simple array-like object that lazily generates the actual array by calling a function with a set of parameters. :param fn: The function that generates the tensor data from ``params``. :type fn: callable :param params: The initial parameters supplied to the generating function like ``fn(params)``. :type params: sequence of numbers .. seealso:: :py:obj:`PTensor` .. py:attribute:: __slots__ :value: ('_fn', '_params', '_data', '_shape', '_shape_fn_id') .. py:property:: fn .. py:property:: params .. py:attribute:: _shape :value: None .. py:attribute:: _shape_fn_id .. py:method:: copy() .. py:property:: data .. py:property:: shape .. py:property:: ndim .. py:method:: add_function(g) Chain the new function ``g`` on top of current function ``f`` like ``g(f(params))``.