Direct product of qubit vectors

    The tensor ranks must match and qubits must be disjoint.
348809
def outer_product(vec0: QubitVector, vec1: QubitVector) -> QubitVector:
    
    R = vec0.rank
    R1 = vec1.rank

    N0 = vec0.qubit_nb
    N1 = vec1.qubit_nb

    if R != R1:
        raise ValueError('Incompatibly vectors. Rank must match')

    if not set(vec0.qubits).isdisjoint(vec1.qubits):
        raise ValueError('Overlapping qubits')

    qubits: Qubits = tuple(vec0.qubits) + tuple(vec1.qubits)

    tensor = bk.outer(vec0.tensor, vec1.tensor)

    # Interleave (super)-operator axes
    # R = 1  perm = (0, 1)
    # R = 2  perm = (0, 2, 1, 3)
    # R = 4  perm = (0, 4, 1, 5, 2, 6, 3, 7)
    tensor = bk.reshape(tensor, ([2**N0] * R) + ([2**N1] * R))
    perm = [idx for ij in zip(range(0, R), range(R, 2*R)) for idx in ij]
    tensor = bk.transpose(tensor, perm)

    return QubitVector(tensor, qubits)
102820
def _apply_krauss_single_qubit(krauss: Union[Tuple[Any], Sequence[Any]],
        args: 'ApplyChannelArgs') -> np.ndarray:
    """"""
    zero_left = linalg.slice_for_qubits_equal_to(args.left_axes, 0)
    one_left = linalg.slice_for_qubits_equal_to(args.left_axes, 1)
    zero_right = linalg.slice_for_qubits_equal_to(args.right_axes, 0)
    one_right = linalg.slice_for_qubits_equal_to(args.right_axes, 1)
    for krauss_op in krauss:
        np.copyto(dst=args.target_tensor,
                  src=args.auxiliary_buffer0)
        linalg.apply_matrix_to_slices(
                args.target_tensor,
                krauss_op,
                [zero_left, one_left],
                out=args.auxiliary_buffer1)
        # No need to transpose as we are acting on the tensor
        # representation of matrix, so transpose is done for us.
        linalg.apply_matrix_to_slices(
                args.auxiliary_buffer1,
                np.conjugate(krauss_op),
                [zero_right, one_right],
                out=args.target_tensor)
        args.out_buffer += args.target_tensor
    return args.out_buffer
74100
function hessenbergQRStep (M) {
  const n = M.dimension;
  const me = M.elements;
  const csr = [0, 0, 0];
  const cs = [];
  for (let k = 0; k < n - 1; ++k) {
    const row1 = k;
    const row2 = k + 1;
    const colK = k * n;
    const a = me[row1 + colK];
    const b = me[row2 + colK];
    rotg(a, b, csr);
    const c = csr[0];
    const s = csr[1];
    const r = csr[2];
    cs[k] = [c, s];
    for (let x = k; x < n; ++x) {
      const colX = x * n;
      const tmp1 = me[row1 + colX];
      const tmp2 = me[row2 + colX];
      me[row1 + colX] = c * tmp1 + s * tmp2;
      me[row2 + colX] = -s * tmp1 + c * tmp2;
    }
    me[row1 + colK] = r;
    me[row2 + colK] = 0;
  }
  for (let k = 0; k < n - 1; ++k) {
    const col1 = k * n;
    const col2 = (k + 1) * n;
    const [c, s] = cs[k];
    for (let x = 0; x <= k + 1; ++x) {
      const rowX = x;
      const tmp1 = me[rowX + col1];
      const tmp2 = me[rowX + col2];
      me[rowX + col1] = tmp1 * c + tmp2 * s;
      me[rowX + col2] = -tmp1 * s + tmp2 * c;
    }
  }
  return M;
}
88682
def identity_gate(qubits: Union[int, Qubits]) -> Gate:
    """"""
    _, qubits = qubits_count_tuple(qubits)
    return I(*qubits)
1068849
public void recomputeQ( DMatrix4x4 Q ) {
		CommonOps_DDF3.multTransB(k,k,w);

		Q.a11 = w.a11;Q.a12 = w.a12;Q.a13 = w.a13;
		Q.a21 = w.a21;Q.a22 = w.a22;Q.a23 = w.a23;
		Q.a31 = w.a31;Q.a32 = w.a32;Q.a33 = w.a33;

		CommonOps_DDF3.mult(w,p,t);
		CommonOps_DDF3.scale(-1,t);

		Q.a14 = t.a1;Q.a24 = t.a2;Q.a34 = t.a3;
		Q.a41 = t.a1;Q.a42 = t.a2;Q.a43 = t.a3;

		Q.a44 = -CommonOps_DDF3.dot(t,p);
	}
