コード例 #1
0
    def do_measurement(self, qubit: int) -> int:
        """
        Measure a qubit, collapse the wavefunction, and return the measurement result.

        :param qubit: Index of the qubit to measure.
        :return: measured bit
        """
        if self.rs is None:
            raise ValueError(
                "You have tried to perform a stochastic operation without setting the "
                "random state of the simulator. Might I suggest using a PyQVM object?"
            )
        # lift projective measure operator to Hilbert space
        # prob(0) = <psi P0 | P0 psi> = psi* . P0* . P0 . psi
        measure_0 = lifted_gate_matrix(matrix=P0,
                                       qubit_inds=[qubit],
                                       n_qubits=self.n_qubits)
        proj_psi = measure_0 @ self.wf
        prob_zero = np.conj(proj_psi).T @ proj_psi

        # generate random number to 'roll' for measure
        if self.rs.uniform() < prob_zero:
            # decohere state using the measure_0 operator
            unitary = measure_0 @ (np.eye(2**self.n_qubits) /
                                   np.sqrt(prob_zero))
            self.wf = unitary.dot(self.wf)
            return 0
        else:  # measure one
            measure_1 = lifted_gate_matrix(matrix=P1,
                                           qubit_inds=[qubit],
                                           n_qubits=self.n_qubits)
            unitary = measure_1 @ (np.eye(2**self.n_qubits) /
                                   np.sqrt(1 - prob_zero))
            self.wf = unitary.dot(self.wf)
            return 1
コード例 #2
0
    def do_measurement(self, qubit: int) -> int:
        """
        Measure a qubit and collapse the wavefunction

        :return: The measurement result. A 1 or a 0.
        """
        if self.rs is None:
            raise ValueError(
                "You have tried to perform a stochastic operation without setting the "
                "random state of the simulator. Might I suggest using a PyQVM object?"
            )
        measure_0 = lifted_gate_matrix(matrix=P0,
                                       qubit_inds=[qubit],
                                       n_qubits=self.n_qubits)
        prob_zero = np.trace(measure_0 @ self.density)

        # generate random number to 'roll' for measurement
        if self.rs.uniform() < prob_zero:
            # decohere state using the measure_0 operator
            unitary = measure_0 @ (np.eye(2**self.n_qubits) /
                                   np.sqrt(prob_zero))
            self.density = unitary.dot(self.density).dot(np.conj(unitary.T))
            return 0
        else:  # measure one
            measure_1 = lifted_gate_matrix(matrix=P1,
                                           qubit_inds=[qubit],
                                           n_qubits=self.n_qubits)
            unitary = measure_1 @ (np.eye(2**self.n_qubits) /
                                   np.sqrt(1 - prob_zero))
            self.density = unitary.dot(self.density).dot(np.conj(unitary.T))
            return 1
コード例 #3
0
def test_lifted_gate_two_qubit():
    test_unitary = lifted_gate(CNOT(0, 1), 4)
    true_unitary = lifted_gate_matrix(mat.CNOT, [0, 1], 4)
    assert np.allclose(test_unitary, true_unitary)

    test_unitary = lifted_gate(CNOT(1, 0), 4)
    true_unitary = lifted_gate_matrix(mat.CNOT, [1, 0], 4)
    assert np.allclose(test_unitary, true_unitary)

    test_unitary = lifted_gate(CNOT(1, 3), 4)
    true_unitary = lifted_gate_matrix(mat.CNOT, [1, 3], 4)
    assert np.allclose(test_unitary, true_unitary)
コード例 #4
0
def test_two_qubit_gates_15():
    unitary_test = lifted_gate_matrix(mat.SWAP, [3, 1], 4)
    swap_12 = np.kron(np.eye(2), np.kron(mat.SWAP, np.eye(2)))
    swapper = swap_12
    V = np.kron(mat.SWAP, np.eye(4))
    unitary_true = np.dot(np.conj(swapper.T), np.dot(V, swapper))
    assert np.allclose(unitary_test, unitary_true)
