Return true if gate tensor is (almost) unitary
75
def almost_unitary(gate: Gate) -> bool:
    """"""
    res = (gate @ gate.H).asoperator()
    N = gate.qubit_nb
    return np.allclose(asarray(res), np.eye(2**N), atol=TOLERANCE)
88007
public function isNonsingular()
    {
        for ($j = 0; $j < $this->n; $j++) {
            if ($this->LU[$j][$j] == 0) {
                return false;
            }
        }
        return true;
    }
667846
public boolean isNonsingular ()
  {
    for (int j = 0; j < m_nCols; j++)
      if (m_aLU[j][j] == 0)
        return false;
    return true;
  }
23227
def dice(input:Tensor, targs:Tensor, iou:bool=False)->Rank0Tensor:
    ""
    n = targs.shape[0]
    input = input.argmax(dim=1).view(n,-1)
    targs = targs.view(n,-1)
    intersect = (input * targs).sum().float()
    union = (input+targs).sum().float()
    if not iou: return (2. * intersect / union if union > 0 else union.new([1.]).squeeze())
    else: return intersect / (union-intersect+1.0)
193402
def almost_identity(gate: Gate) -> bool:
    """"""
    N = gate.qubit_nb
    return np.allclose(asarray(gate.asoperator()), np.eye(2**N))
1142139
def hessian_tensor_product(fun, argnum=0):
    """"""
    fun_grad = grad(fun, argnum)
    def vector_dot_grad(*args, **kwargs):
        args, vector = args[:-1], args[-1]
        return np.tensordot(fun_grad(*args, **kwargs), vector, np.ndim(vector))
    return grad(vector_dot_grad, argnum)
127032
def operator_is(u):
    """"""
    global _aux
    if np.ndim(u) == 2:
        P = _P2
    elif np.ndim(u) == 3:
        P = _P3
    else:
        raise ValueError("u has an invalid number of dimensions "
                         "(should be 2 or 3)")
    
    if u.shape != _aux.shape[1:]:
        _aux = np.zeros((len(P),) + u.shape)
    
    for _aux_i, P_i in zip(_aux, P):
        _aux_i[:] = binary_dilation(u, P_i)
    
    return _aux.min(0)
1274661
def sdot( U, V ):
    '''
    
    '''
    nu = U.ndim
    #nv = V.ndim
    return np.tensordot( U, V, axes=(nu-1,0) )
32760
def _kak_decomposition_to_operations(q0: ops.Qid,
                                     q1: ops.Qid,
                                     kak: linalg.KakDecomposition,
                                     allow_partial_czs: bool,
                                     atol: float = 1e-8
                                     ) -> List[ops.Operation]:
    """"""
    b0, b1 = kak.single_qubit_operations_before
    pre = [_do_single_on(b0, q0, atol=atol), _do_single_on(b1, q1, atol=atol)]
    a0, a1 = kak.single_qubit_operations_after
    post = [_do_single_on(a0, q0, atol=atol), _do_single_on(a1, q1, atol=atol)]

    return list(cast(Iterable[ops.Operation], ops.flatten_op_tree([
        pre,
        _non_local_part(q0,
                        q1,
                        kak.interaction_coefficients,
                        allow_partial_czs,
                        atol=atol),
        post,
    ])))
1299259
def T(a, half=False, cuda=True):
    
    if not torch.is_tensor(a):
        a = np.array(np.ascontiguousarray(a))
        if a.dtype in (np.int8, np.int16, np.int32, np.int64):
            a = torch.LongTensor(a.astype(np.int64))
        elif a.dtype in (np.float32, np.float64):
            a = to_half(a) if half else torch.FloatTensor(a)
        else: raise NotImplementedError(a.dtype)
    if cuda: a = to_gpu(a)
    return a
1238132
def use_to_ned(tensor):
    '''
    
    '''
    return np.array(ROT_NED_USE.T * np.matrix(tensor) * ROT_NED_USE)
78542
def _disjoint_qubits(op1: ops.Operation, op2: ops.Operation) -> bool:
    """"""
    return not set(op1.qubits) & set(op2.qubits)
768357
def asin(cls, x: 'TensorFluent') -> 'TensorFluent':
        '''
        '''
        return cls._unary_op(x, tf.asin, tf.float32)
1231504
def do_gate(self, gate: Gate):
        
        gate_matrix, qubit_inds = _get_gate_tensor_and_qubits(gate=gate)
        # Note to developers: you can use either einsum- or tensordot- based functions.
        # tensordot seems a little faster, but feel free to experiment.
        # self.wf = targeted_einsum(gate=gate_matrix, wf=self.wf, wf_target_inds=qubit_inds)
        self.wf = targeted_tensordot(gate=gate_matrix, wf=self.wf, wf_target_inds=qubit_inds)
        return self
241802
def tensor_product_basis(*bases):
    
    dim = np.prod([basis.data.shape[1] for basis in bases])
    tp_basis = np.zeros((dim**2, dim, dim), dtype=complex)

    for idx_factors, factors in enumerate(it.product(*[basis.data for basis in bases])):
        tp_basis[idx_factors, :, :] = reduce(np.kron, factors)

    return TomographyBasis(tp_basis,
        sum((
            factor.dims for factor in bases
        ), []),
        list(map(
        r"\otimes".join,
        it.product(*[
            basis.labels for basis in bases
        ])
    )))
478164
def do_gate_matrix(self, matrix: np.ndarray, qubits: Sequence[int]):
        
        unitary = lifted_gate_matrix(matrix, list(qubits), n_qubits=self.n_qubits)
        self.wf = unitary.dot(self.wf)
        return self
372773
def partial_trace(self, qubits: Qubits) -> 'Channel':
        """"""
        vec = self.vec.partial_trace(qubits)
        return Channel(vec.tensor, vec.qubits)