Beispiel #1
0
    def test_xyx(self):
        """Exercise 4.7 in Nielson, Chuang, XYX == -Y."""

        x = ops.PauliX()
        y = ops.PauliY()
        op = x(y(x))
        self.assertTrue(op.is_close(-1.0 * ops.PauliY()))
Beispiel #2
0
def run_single_qubit_mult():
    """Run experiments with single qubits."""

    # Construct Hamiltonian.
    hamil = (random.random() * ops.PauliX() + random.random() * ops.PauliY() +
             random.random() * ops.PauliZ())
    # Compute known minimum eigenvalue.
    eigvals = np.linalg.eigvalsh(hamil)

    # Brute force over the Bloch sphere.
    min_val = 1000.0
    for i in range(0, 180, 10):
        for j in range(0, 180, 10):
            theta = np.pi * i / 180.0
            phi = np.pi * j / 180.0

            # Build the ansatz with two rotation gates.
            ansatz = single_qubit_ansatz(theta, phi)

            # Compute <psi ! H ! psi>. Find smallest one, which will be
            # the best approximation to the minimum eigenvalue from above.
            # In this version, we just multiply out the result.
            psi = np.dot(ansatz.psi.adjoint(), hamil(ansatz.psi))
            if psi < min_val:
                min_val = psi

    # Result from brute force approach:
    print('Minimum: {:.4f}, Estimated: {:.4f}, Delta: {:.4f}'.format(
        eigvals[0], np.real(min_val), np.real(min_val - eigvals[0])))
Beispiel #3
0
    def test_equalities(self):
        """Exercise 4.13 in Nielson, Chuang."""

        _, x, y, z = ops.Pauli()
        h = ops.Hadamard()

        op = h(x(h))
        self.assertTrue(op.is_close(ops.PauliZ()))

        op = h(y(h))
        self.assertTrue(op.is_close(-1.0 * ops.PauliY()))

        op = h(z(h))
        self.assertTrue(op.is_close(ops.PauliX()))

        op = x(z)
        self.assertTrue(op.is_close(1.0j * ops.PauliY()))
Beispiel #4
0
    def test_bell_and_pauli(self):
        b00 = bell.bell_state(0, 0)

        bell_xz = ops.PauliX()(b00)
        bell_xz = ops.PauliZ()(bell_xz)

        bell_iy = (1j * ops.PauliY())(b00)

        self.assertTrue(np.allclose(bell_xz, bell_iy))
Beispiel #5
0
def single_qubit():
    """Compute Pauli representation of single qubit."""

    for i in range(10):
        # First we construct a circuit with just one, very random qubit.
        #
        qc = circuit.qc('random qubit')
        qc.qubit(random.random())
        qc.rx(0, math.pi * random.random())
        qc.ry(0, math.pi * random.random())
        qc.rz(0, math.pi * random.random())

        # Every qubit (rho) can be put in the Pauli Representation,
        # which is this Sum over i from 0 to 3 inclusive, representing
        # the four Pauli matrices (including the Identity):
        #
        #                  3
        #    rho = 1/2 * Sum(c_i * Pauli_i)
        #                 i=0
        #
        # To compute the various factors c_i, we multiply the Pauli
        # matrices with the density matrix and take the trace. This
        # trace is the computed factor:
        #
        rho = qc.psi.density()
        i = np.trace(ops.Identity() @ rho)
        x = np.trace(ops.PauliX() @ rho)
        y = np.trace(ops.PauliY() @ rho)
        z = np.trace(ops.PauliZ() @ rho)

        # Let's verify the result and construct a density matrix
        # from the Pauli matrices using the computed factors:
        #
        new_rho = 0.5 * (i * ops.Identity() + x * ops.PauliX() +
                         y * ops.PauliY() + z * ops.PauliZ())
        if not np.allclose(rho, new_rho):
            raise AssertionError('Invalid Pauli Representation')

        print(f'qubit({qc.psi[0]:11.2f}, {qc.psi[1]:11.2f}) = ', end='')
        print(f'{i:11.2f} I + {x:11.2f} X + {y:11.2f} Y + {z:11.2f} Z')
Beispiel #6
0
    def test_acceleration(self):
        psi = state.bitstring(1, 0, 1, 0)
        qc = circuit.qc()
        qc.bitstring(1, 0, 1, 0)

        for i in range(4):
            qc.x(i)
            psi.apply(ops.PauliX(), i)
            qc.y(i)
            psi.apply(ops.PauliY(), i)
            qc.z(i)
            psi.apply(ops.PauliZ(), i)
            qc.h(i)
            psi.apply(ops.Hadamard(), i)
            if i:
                qc.cu1(0, i, 1.1)
                psi.apply_controlled(ops.U1(1.1), 0, i)

        if not psi.is_close(qc.psi):
            raise AssertionError('Numerical Problems')

        psi = state.bitstring(1, 0, 1, 0, 1)
        qc = circuit.qc()
        qc.bitstring(1, 0, 1, 0, 1)

        for n in range(5):
            qc.h(n)
            psi.apply(ops.Hadamard(), n)
            for i in range(0, 5):
                qc.cu1(n - (i + 1), n, math.pi / float(2**(i + 1)))
                psi.apply_controlled(ops.U1(math.pi / float(2**(i + 1))),
                                     n - (i + 1), n)
            for i in range(0, 5):
                qc.cu1(n - (i + 1), n, -math.pi / float(2**(i + 1)))
                psi.apply_controlled(ops.U1(-math.pi / float(2**(i + 1))),
                                     n - (i + 1), n)
            qc.h(n)
            psi.apply(ops.Hadamard(), n)

        if not psi.is_close(qc.psi):
            raise AssertionError('Numerical Problems')