コード例 #5
0
    def do_gate_matrix(self, matrix: np.ndarray, qubits: Sequence[int]):
        """
        Apply an arbitrary unitary; not necessarily a named gate.

        :param matrix: The unitary matrix to apply. No checks are done.
        :param qubits: The qubits to apply the unitary to.
        :return: ``self`` to support method chaining.
        """
        unitary = lifted_gate_matrix(matrix, list(qubits), n_qubits=self.n_qubits)
        self.wf = unitary.dot(self.wf)
        return self
コード例 #6
0
def _term_expectation(wf, term: PauliTerm, n_qubits):
    # Computes <psi|XYZ..XXZ|psi>
    wf2 = wf
    for qubit_i, op_str in term._ops.items():
        # Re-use QUANTUM_GATES since it has X, Y, Z
        op_mat = QUANTUM_GATES[op_str]
        op_mat = lifted_gate_matrix(matrix=op_mat, qubit_inds=[qubit_i], n_qubits=n_qubits)
        wf2 = op_mat @ wf2

    # `wf2` is XYZ..XXZ|psi>
    # hit it with a <psi| i.e. `wf.dag`
    return term.coefficient * (wf.conj().T @ wf2)
コード例 #7
0
    def do_gate_matrix(self, matrix: np.ndarray,
                       qubits: Sequence[int]) -> 'AbstractQuantumSimulator':
        """
        Apply an arbitrary unitary; not necessarily a named gate.

        :param matrix: The unitary matrix to apply. No checks are done
        :param qubits: A list of qubits to apply the unitary to.
        :return: ``self`` to support method chaining.
        """
        unitary = lifted_gate_matrix(matrix=matrix, qubit_inds=qubits, n_qubits=self.n_qubits)
        self.density = unitary.dot(self.density).dot(np.conj(unitary).T)
        return self
コード例 #8
0
    def do_post_gate_noise(self, noise_type: str, noise_prob: float, qubits: List[int]):
        kraus_ops = KRAUS_OPS[noise_type](p=noise_prob)
        if np.isclose(noise_prob, 0.0):
            warnings.warn(f"Skipping {noise_type} post-gate noise because noise_prob is close to 0")
            return self

        for q in qubits:
            new_density = np.zeros_like(self.density)
            for kraus_op in kraus_ops:
                lifted_kraus_op = lifted_gate_matrix(matrix=kraus_op, qubit_inds=[q],
                                                     n_qubits=self.n_qubits)
                new_density += lifted_kraus_op.dot(self.density).dot(np.conj(lifted_kraus_op.T))
            self.density = new_density
        return self
コード例 #9
0
def test_two_qubit_gates_6():
    unitary_test = lifted_gate_matrix(mat.ISWAP, [1, 0], 3)
    unitary_true = np.kron(np.eye(2), mat.ISWAP)
    assert np.allclose(unitary_test, unitary_true)
コード例 #10
0
def test_single_qubit_gates_9():
    test_unitary = lifted_gate_matrix(mat.H, [4], 5)
    true_unitary = np.kron(np.eye(2**0), np.kron(mat.H, np.eye(2**4)))
    assert np.allclose(test_unitary, true_unitary)
コード例 #11
0
def test_single_qubit_gates_5():
    test_unitary = lifted_gate_matrix(mat.H, [0], 5)
    true_unitary = np.kron(np.eye(2**4), mat.H)
    assert np.allclose(test_unitary, true_unitary)
コード例 #12
0
def test_single_qubit_gates_4():
    test_unitary = lifted_gate_matrix(mat.H, [3], 4)
    true_unitary = np.kron(mat.H, np.eye(8))
    assert np.allclose(test_unitary, true_unitary)
コード例 #13
0
def test_two_qubit_gates_1():
    unitary_test = lifted_gate_matrix(mat.CNOT, [1, 0], 2)
    unitary_true = np.kron(mat.P0, np.eye(2)) + \
                   np.kron(mat.P1, mat.X)
    assert np.allclose(unitary_test, unitary_true)
