예제 #1
0
 def test_circuit_of_circuit(self):
     c1 = circuit.qc('c1')
     c1.reg(6, 0)
     c1.x(0)
     c1.cx(1, 2)
     c2 = circuit.qc('c2', eager=False)
     c2.x(1)
     c2.cx(3, 1)
     c1.qc(c2, 0)
     c1.qc(c2, 1)
     c1.qc(c2, 2)
     self.assertEqual(8, c1.ir.ngates)
예제 #2
0
    def test_toffoli(self):
        qc = circuit.qc()
        qc.bitstring(1, 1, 0, 1, 1)
        qc.toffoli(0, 1, 3)
        self.compare_to(qc.psi, 1, 1, 0, 0, 1)

        qc = circuit.qc()
        qc.bitstring(1, 1, 0, 1, 1)
        qc.toffoli(4, 3, 0)
        self.compare_to(qc.psi, 0, 1, 0, 1, 1)

        qc = circuit.qc()
        qc.bitstring(1, 1, 0, 1, 1)
        qc.toffoli(1, 2, 3)
        self.compare_to(qc.psi, 1, 1, 0, 1, 1)
예제 #3
0
    def test_cswap(self):
        qc = circuit.qc()
        qc.bitstring(1, 1, 0, 1, 1)
        qc.cswap(1, 2, 3)
        self.compare_to(qc.psi, 1, 1, 1, 0, 1)

        qc = circuit.qc()
        qc.bitstring(1, 1, 0, 1, 0)
        qc.cswap(2, 3, 4)
        self.compare_to(qc.psi, 1, 1, 0, 1, 0)

        qc = circuit.qc()
        qc.bitstring(1, 1, 0, 1, 0)
        qc.cswap(3, 2, 1)
        self.compare_to(qc.psi, 1, 0, 1, 1, 0)
예제 #4
0
 def test_multi0(self):
     c = circuit.qc('multi', eager=True)
     comp = c.reg(4, (1, 0, 0, 1))
     aux = c.reg(4)
     ctl = [0, [1], [2]]
     c.multi_control(ctl, 3, aux, ops.PauliX(), f'multi-x({ctl}, 5)')
     self.assertGreater(c.psi.prob(1, 0, 0, 0, 0, 0, 0, 0), 0.99)
예제 #5
0
def simple_walk():
  """Simple quantum walk, allowing initial experiments."""

  nbits = 8
  qc = circuit.qc('simple_walk')
  x = qc.reg(nbits, 0b10000000)
  aux = qc.reg(nbits, 0)
  coin = qc.reg(1, 0)

  for _ in range(32):
    # Using a Hadamard coin, others are possible, of course.
    qc.h(coin[0])
    incr(qc, 0, nbits, aux, [coin[0]])
    decr(qc, 0, nbits, aux, [[coin[0]]])

  # Find and print the non-zero amplitudes for all states
  for bits in helper.bitprod(nbits):
    idx_bits = bits
    for i in range(nbits):
        idx_bits = idx_bits + (0,)
    idx_bits0 = idx_bits + (0,)
    idx_bits1 = idx_bits + (1,)

    # Printing bits0 only, this can be changed, of course.
    if qc.psi.ampl(*idx_bits0) != 0.0:
      print('{:5.1f} {:5.4f}'.format(float(helper.bits2val(bits)),
                                     qc.psi.ampl(*idx_bits0).real))
예제 #6
0
파일: circuit_test.py 프로젝트: qcc4cp/qcc
  def test_x_error_first_approach(self):
    error_qubit = 0

    qc = circuit.qc('x-flip / correction')
    qc.qubit(alpha=0.6)
    qc.reg(2, 0)
    qc.cx(0, 1)
    qc.cx(0, 2)

    # insert error (index 0, 1, or 2)
    qc.x(error_qubit)

    syndrom = qc.reg(2, 0)
    qc.cx(0, syndrom[0])
    qc.cx(1, syndrom[0])
    qc.cx(1, syndrom[1])
    qc.cx(2, syndrom[1])

    # Measure syndrom qubit 3, 4:
    #   00  - nothing needs to be done
    #   01  - x(2)
    #   10  - x(0)
    #   11  - x(1)
    qc.x(error_qubit)
    p2, _ = qc.measure_bit(error_qubit, 0)
    self.assertTrue(np.allclose(p2, 0.36, atol=0.001))
