Return true if gate tensor is (almost) the identity
193402
def almost_identity(gate: Gate) -> bool:
    """"""
    N = gate.qubit_nb
    return np.allclose(asarray(gate.asoperator()), np.eye(2**N))
824787
def _is_subspan(self, m, span):
        """"""
        return m.figure.document.id == span[0] and m.figure.position == span[1]
133466
def join_gates(*gates: Gate) -> Gate:
    """"""
    vectors = [gate.vec for gate in gates]
    vec = reduce(outer_product, vectors)
    return Gate(vec.tensor, vec.qubits)
58523
def aschannel(self) -> Channel:
        """"""
        qubits = self.qubits
        N = len(qubits)
        ident = Gate(np.eye(2**N), qubits=qubits).aschannel()

        channels = [op.aschannel() @ ident for op in self.operators]
        if self.weights is not None:
            channels = [c*w for c, w in zip(channels, self.weights)]
        channel = reduce(add, channels)
        return channel
768357
def asin(cls, x: 'TensorFluent') -> 'TensorFluent':
        '''
        '''
        return cls._unary_op(x, tf.asin, tf.float32)
836153
def has_nans(obj):
    
    nans = np.isnan(obj)
    while np.ndim(nans):
        nans = np.any(nans)
    return bool(nans)
979520
def kronecker_decomposition(gate: Gate) -> Circuit:
    
    # An alternative approach would be to take partial traces, but
    # this approach appears to be more robust.

    if gate.qubit_nb != 2:
        raise ValueError('Expected 2-qubit gate')

    U = asarray(gate.asoperator())
    rank = 2**gate.qubit_nb
    U /= np.linalg.det(U) ** (1/rank)

    R = np.stack([U[0:2, 0:2].reshape(4),
                  U[0:2, 2:4].reshape(4),
                  U[2:4, 0:2].reshape(4),
                  U[2:4, 2:4].reshape(4)])
    u, s, vh = np.linalg.svd(R)
    v = vh.transpose()
    A = (np.sqrt(s[0]) * u[:, 0]).reshape(2, 2)
    B = (np.sqrt(s[0]) * v[:, 0]).reshape(2, 2)

    q0, q1 = gate.qubits
    g0 = Gate(A, qubits=[q0])
    g1 = Gate(B, qubits=[q1])

    if not gates_close(gate, Circuit([g0, g1]).asgate()):
        raise ValueError("Gate cannot be decomposed into two 1-qubit gates")

    circ = Circuit()
    circ += zyz_decomposition(g0)
    circ += zyz_decomposition(g1)

    assert gates_close(gate, circ.asgate())  # Sanity check

    return circ
316952
public static boolean isIdentity(DMatrixRMaj mat , double tol )
    {
        // see if the result is an identity matrix
        int index = 0;
        for( int i = 0; i < mat.numRows; i++ ) {
            for( int j = 0; j < mat.numCols; j++ ) {
                if( i == j ) {
                    if( !(Math.abs(mat.get(index++)-1) <= tol) )
                        return false;
                } else {
                    if( !(Math.abs(mat.get(index++)) <= tol) )
                        return false;
                }
            }
        }

        return true;
    }
965026
def productdiag(tensor: BKTensor) -> BKTensor:
    """"""  # DOCME: Explain
    N = rank(tensor)
    tensor = reshape(tensor, [2**(N//2), 2**(N//2)])
    tensor = np.diag(tensor)
    tensor = reshape(tensor, [2]*(N//2))
    return tensor
661116
def _conversion_function(pt_wrapper, dtype=None, name=None, as_ref=False):
  """"""
  # Ignore as_ref to not create backward compatibility issues.
  _ = name, as_ref
  t = pt_wrapper.tensor
  if dtype and not dtype.is_compatible_with(t.dtype):
    raise ValueError(
        'Tensor conversion requested dtype %s for Tensor with dtype %s: %r' %
        (dtype, t.dtype, t))
  return t
464678
def canonical_coords(gate: Gate) -> Sequence[float]:
    """"""
    circ = canonical_decomposition(gate)
    gate = circ.elements[6]  # type: ignore
    params = [gate.params[key] for key in ('tx', 'ty', 'tz')]
    return params
268633
def np2model_tensor(a):
    ""
    dtype = model_type(a.dtype)
    res = as_tensor(a)
    if not dtype: return res
    return res.type(dtype)
1331441
def as_proto(self):
        """"""
        if self._dims is None:
            return tensor_shape_pb2.TensorShapeProto(unknown_rank=True)
        else:
            return tensor_shape_pb2.TensorShapeProto(
                dim=[
                    tensor_shape_pb2.TensorShapeProto.Dim(
                        size=-1 if d.value is None else d.value
                    )
                    for d in self._dims
                ]
            )
188114
def augment_tensor(matrix, ndim=None):
    
    s = matrix.shape
    if ndim is None:
        ndim = s[0]+1
    arr = N.identity(ndim)
    arr[:s[0],:s[1]] = matrix
    return arr
225892
def on_separate_dims(self, other_kernel):
        
        if isinstance(self.active_dims, slice) or isinstance(other_kernel.active_dims, slice):
            # Be very conservative for kernels defined over slices of dimensions
            return False

        if np.any(self.active_dims.reshape(-1, 1) == other_kernel.active_dims.reshape(1, -1)):
            return False

        return True
807783
def is_int_vector(l):
    

    """
    if isinstance(l, np.ndarray):
        if l.ndim == 1 and (l.dtype.kind == 'i' or l.dtype.kind == 'u'):
            return True
    return False
180973
def is_invertible(self,X):
        """"""
        if len(X.shape) == 2:
            return X.shape[0] == X.shape[1] and np.linalg.matrix_rank(X) == X.shape[0]
        else:
            return False