def decompose_transfer_operator( ket: BitString, bra: BitString, qubits: typing.List[int] = None) -> QubitHamiltonian: """ Notes ---------- Create the operator Note that this is operator is not necessarily hermitian So be careful when using it as a generator for gates e.g. decompose_transfer_operator(ket="01", bra="10", qubits=[2,3]) gives the operator .. math:: \\lvert 01 \\rangle \\langle 10 \\rvert_{2,3} acting on qubits 2 and 3 Parameters ---------- ket: pass an integer, string, or tequila BitString bra: pass an integer, string, or tequila BitString qubits: pass the qubits onto which the operator acts Returns ------- """ opmap = {(0, 0): Qp, (0, 1): Sp, (1, 0): Sm, (1, 1): Qm} nbits = None if qubits is not None: nbits = len(qubits) if isinstance(bra, int): bra = BitString.from_int(integer=bra, nbits=nbits) if isinstance(ket, int): ket = BitString.from_int(integer=ket, nbits=nbits) b_arr = bra.array k_arr = ket.array assert (len(b_arr) == len(k_arr)) n_qubits = len(k_arr) if qubits is None: qubits = range(n_qubits) assert (n_qubits <= len(qubits)) result = QubitHamiltonian.unit() for q, b in enumerate(b_arr): k = k_arr[q] result *= opmap[(k, b)](qubit=qubits[q]) return result
def test_conjugation(): primitives = [paulis.X, paulis.Y, paulis.Z] factors = [1, -1, 1j, -1j, 0.5 + 1j] string = QubitHamiltonian.unit() cstring = QubitHamiltonian.unit() for repeat in range(10): for q in random.randint(0, 7, 5): ri = random.randint(0, 2) P = primitives[ri] sign = 1 if ri == 1: sign = -1 factor = factors[random.randint(0, len(factors) - 1)] cfactor = factor.conjugate() string *= factor * P(qubit=q) cstring *= cfactor * sign * P(qubit=q) assert (string.conjugate() == cstring)
def I(*args, **kwargs) -> QubitHamiltonian: """ Initialize unit Operator Returns ------- QubitHamiltonian """ return QubitHamiltonian.unit()
def make_random_pauliword(complex=True): primitives = [paulis.X, paulis.Y, paulis.Z] result = QubitHamiltonian.unit() for q in random.choice(range(10), 5, replace=False): P = primitives[random.randint(0, 2)] real = random.uniform(0, 1) imag = 0 if complex: imag = random.uniform(0, 1) factor = real + imag * 1j result *= factor * P(q) return result
def test_transposition(): primitives = [paulis.X, paulis.Y, paulis.Z] factors = [1, -1, 1j, -1j, 0.5 + 1j] assert ((paulis.X(0) * paulis.X(1) * paulis.Y(2)).transpose() == -1 * paulis.X(0) * paulis.X(1) * paulis.Y(2)) assert ((paulis.X(0) * paulis.X(1) * paulis.Z(2)).transpose() == paulis.X(0) * paulis.X(1) * paulis.Z(2)) for repeat in range(10): string = QubitHamiltonian.unit() tstring = QubitHamiltonian.unit() for q in range(5): ri = random.randint(0, 2) P = primitives[ri] sign = 1 if ri == 1: sign = -1 factor = factors[random.randint(0, len(factors) - 1)] string *= factor * P(qubit=q) tstring *= factor * sign * P(qubit=q) assert (string.transpose() == tstring)