예제 #7
0
def run_two_qubit_zi_experiment():
    """Run VQE experiments with a given ansatz."""

    # Best achieved result. Goal is to get as close to +1 as possible.
    max_expect = 0.0

    # Perform experiments with randomly selected angles.
    for experiment in range(flags.FLAGS.experiments):
        # Pick random angles.
        for i in range(10):
            angles[i] = random.random() * 2.0 * math.pi

        # Construct and run the circuit.
        qc = circuit.qc('vqe')
        full_ansatz(qc)
        qc.z(0)

        # Measure the probablities as computed from the amplitudes.
        # We only do this once per experiment.
        p0, _ = qc.measure_bit(0, collapse=True)
        p1, _ = qc.measure_bit(1, collapse=True)

        # Simulate multiple measurements by sampling over the probabilities
        # to obtain a distribution of sampled states. The measurements above
        # are the probablities that a state would be found in the |0> state.
        # For each bit, we compare this probability against another random value r.
        # If the measured probability is < r, we pretend we've actually measured an
        # |0> state, else a |1> state. We do this via sample_state() on both qubits.
        #
        num_shots = flags.FLAGS.shots
        counts = [0] * 4
        for _ in range(num_shots):
            bit0 = qc.sample_state(p0)
            bit1 = qc.sample_state(p1)
            counts[bit1 * 2 + bit0] += 1

        # Compute the expectation value from samples measurements. Again,
        #   |00> and |01> map to Eigenvalue +1
        #   |10> and |11> map to Eigenvalue -1
        #
        # This is a bit of cheating. In this example we _know_ the
        # Eigenvalues and can therefore properly construct the expectation
        # value. I'd think in the general case it has to actually be
        # computed with <psi|H|psi>, which is still O(n^2).
        #
        expect = (counts[0] + counts[1] - counts[2] - counts[3]) / num_shots

        # Update and print currently best result.
        #
        if expect > max_expect:
            max_expect = expect
            print(
                'Max expecation of H for experiment {:5d}: {:.4f} (target: 1.0)'
                .format(experiment, max_expect))
            print('  |00>: {}, |01>: {}, |10>: {}, |11>: {}'.format(
                counts[0], counts[1], counts[2], counts[3]))
            print('  ', end='')
            for i in range(10):
                print('{:.1f} '.format(angles[i] / 2 / math.pi * 360), end='')
            print()
예제 #8
0
 def test_multi1(self):
     c = circuit.qc('multi', eager=False)
     comp = c.reg(6)
     aux = c.reg(6)
     ctl = [0, 1, 2, 3, 4]
     c.multi_control(ctl, 5, aux, ops.PauliX(), f'multi-x({ctl}, 5)')
     self.assertEqual(41, c.ir.ngates)
예제 #9
0
def single_qubit_ansatz(theta: float, phi: float) -> circuit.qc:
    """Generate a single qubit ansatz."""

    qc = circuit.qc('single-qubit ansatz Y')
    qc.qubit(1.0)
    qc.rx(0, theta)
    qc.ry(0, phi)
    return qc