374843
def cross_product(self, p1, p2):
        """"""
        return (p1.x * p2.y - p1.y * p2.x)
1011042
def normalize(self) -> 'State':
        """"""
        tensor = self.tensor / bk.ccast(bk.sqrt(self.norm()))
        return State(tensor, self.qubits, self._memory)
377574
def quaternion_product(quat1, quat2):
    """"""
    return np.array([
        quat1[0]*quat2[0] - np.dot(quat1[1:], quat2[1:]),
        quat1[0]*quat2[1] + quat2[0]*quat1[1] + quat1[2]*quat2[3] - quat1[3]*quat2[2],
        quat1[0]*quat2[2] + quat2[0]*quat1[2] + quat1[3]*quat2[1] - quat1[1]*quat2[3],
        quat1[0]*quat2[3] + quat2[0]*quat1[3] + quat1[1]*quat2[2] - quat1[2]*quat2[1]
    ], float)
469595
def su(self) -> 'Gate':
        """"""
        rank = 2**self.qubit_nb
        U = asarray(self.asoperator())
        U /= np.linalg.det(U) ** (1/rank)
        return Gate(tensor=U, qubits=self.qubits)
251579
def quartic_paired_acquaintance_strategy(
    qubit_pairs: Iterable[Tuple[ops.Qid, ops.Qid]]
    ) -> Tuple[circuits.Circuit, Sequence[ops.Qid]]:
    

    qubit_pairs = tuple(
            cast(Tuple[ops.Qid, ops.Qid], tuple(qubit_pair))
            for qubit_pair in qubit_pairs)
    qubits = qubit_pairs_to_qubit_order(qubit_pairs)
    n_qubits = len(qubits)
    swap_network = SwapNetworkGate((1,) * n_qubits, 2)(*qubits)
    strategy = circuits.Circuit.from_ops(swap_network,
            device=UnconstrainedAcquaintanceDevice)
    expose_acquaintance_gates(strategy)
    for i in reversed(range(0, n_qubits, 2)):
        moment = ops.Moment([acquaint(*qubits[j: j + 4])
                             for j in range(i % 4, n_qubits - 3, 4)])
        strategy.insert(2 * i, moment)
    return strategy, qubits
184586
def zero_state(qubits: Union[int, Qubits]) -> State:
    """"""
    N, qubits = qubits_count_tuple(qubits)
    ket = np.zeros(shape=[2] * N)
    ket[(0,) * N] = 1
    return State(ket, qubits)
78542
def _disjoint_qubits(op1: ops.Operation, op2: ops.Operation) -> bool:
    """"""
    return not set(op1.qubits) & set(op2.qubits)
1368856
def _probs(state: np.ndarray, indices: List[int],
           num_qubits: int) -> List[float]:
    """"""
    # Tensor of squared amplitudes, shaped a rank [2, 2, .., 2] tensor.
    tensor = np.reshape(state, [2] * num_qubits)

    # Calculate the probabilities for measuring the particular results.
    probs = [
        np.linalg.norm(
                tensor[linalg.slice_for_qubits_equal_to(indices, b)]) ** 2
        for b in range(2 ** len(indices))]

    # To deal with rounding issues, ensure that the probabilities sum to 1.
    probs /= sum(probs) # type: ignore
    return probs
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)
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)
717532
def _probs(density_matrix: np.ndarray, indices: List[int],
    num_qubits: int) -> List[float]:
    """"""
    # Only diagonal elements matter.
    all_probs = np.diagonal(
        np.reshape(density_matrix, (2 ** num_qubits, 2 ** num_qubits)))
    # Shape into a tensor
    tensor = np.reshape(all_probs, [2] * num_qubits)

    # Calculate the probabilities for measuring the particular results.
    probs = [
        np.sum(np.abs(tensor[linalg.slice_for_qubits_equal_to(indices, b)]))
        for b in range(2 ** len(indices))]

    # To deal with rounding issues, ensure that the probabilities sum to 1.
    probs /= np.sum(probs) # type: ignore
    return probs
1207677
def vectors_close(vec0: QubitVector, vec1: QubitVector,
                  tolerance: float = TOLERANCE) -> bool:
    
    if vec0.rank != vec1.rank:
        return False

    if vec0.qubit_nb != vec1.qubit_nb:
        return False

    if set(vec0.qubits) ^ set(vec1.qubits):
        return False

    return bk.evaluate(fubini_study_angle(vec0, vec1)) <= tolerance