コード例 #14
0
def test_two_qubit_gates_9():
    unitary_test = lifted_gate_matrix(mat.ISWAP, [2, 3], 4)
    unitary_true = np.kron(mat.ISWAP, np.eye(4))
    assert np.allclose(unitary_test, unitary_true)
コード例 #15
0
def test_two_qubit_gates_2():
    unitary_test = lifted_gate_matrix(mat.CNOT, [0, 1], 2)
    unitary_true = np.kron(np.eye(2), mat.P0) + \
                   np.kron(mat.X, mat.P1)
    assert np.allclose(unitary_test, unitary_true)
コード例 #16
0
def test_two_qubit_gates_4():
    with pytest.raises(IndexError):
        lifted_gate_matrix(mat.CNOT, [2, 1], 2)
コード例 #17
0
def test_two_qubit_gates_3():
    unitary_test = lifted_gate_matrix(mat.CNOT, [2, 1], 3)
    unitary_true = np.kron(mat.CNOT, np.eye(2**1))
    assert np.allclose(unitary_test, unitary_true)
コード例 #18
0
def test_multiqubit_decay_bellstate():
    program = Program(RY(np.pi / 3, 0), CNOT(0, 1))

    # commence manually dotting the above program
    initial_density = np.zeros((4, 4), dtype=complex)
    initial_density[0, 0] = 1.0

    gate_time_1q = 50e-9
    T1 = 30e-6
    T2 = 15e-6
    p1 = 1 - np.exp(-gate_time_1q / T1)
    p2 = 1 - np.exp(-gate_time_1q / T2)

    # RY
    gate_1 = np.kron(np.eye(2), qmats.RY(np.pi / 3))
    state = gate_1.dot(initial_density).dot(np.conj(gate_1).T)

    for ii in range(2):
        new_density = np.zeros_like(state)
        for kop in qmats.relaxation_operators(p1):
            operator = lifted_gate_matrix(matrix=kop,
                                          qubit_inds=[ii],
                                          n_qubits=2)
            new_density += operator.dot(state).dot(np.conj(operator).T)
        state = new_density

    for ii in range(2):
        new_density = np.zeros_like(state)
        for kop in qmats.dephasing_operators(p2):
            operator = lifted_gate_matrix(matrix=kop,
                                          qubit_inds=[ii],
                                          n_qubits=2)
            new_density += operator.dot(state).dot(np.conj(operator).T)
        state = new_density

    # CNOT
    # TODO: different 1q, 2q noise probabilities
    cnot_01 = np.kron(qmats.I, qmats.P0) + np.kron(qmats.X, qmats.P1)
    state = cnot_01.dot(state).dot(cnot_01.T)
    gate_time_2q = 150e-9
    p1 = 1 - np.exp(-gate_time_2q / T1)
    p2 = 1 - np.exp(-gate_time_2q / T2)

    for ii in range(2):
        new_density = np.zeros_like(state)
        for kop in qmats.relaxation_operators(p1):
            operator = lifted_gate_matrix(matrix=kop,
                                          qubit_inds=[ii],
                                          n_qubits=2)
            new_density += operator.dot(state).dot(np.conj(operator).T)
        state = new_density

    for ii in range(2):
        new_density = np.zeros_like(state)
        for kop in qmats.dephasing_operators(p2):
            operator = lifted_gate_matrix(matrix=kop,
                                          qubit_inds=[ii],
                                          n_qubits=2)
            new_density += operator.dot(state).dot(np.conj(operator).T)
        state = new_density

    qam = PyQVM(n_qubits=2,
                quantum_simulator_type=ReferenceDensitySimulator,
                post_gate_noise_probabilities={
                    'relaxation': p1,
                    'dephasing': p2
                })
    qam.execute(program)

    assert np.allclose(qam.wf_simulator.density, state)
コード例 #19
0
def test_two_qubit_gates_7():
    unitary_test = lifted_gate_matrix(mat.ISWAP, [1, 2], 4)
    unitary_true = np.kron(np.eye(2), np.kron(mat.ISWAP, np.eye(2)))
    assert np.allclose(unitary_test, unitary_true)