예제 #10
0
파일: order_finding.py 프로젝트: qcc4cp/qcc
def main(argv):
    if len(argv) > 1:
        raise app.UsageError('Too many command-line arguments.')
    print('Order finding.')

    number = flags.FLAGS.N
    a = flags.FLAGS.a

    # The classical part are handled in 'shor_classic.py'
    nbits = number.bit_length()
    print('Shor: N = {}, a = {}, n = {} -> qubits: {}'.format(
        number, a, nbits, nbits * 4 + 2))
    qc = circuit.qc('order_finding')

    # Aux register for additional and multiplication.
    aux = qc.reg(nbits + 2, name='q0')

    # Register for QFT. This reg will hold the resulting x-value.
    up = qc.reg(nbits * 2, name='q1')

    # Register for multiplications.
    down = qc.reg(nbits, name='q2')

    qc.h(up)
    qc.x(down[0])
    for i in range(nbits * 2):
        cmultmodn(qc, up[i], down, aux, int(a**(2**i)), number, nbits)
    inverse_qft(qc, up, 2 * nbits, with_swaps=1)

    qc.dump_to_file()

    print('Measurement...')
    total_prob = 0.0
    for bits in helper.bitprod(nbits * 4 + 2):
        prob = qc.psi.prob(*bits)
        if prob > 0.01:
            intval = helper.bits2val(bits[nbits + 2:nbits + 2 +
                                          nbits * 2][::-1])
            phase = helper.bits2frac(bits[nbits + 2:nbits + 2 +
                                          nbits * 2][::-1])

            r = fractions.Fraction(phase).limit_denominator(8).denominator
            guesses = [
                math.gcd(a**(r // 2) - 1, number),
                math.gcd(a**(r // 2) + 1, number)
            ]

            print(
                'Final x: {:3d} phase: {:3f} prob: {:.3f} factors: {}'.format(
                    intval, phase, prob.real, guesses))

            total_prob += qc.psi.prob(*bits)
            if total_prob > 0.999:
                break

    print(qc.stats())
예제 #11
0
    def test_circuit_of_inv_circuit(self):
        c1 = circuit.qc('c1')
        c1.reg(6, 0)
        c1.x(0)
        c1.rx(1, math.pi / 3)
        c1.h(1)
        c1.cz(3, 2)

        c2 = c1.inverse()
        c1.qc(c2, 0)
        self.assertEqual(8, c1.ir.ngates)
예제 #12
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')
예제 #13
0
def experiment_decr():
  """Run a few decr experiments."""
  qc = circuit.qc('decr')
  x = qc.reg(4, 15)
  aux = qc.reg(4)

  for val in range(15, 0, -1):
    decr(qc, 0, 4, aux)

    maxbits, _ = qc.psi.maxprob()
    res = helper.bits2val(maxbits[0:4])
    if val-1 != res:
      raise AssertionError('Invalid Result')
예제 #14
0
def experiment_qc(a, b, cin, expected_sum, expected_cout):
  """Run a simple classic experiment, check results."""

  qc = circuit.qc('classic')

  qc.bitstring(a, b, cin, 0, 0)
  fulladder_qc(qc)

  bsum, _ = qc.measure_bit(3, tostate=1, collapse=False)
  bout, _ = qc.measure_bit(4, tostate=1, collapse=False)
  print(f'a: {a} b: {b} cin: {cin} sum: {bsum} cout: {bout}')
  if bsum != expected_sum or bout != expected_cout:
    raise AssertionError('invalid results')
예제 #15
0
def experiment_mod_9():
  """Run a few incr-mod-9 experiments."""

  qc = circuit.qc('incr')
  x = qc.reg(4, 0)
  aux = qc.reg(5)  # extra aux

  for val in range(18):
    incr_mod_9(qc, aux)
    maxbits, _ = qc.psi.maxprob()
    res = helper.bits2val(maxbits[0:4])
    if ((val+1) % 9) != res:
      raise AssertionError('Invalid Result')
예제 #16
0
파일: arith_quantum.py 프로젝트: xbe/qcc
def arith_quantum(n, init_a, init_b, factor=1.0, dumpit=False):
    """Run a quantum add experiment."""

    qc = circuit.qc('qadd')
    a = qc.reg(n + 1, helper.val2bits(init_a, n)[::-1], name='a')
    b = qc.reg(n + 1, helper.val2bits(init_b, n)[::-1], name='b')
    for i in range(0, n + 1):
        qft(qc, a, n - i)
    for i in range(0, n + 1):
        evolve(qc, a, b, n - i, factor)
    for i in range(0, n + 1):
        inverse_qft(qc, a, i)
    if dumpit:
        qc.dump_to_file()
    check_result(qc.psi, init_a, init_b, n + 1, factor)
예제 #17
0
파일: circuit_test.py 프로젝트: qcc4cp/qcc
  def test_shor_9_qubit_correction(self):
    for i in range(9):
      qc = circuit.qc('shor-9')
      # print(f'Initialize qubit as 0.60|0> + 0.80|1>, error on qubit {i}')
      qc.qubit(0.6)
      qc.reg(8, 0)

      # Left Side.
      qc.cx(0, 3)
      qc.cx(0, 6)
      qc.h(0)
      qc.h(3)
      qc.h(6)
      qc.cx(0, 1)
      qc.cx(0, 2)
      qc.cx(3, 4)
      qc.cx(3, 5)
      qc.cx(6, 7)
      qc.cx(6, 8)

      # Error insertion, use x(i), y(i), or z(i)
      qc.x(i)

      # Fix.
      qc.cx(0, 1)
      qc.cx(0, 2)
      qc.ccx(1, 2, 0)

      qc.h(0)
      qc.cx(3, 4)
      qc.cx(3, 5)
      qc.ccx(4, 5, 3)
      qc.h(3)
      qc.cx(6, 7)
      qc.cx(6, 8)
      qc.ccx(7, 8, 6)
      qc.h(6)

      qc.cx(0, 3)
      qc.cx(0, 6)
      qc.ccx(6, 3, 0)

      prob0, _ = qc.measure_bit(0, 0, collapse=False)
      prob1, _ = qc.measure_bit(0, 1, collapse=False)
      self.assertTrue(math.isclose(math.sqrt(prob0), 0.6, abs_tol=0.001))
      self.assertTrue(math.isclose(math.sqrt(prob1), 0.8, abs_tol=0.001))
예제 #18
0
    def test_circuit_exec(self):
        c = circuit.qc('c', eager=False)
        c.reg(3, 0)
        c.h(0)
        c.h(1)
        c.h(2)

        c.run()
        self.assertEqual(3, c.ir.ngates)
        for i in range(8):
            self.assertGreater(c.psi[i], 0.3)

        c.run()
        self.assertEqual(3, c.ir.ngates)
        self.assertGreater(c.psi[0], 0.99)
        for i in range(1, 8):
            self.assertLess(c.psi[i], 0.01)
예제 #19
0
    def test_opt(self):
        def decr(qc, idx, nbits, aux, controller=[]):
            for i in range(0, nbits):
                ctl = controller.copy()
                for j in range(nbits - 1, i, -1):
                    ctl.append([j + idx])
            qc.multi_control(ctl, i + idx, aux, ops.PauliX(), "multi-0-X")

        qc = circuit.qc('decr')
        x = qc.reg(4, 15)
        aux = qc.reg(4)

        for val in range(15, 0, -1):
            decr(qc, 0, 4, aux)

        # print(qc.stats())
        qc.optimize()
예제 #20
0
파일: circuit_test.py 프로젝트: qcc4cp/qcc
  def test_x_error(self):
    qc = circuit.qc('x-flip / correction')
    qc.qubit(0.6)

    qc.reg(2, 0)
    qc.cx(0, 2)
    qc.cx(0, 1)
    self.assertTrue(np.allclose(qc.psi.prob(0, 0, 0), 0.36, atol=0.001))
    self.assertTrue(np.allclose(qc.psi.prob(1, 1, 1), 0.64, atol=0.001))

    qc.x(0)

    # Fix
    qc.cx(0, 1)
    qc.cx(0, 2)
    qc.ccx(1, 2, 0)
    p0, _ = qc.measure_bit(0, 0, collapse=False)
    self.assertTrue(np.allclose(p0, 0.36))
    p1, _ = qc.measure_bit(0, 1, collapse=False)
    self.assertTrue(np.allclose(p1, 0.64))
예제 #21
0
파일: larose_benchmark.py 프로젝트: xbe/qcc
def main(argv):
    if len(argv) > 1:
        raise app.UsageError('Too many command-line arguments.')

    print(f'LaRose benchmark with {flags.FLAGS.nbits} qubits, ' +
          f'depth: {flags.FLAGS.depth}...')

    qc = circuit.qc(eager=False)
    qc.reg(flags.FLAGS.nbits,
           random.randint(0, 2 ^ flags.FLAGS.nbits),
           name='q')

    for d in range(flags.FLAGS.depth):
        print(f'  depth: {d}')
        for bit in range(flags.FLAGS.nbits):
            qc.h(bit)
            qc.v(bit)
            if bit > 0:
                qc.cx(bit, 0)
    qc.dump_to_file()
예제 #22
0
파일: arith_quantum.py 프로젝트: xbe/qcc
def arith_quantum_constant(n, init_a, c):
    """Run a quantum add-constant experiment."""

    qc = circuit.qc('qadd')
    a = qc.reg(n + 1, helper.val2bits(init_a, n)[::-1], name='a')
    for i in range(0, n + 1):
        qft(qc, a, n - i)

    angles = precompute_angles(c, n)
    for i in range(0, n):
        qc.u1(a[i], angles[i])

    for i in range(0, n + 1):
        inverse_qft(qc, a, i)

    maxbits, _ = qc.psi.maxprob()
    result = helper.bits2val(maxbits[0:n][::-1])
    if result != init_a + c:
        print(f'{init_a} + {c} = {result}')
        raise AssertionError('incorrect addition')
예제 #23
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')
예제 #24
0
파일: circuit_test.py 프로젝트: qcc4cp/qcc
  def test_multi_n(self):
    c = circuit.qc('multi', eager=True)
    c.reg(4, (1, 0, 0, 1))
    aux = c.reg(4)
    ctl = []
    c.multi_control(ctl, 3, aux, ops.PauliX(), 'single')
    self.assertGreater(c.psi.prob(1, 0, 0, 0, 0, 0, 0, 0), 0.99)

    ctl = [0]
    c.multi_control(ctl, 3, aux, ops.PauliX(), 'single')
    self.assertGreater(c.psi.prob(1, 0, 0, 1, 0, 0, 0, 0), 0.99)

    ctl = [1]
    c.multi_control(ctl, 3, aux, ops.PauliX(), 'single')
    self.assertGreater(c.psi.prob(1, 0, 0, 1, 0, 0, 0, 0), 0.99)

    ctl = [[1]]
    c.multi_control(ctl, 3, aux, ops.PauliX(), 'single')
    self.assertGreater(c.psi.prob(1, 0, 0, 0, 0, 0, 0, 0), 0.99)

    ctl = [0, [1], [2]]
    c.multi_control(ctl, 3, aux, ops.PauliX(), 'single')
    self.assertGreater(c.psi.prob(1, 0, 0, 1, 0, 0, 0, 0), 0.99)
예제 #25
0
파일: tensor_math.py 프로젝트: xbe/qcc
 def bench():
     qc = circuit.qc()
     qc.rand(nbits)
     for i in range(nbits):
         qc.h(i)
예제 #26
0
def main(argv):
    if len(argv) > 1:
        raise app.UsageError('Too many command-line arguments.')

    # Alice has qubits 1 and 4
    # Bob   has qubits 2 and 3
    qc = circuit.qc('swap the entanglement', eager=True)
    reg = qc.reg(4, 0)

    # Qubits 1 and 2 are entangled, and so are qubits 3 and 4:
    #
    # Alice  1        4
    #        |        |
    # Bob    2        3
    #
    qc.h(0)
    qc.cx(0, 1)
    qc.h(2)
    qc.cx(2, 3)

    # Now Alice and Bob physically separate.
    # Alice keeps qubits 1 and 4 on Earth.
    # Bob takes qubits 2 and 3 to the Moon.

    # ... travel, space ships, etc...

    # Alice performs a Bell measurement between qubits 1 and 4,
    # which means to apply a reverse entangler circuit:
    #
    # Alice  1~~~BM~~~4
    #        |        |
    # Bob    2        3
    #
    qc.cx(0, 3)
    qc.h(0)

    # At this point, Alice will physically measure her qubits 1 and 4.
    # There are four possible outcomes, |00>, |01>, |10>, and |11>,
    #
    # Depending on that outcome, now qubits 2 and 3 will also be
    # in a corresponding Bell state! The entanglement has been
    # teleported to qubits 2 and 3, even though they never
    # interacted before!
    #
    # Alice  1        4
    #        |        |
    # Bob    2 ~~~~~~ 3
    #
    #
    # To check the results:
    #
    # Iterate over the four possibilities
    # This array 'cases' represents 2 cases in each entry, either
    #   qubit entries 0, 1, 2, 3  or
    #   qubit entries 0, 5, 6, 3 (multiplied by c[7])
    #
    # This covers all expected results.
    #
    # qubits   0  1  2  3       1  2   factor
    #-----------------------------------------
    cases = [[0, 0, 0, 0, 1.0, 1, 1, 1.0], [0, 0, 1, 1, 1.0, 1, 0, 1.0],
             [1, 0, 0, 0, 1.0, 1, 1, -1.0], [1, 0, 1, 1, 1.0, 1, 0, -1.0]]

    c07 = 1 / math.sqrt(2)
    psi = qc.psi
    for c in cases:
        qc.psi = psi

        qc.measure_bit(0, c[0], collapse=True)
        qc.measure_bit(3, c[3], collapse=True)
        qc.psi.dump(f'after measuring |{c[0]}..{c[3]}>')

        if not math.isclose(np.real(qc.psi.ampl(c[0], c[1], c[2], c[3])),
                            c07,
                            abs_tol=1e-5):
            raise AssertionError('Invalid measurement results')
        if not math.isclose(np.real(qc.psi.ampl(c[0], c[5], c[6], c[3])),
                            c07 * c[7],
                            abs_tol=1e-5):
            raise AssertionError('Invalid measurement results')
예제 #27
0
 def compare_to(self, psi, *bits):
     qc = circuit.qc()
     qc.bitstring(*bits)
     self.assertTrue(psi.is_close(qc.psi))
예제 #28
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')
예제 #29
0
 def test_swap(self):
     qc = circuit.qc()
     qc.bitstring(1, 1, 0, 1, 1)
     qc.swap(1, 2)
     self.compare_to(qc.psi, 1, 0, 1, 1, 1)