Beispiel #7
0
def run_single_qubit_measure():
    """Run measurement experiments with single qubits."""

    # Construct Hamiltonian.
    a = random.random()
    b = random.random()
    c = random.random()
    hamil = (a * ops.PauliX() + b * ops.PauliY() + c * ops.PauliZ())

    # Compute known minimum eigenvalue.
    eigvals = np.linalg.eigvalsh(hamil)

    min_val = 1000.0
    for i in range(0, 360, 5):
        for j in range(0, 180, 5):

            theta = np.pi * i / 360.0
            phi = np.pi * j / 180.0

            # X Basis
            qc = single_qubit_ansatz(theta, phi)
            qc.h(0)
            val_a = a * qc.pauli_expectation(0)

            # Y Basis
            qc = single_qubit_ansatz(theta, phi)
            qc.sdag(0)
            qc.h(0)
            val_b = b * qc.pauli_expectation(0)

            # Z Basis
            qc = single_qubit_ansatz(theta, phi)
            val_c = c * qc.pauli_expectation(0)

            expectation = val_a + val_b + val_c
            if expectation < min_val:
                min_val = expectation

    print('Minimum eigenvalue: {:.3f}, Delta: {:.3f}'.format(
        eigvals[0], min_val - eigvals[0]))
Beispiel #8
0
 def y(self, idx: int):
     self.apply1(ops.PauliY(), idx, 'y')
Beispiel #9
0
 def cy(self, idx0: int, idx1: int):
     self.applyc(ops.PauliY(), idx0, idx1, 'cy')
Beispiel #10
0
 def test_unitary(self):
   self.assertTrue(ops.PauliX().is_unitary())
   self.assertTrue(ops.PauliY().is_unitary())
   self.assertTrue(ops.PauliZ().is_unitary())
   self.assertTrue(ops.Identity().is_unitary())
Beispiel #11
0
  def test_yroot_gate(self):
    """Test that Yroot^2 == Y."""

    t = ops.Yroot()
    self.assertTrue(t(t).is_close(ops.PauliY()))
Beispiel #12
0
 def cy(self, idx0, idx1):
     self.apply_controlled(ops.PauliY(), idx0, idx1, 'cy')
Beispiel #13
0
def two_qubit():
    """Compute Pauli representation for two-qubit system."""

    for iteration in range(10):

        # First we construct a circuit with two, very random qubits.
        #
        qc = circuit.qc('random qubit')
        qc.qubit(random.random())
        qc.qubit(random.random())

        # Potentially entangle them.
        qc.h(0)
        qc.cx(0, 1)

        # Additionally rotate around randomly.
        for i in range(2):
            qc.rx(i, math.pi * random.random())
            qc.ry(i, math.pi * random.random())
            qc.rz(i, math.pi * random.random())

        # Compute density matrix.
        rho = qc.psi.density()

        # Every rho can be put in the 2-qubit Pauli representation,
        # which is this Sum over i, j from 0 to 3 inclusive, representing
        # the four Pauli matrices (including the Identity):
        #
        #                 3
        #    rho = 1/4 * Sum(c_ij * Pauli_i kron Pauli_j)
        #                i,j=0
        #
        # To compute the various factors c_ij, we multiply the Pauli
        # tensor products with the density matrix and take the trace. This
        # trace is the computed factor:
        #
        paulis = [ops.Identity(), ops.PauliX(), ops.PauliY(), ops.PauliZ()]
        c = np.zeros((4, 4), dtype=np.complex64)
        for i in range(4):
            for j in range(4):
                tprod = paulis[i] * paulis[j]
                c[i][j] = np.trace(rho @ tprod)

        # To test whether the two qubits are entangled, the diagonal factors
        # (without c[0][0]) are added up. If the sum is < 1.0, the qubit
        # states are still seperable.
        #
        diag = np.abs(c[1][1]) + np.abs(c[2][2]) + np.abs(c[3][3])
        print(f'{iteration}: diag: {diag:5.2f} ', end='')
        if diag > 1.0:
            print('--> Entangled')
        else:
            print('Seperable')

        # Let's verify the result and construct a density matrix
        # from the Pauli matrices using the computed factors:
        #
        new_rho = np.zeros((4, 4), dtype=np.complex64)
        for i in range(4):
            for j in range(4):
                tprod = paulis[i] * paulis[j]
                new_rho = new_rho + c[i][j] * tprod

        if not np.allclose(rho, new_rho / 4, atol=1e-5):
            raise AssertionError('Invalid Pauli Representation')