Beispiel #1
0
def run_experiment():
    """Run single, defined experiment for secret 11."""

    psi = state.zeros(4)
    u = make_u()

    psi = ops.Hadamard(2)(psi)
    psi = u(psi)
    psi = ops.Hadamard(2)(psi)

    # Because of the xor patterns (Yanofski 6.64)
    # measurement will only find those qubit strings where
    # the scalar product of z (lower bits) and secret string:
    #    <z, c> = 0
    #
    # This should measure |00> and |11> with equal probability.
    # If true, than we can derive the secret string as being 11
    # because f(00) = f(11) and because f(00) = f(00 ^ c) -> c = 11
    #
    print('Measure likely states (want: pairs of 00 or 11):')
    for bits in helper.bitprod(4):
        if psi.prob(*bits) > 0.01:
            if (bits[0] == 0 and bits[1] == 1) or (bits[0] == 1
                                                   and bits[1] == 0):
                raise AssertionError('Invalid Results')
            print('|{}{} {}{}> = 0 : {:.2f}  dot % 2: {:.2f}'.format(
                bits[0], bits[1], bits[2], bits[3], psi.prob(*bits),
                dot2(bits)))
Beispiel #2
0
def run_experiment(a1: np.complexfloating, a2: np.complexfloating,
                   target: float) -> None:
    """Construct swap test circuit and measure."""

    # The circuit is quite simple:
    #
    # |0> --- H --- o --- H --- Measure
    #               |
    # a1  --------- x ---------
    #               |
    # a2  ----------x ---------

    psi = state.bitstring(0) * state.qubit(a1) * state.qubit(a2)
    psi = ops.Hadamard()(psi, 0)
    psi = ops.ControlledU(0, 1, ops.Swap(1, 2))(psi)
    psi = ops.Hadamard()(psi, 0)

    # Measure once.
    p0, _ = ops.Measure(psi, 0)
    if abs(p0 - target) > 0.05:
        raise AssertionError(
            'Probability {:.2f} off more than 5% from target {:.2f}'.format(
                p0, target))
    print('Similarity of a1: {:.2f}, a2: {:.2f} ==>  %: {:.2f}'.format(
        a1, a2, 100.0 * p0))
Beispiel #3
0
def basis_kick1():
  """Simple H-Cnot-H phase kick."""

  psi = state.zeros(3) * state.ones(1)
  psi = ops.Hadamard(4)(psi)
  psi = ops.Cnot(2, 3)(psi, 2)
  psi = ops.Hadamard(4)(psi)
  if psi.prob(0, 0, 1, 1) < 0.9:
    raise AssertionError('Something is wrong with the phase kick')
Beispiel #4
0
def run_experiment(nbits: int) -> None:
    """Run full experiment for a given number of bits."""

    c = make_c(nbits - 1)
    u = make_u(nbits, c)

    psi = state.zeros(nbits - 1) * state.ones(1)
    psi = ops.Hadamard(nbits)(psi)
    psi = u(psi)
    psi = ops.Hadamard(nbits)(psi)

    check_result(nbits, c, psi)
Beispiel #5
0
def run_oracle_experiment(nbits) -> None:
    """Run full experiment for a given number of bits."""

    c = make_c(nbits - 1)
    f = make_oracle_f(c)
    u = ops.OracleUf(nbits, f)

    psi = state.zeros(nbits - 1) * state.ones(1)
    psi = ops.Hadamard(nbits)(psi)
    psi = u(psi)
    psi = ops.Hadamard(nbits)(psi)

    check_result(nbits, c, psi)
Beispiel #6
0
  def test_double_hadamard(self):
    """Check that Hadamard is fully reversible."""

    psi = state.zeros(2)

    psi2 = ops.Hadamard(2)(ops.Hadamard(2)(psi))
    self.assertEqual(psi2.nbits, 2)
    self.assertTrue(psi.is_close(psi2))

    combo = ops.Hadamard(2) @ ops.Hadamard(2)
    psi3 = combo(psi)
    self.assertEqual(psi3.nbits, 2)
    self.assertTrue(psi.is_close(psi3))
    self.assertTrue(psi.density().is_pure())
Beispiel #7
0
def main(argv):
  if len(argv) > 1:
    raise app.UsageError('Too many command-line arguments.')

  num_experiments = 10
  depth = 8
  recursion = 4
  print('SK algorithm - depth: {}, recursion: {}, experiments: {}'.
        format(depth, recursion, num_experiments))

  base = [to_su2(ops.Hadamard()), to_su2(ops.Tgate())]
  gates = create_unitaries(base, depth)
  sum_dist = 0.0
  for i in range(num_experiments):
      U = (ops.RotationX(2.0 * np.pi * random.random()) @
           ops.RotationY(2.0 * np.pi * random.random()) @
           ops.RotationZ(2.0 * np.pi * random.random()))

      U_approx = sk_algo(U, gates, recursion)

      dist = trace_dist(U, U_approx)
      sum_dist += dist

      phi1 = U(state.zero)
      phi2 = U_approx(state.zero)
      print('[{:2d}]: Trace Dist: {:.4f} State: {:6.4f}%'.
            format(i, dist,
                   100.0 * (1.0 - np.real(np.dot(phi1, phi2.conj())))))

  print('Gates: {}, Mean Trace Dist:: {:.4f}'.
        format(len(gates), sum_dist / num_experiments))
Beispiel #8
0
def random_gates(min_length, max_length, num_experiments):
  """Just create random sequences, find the best."""

  base = [to_su2(ops.Hadamard()), to_su2(ops.Tgate())]

  U = (ops.RotationX(2.0 * np.pi * random.random()) @
       ops.RotationY(2.0 * np.pi * random.random()) @
       ops.RotationZ(2.0 * np.pi * random.random()))

  min_dist = 1000
  for _ in range(num_experiments):
    seq_length = min_length + random.randint(0, max_length)
    U_approx = ops.Identity()

    for _ in range(seq_length):
      g = random.randint(0, 1)
      U_approx = U_approx @ base[g]

    dist = trace_dist(U, U_approx)
    min_dist = min(dist, min_dist)

  phi1 = U(state.zero)
  phi2 = U_approx(state.zero)
  print('Trace Dist: {:.4f} State: {:6.4f}%'.
        format(min_dist,
               100.0 * (1.0 - np.real(np.dot(phi1, phi2.conj())))))
Beispiel #9
0
    def test_had_cnot_had(self):
        """Exercise 4.20 in Nielson, Chuang, H2.Cnot(0,1).H2==Cnot(1,0)."""

        h2 = ops.Hadamard(2)
        cnot = ops.Cnot(0, 1)
        op = h2(cnot(h2))
        self.assertTrue(op.is_close(ops.Cnot(1, 0)))
Beispiel #10
0
    def test_density_to_cartesian(self):
        """Test density to cartesian conversion."""

        q0 = state.zeros(1)
        rho = q0.density()
        x, y, z = helper.density_to_cartesian(rho)
        self.assertEqual(x, 0.0)
        self.assertEqual(y, 0.0)
        self.assertEqual(z, 1.0)

        q1 = state.ones(1)
        rho = q1.density()
        x, y, z = helper.density_to_cartesian(rho)
        self.assertEqual(x, 0.0)
        self.assertEqual(y, 0.0)
        self.assertEqual(z, -1.0)

        qh = ops.Hadamard()(q0)
        rho = qh.density()
        x, y, z = helper.density_to_cartesian(rho)
        self.assertTrue(math.isclose(np.real(x), 1.0, abs_tol=1e-6))
        self.assertTrue(math.isclose(np.real(y), 0.0))
        self.assertTrue(math.isclose(np.real(z), 0.0, abs_tol=1e-6))

        qr = ops.RotationZ(90.0 * math.pi / 180.0)(qh)
        rho = qr.density()
        x, y, z = helper.density_to_cartesian(rho)
        self.assertTrue(math.isclose(np.real(x), 0.0, abs_tol=1e-6))
        self.assertTrue(math.isclose(np.real(y), -1.0, abs_tol=1e-6))
        self.assertTrue(math.isclose(np.real(z), 0.0, abs_tol=1e-6))
Beispiel #11
0
def operator_order():
    """Evaluate order of operations and corresponding matmuls."""

    hi = ops.Hadamard() * ops.Identity()
    cx = ops.Cnot(0, 1)

    # Make sure that the order of evaluation is correct. For example,
    # this simple circuit:
    #
    # |0> --- H --- o ---
    #               |
    # |0> ----------X ---
    #
    #  p0   p1     p2
    #
    # Can be evaluated step wise, applying each gate to psi:
    psi_0 = state.zeros(2)
    psi_1 = hi(psi_0)
    psi_2 = cx(psi_1)

    # Or via a combined operator. Yet, the order ot the ops
    # has to be reversed from above picture:
    combined_op = (cx @ hi)
    combined_psi = state.zeros(2)
    combined_psi_2 = combined_op(combined_psi)
    if not psi_2.is_close(combined_psi_2):
        raise AssertionError('Invalid order of operators from matmul')

    # This can also be expressed via the function call construct:
    combined_f = hi(cx)
    combined_f_psi = state.zeros(2)
    combined_f_psi_2 = combined_f(combined_f_psi)
    if not psi_2.is_close(combined_f_psi_2):
        raise AssertionError('Invalid order of operators from call construct')
Beispiel #12
0
    def with_matmul():
        psi = state.zeros(n)
        ident = ops.Identity(n)
        h = ops.Hadamard(n)

        psi = (ident @ h)(psi)
        return psi
Beispiel #13
0
  def test_padding(self):
    ident = ops.Identity(3)
    h = ops.Hadamard()

    op = ident(h, 0)
    op_manual = h * ops.Identity(2)
    self.assertTrue(op.is_close(op_manual))
    op = ident(h, 1)
    op_manual = ops.Identity() * h * ops.Identity()
    self.assertTrue(op.is_close(op_manual))
    op = ident(h, 2)
    op_manual = ops.Identity(2) * h
    self.assertTrue(op.is_close(op_manual))

    ident = ops.Identity(4)
    cx = ops.Cnot(0, 1)

    op = ident(cx, 0)
    op_manual = cx * ops.Identity(2)
    self.assertTrue(op.is_close(op_manual))
    op = ident(cx, 1)
    op_manual = ops.Identity(1) *  cx * ops.Identity(1)
    self.assertTrue(op.is_close(op_manual))
    op = ident(cx, 2)
    op_manual = ops.Identity(2) *  cx
    self.assertTrue(op.is_close(op_manual))
Beispiel #14
0
def main(argv):
    if len(argv) > 1:
        raise app.UsageError('Too many command-line arguments.')

    # Step 1: Alice and Bob share an entangled pair, and separate.
    psi = bell.bell_state(0, 0)

    # Step 2: Alice wants to teleport a qubit |x> to Bob,
    #         which is in the state:
    #         |x> = a|0> + b|1> (with a^2 + b^2 == 1)
    a = 0.6
    b = math.sqrt(1.0 - a * a)
    x = state.qubit(a, b)
    print('Quantum Teleportation')
    print('Start with EPR Pair a={:.2f}, b={:.2f}'.format(a, b))

    # Produce combined state.
    alice = x * psi

    # Alice lets the 1st qubit interact with the 2nd qubit, which is her
    # part of the entangle state with Bob.
    alice = ops.Cnot(0, 1)(alice)

    # Now she applies a Hadamard to qubit 0. Bob still owns qubit 2.
    alice = ops.Hadamard()(alice, idx=0)

    # Alices measures and communicates the result (|00>, |01>, ...) to Bob.
    alice_measures(alice, a, b, 0, 0)
    alice_measures(alice, a, b, 0, 1)
    alice_measures(alice, a, b, 1, 0)
    alice_measures(alice, a, b, 1, 1)
Beispiel #15
0
def run_experiment(nbits, flavor):
    """Run full experiment for a given flavor of f()."""

    f = make_f(nbits - 1, flavor)
    u = ops.OracleUf(nbits, f)

    psi = (ops.Hadamard(nbits - 1)(state.zeros(nbits - 1)) *
           ops.Hadamard()(state.ones(1)))
    psi = u(psi)
    psi = (ops.Hadamard(nbits - 1) * ops.Identity(1))(psi)

    # Measure all of |0>. If all close to 1.0, f() is constant.
    for idx in range(nbits - 1):
        p0, _ = ops.Measure(psi, idx, tostate=0, collapse=False)
        if not math.isclose(p0, 1.0, abs_tol=1e-5):
            return exp_balanced
    return exp_constant
Beispiel #16
0
    def by_op():
        psi = state.zeros(n)
        ident = ops.Identity(n)
        h = ops.Hadamard(n)

        psi = ident(psi)
        psi = h(psi)
        return psi
Beispiel #17
0
Datei: bell.py Projekt: xbe/qcc
def bell_state(a, b) -> state.State:
    """Make one of the four bell states with a, b from {0,1}."""

    if a not in [0, 1] or b not in [0, 1]:
        raise ValueError('Bell state arguments are bits and must be 0 or 1.')

    psi = state.bitstring(a, b)
    psi = ops.Hadamard()(psi)
    return ops.Cnot()(psi)
Beispiel #18
0
    def test_measure(self):
        psi = state.zeros(2)
        psi = ops.Hadamard()(psi)
        psi = ops.Cnot(0, 1)(psi)

        p0, psi2 = ops.Measure(psi, 0)
        self.assertTrue(math.isclose(p0, 0.5, abs_tol=1e-5))

        # Measure again - now state should have collapsed.
        p0, _ = ops.Measure(psi2, 0)
        self.assertTrue(math.isclose(p0, 1.0, abs_tol=1e-6))
Beispiel #19
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 #20
0
def run_experiment(nbits):
    """Run single, defined experiment for secret 11."""

    psi = state.zeros(nbits * 2)
    c = make_c(nbits)
    u = make_u(nbits, c)

    psi = ops.Hadamard(nbits)(psi)
    psi = u(psi)
    psi = ops.Hadamard(nbits)(psi)

    # Because of the xor patterns (Yanofski 6.64)
    # measurement will only find those qubit strings where
    # the scalar product of z (lower bits) and secret string:
    #    <z, c> = 0
    #
    print('Measure likely states:')
    for bits in helper.bitprod(nbits * 2):
        if psi.prob(*bits) > 0.0 and dot2(bits, nbits) < 1.0:
            print('|{}> = 0 : {:.2f}  dot % 2: {:.2f}'.format(
                bits, psi.prob(*bits), dot2(bits, nbits)))
Beispiel #21
0
def time_series(limit):
    """Simple time series for gate application."""
    def bench():
        psi = state.zeros(nbits)
        for i in range(nbits):
            psi = apply_single_gate(h, i, psi)

    h = ops.Hadamard()
    for i in range(10, limit):
        nbits = i
        print('qubit: {}, muls: {}, mem: {}k, time: {:.3f} secs'.format(
            nbits, 2**nbits * 4, 2**nbits * 16 / 1024,
            timeit.timeit(bench, number=1)))
Beispiel #22
0
Datei: bell.py Projekt: xbe/qcc
def ghz_state(nbits) -> state.State:
    """Make a maximally entangled nbits state (GHZ State)."""

    # Simple construction via:
    #
    # |0> --- H --- o ---------
    # |0> ----------X --- o ---
    # |0> ----------------X ---  ...
    #
    psi = state.zeros(nbits)
    psi = ops.Hadamard()(psi)
    for offset in range(nbits - 1):
        psi = ops.Cnot(0, 1)(psi, offset)
    return psi
Beispiel #23
0
def basis_changes():
  """Explore basis changes via Hadamard."""

  # Generate [1, 0]
  psi = state.zeros(1)

  # Hadamard will result in 1/sqrt(2) [1, 1] (|+>)
  psi = ops.Hadamard()(psi)

  # Generate [0, 1]
  psi = state.ones(1)

  # Hadamard on |1> will result in 1/sqrt(2) [1, -1] (|->)
  psi = ops.Hadamard()(psi)

  # Simple PauliX will result in 1/sqrt(2) [-1, 1]
  psi = ops.PauliX()(psi)

  # But back to computational, will result in -|1>.
  # Global phases can be ignored.
  psi = ops.Hadamard()(psi)
  if not np.allclose(psi[1], -1.0):
    raise AssertionError('Invalid basis change.')
Beispiel #24
0
def hipster_single():
    """Single-qubit Hipster Technique."""

    # This is a nice trick, outlined in this paper on "Hipster":
    #    https://arxiv.org/pdf/1601.07195.pdf
    #
    # The observation is that to apply a single-qubit gate to a
    # gubit with index i, take the binary representation of inidices and
    # apply the transformation matrix to the elements according
    # to the power of 2 index. Generally:
    # "Performing a single-qubit gate on qubit k of n-qubit quantum
    # register applies G to pairs of amplitudes whose indices differ in
    # k-th bits of their binary index".
    #
    # For example, for a 2-qubit system, to apply a gate to qubit 0:
    #    apply G to
    #    q11, q12   psi[0], psi[1]
    #    q21, q22   psi[2], psi[3]
    #
    # To apply to qubit 1:
    #    q11, q12   psi[0], psi[2]
    #    q21, q22   psi[1], psi[3]
    #
    # 'Outer loop' jumps by 2**(nbits+1)
    # 'Inner loop' jumps by 2**k
    #
    # To maintain the qubit / index ordering of this infrastructure,
    # the qubit index in the paper is reversed to the qubit index here.
    # (Hence the (nbits - qubit - 1) above)
    #

    # Make sure that for sample gates and all states the transformations
    # are identical.
    #
    for gate in (ops.PauliX(), ops.PauliZ(), ops.Hadamard(),
                 ops.RotationX(0.5)):
        nbits = 5
        for bits in helper.bitprod(nbits):
            psi = state.bitstring(*bits)
            qubit = random.randint(0, nbits - 1)

            # Full matrix (O(n*n).
            op = ops.Identity(qubit) * gate * ops.Identity(nbits - qubit - 1)
            psi1 = op(psi)

            # Single Qubit (O(n))
            psi = apply_single_gate(gate, qubit, psi)

            if not psi.is_close(psi1):
                raise AssertionError('Invalid Single Gate Application.')
Beispiel #25
0
def basis_changes():
    """Explore basis changes via Hadamard."""

    # Generate [1, 0]
    psi = state.zeros(1)

    # Hadamard will result in 1/sqrt(2) [1, 1] (|+>)
    psi = ops.Hadamard()(psi)

    # Generate [0, 1]
    psi = state.ones(1)

    # Hadamard on |1> will result in 1/sqrt(2) [1, -1] (|->)
    psi = ops.Hadamard()(psi)

    # Simple PauliX will result in 1/sqrt(2) [-1, 1]
    psi = ops.PauliX()(psi)

    # But back to computational, will result in -|1>, but phases
    # can be ignored.
    psi = ops.Hadamard()(psi)
    if psi[1] > -0.95:
        raise AssertionError('Invalid Basis Changes')
Beispiel #26
0
def bob_measures(psi: state.State, expect0: int, expect1: int):
    """Bob measures both bits (in computational basis)."""

    # Change Hadamard basis back to computational basis.
    psi = ops.Cnot(0, 1)(psi)
    psi = ops.Hadamard()(psi)

    p0, _ = ops.Measure(psi, 0, tostate=expect1)
    p1, _ = ops.Measure(psi, 1, tostate=expect0)

    if (not math.isclose(p0, 1.0, abs_tol=1e-6)
            or not math.isclose(p1, 1.0, abs_tol=1e-6)):
        raise AssertionError(f'Invalid Result p0 {p0} p1 {p1}')

    print(f'Expected/matched: |{expect0}{expect1}>.')
Beispiel #27
0
  def test_dft(self):
    """Build 'manually' a 3 qubit gate, Nielsen/Chuang Box 5.1."""

    h = ops.Hadamard()

    op = ops.Identity(3)
    op = op(h, 0)
    op = op(ops.ControlledU(1, 0, ops.Rk(2)), 0)  # S-gate
    op = op(ops.ControlledU(2, 0, ops.Rk(3)), 0)  # T-gate
    op = op(h, 1)
    op = op(ops.ControlledU(1, 0, ops.Rk(2)), 1)  # S-gate
    op = op(h, 2)
    op = op(ops.Swap(0, 2), 0)

    op3 = ops.Qft(3)
    self.assertTrue(op3.is_close(op))
Beispiel #28
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 #29
0
  def test_bloch(self):
    psi = state.zeros(1)
    x, y, z = helper.density_to_cartesian(psi.density())
    self.assertEqual(x, 0.0)
    self.assertEqual(y, 0.0)
    self.assertEqual(z, 1.0)

    psi = ops.PauliX()(psi)
    x, y, z = helper.density_to_cartesian(psi.density())
    self.assertEqual(x, 0.0)
    self.assertEqual(y, 0.0)
    self.assertEqual(z, -1.0)

    psi = ops.Hadamard()(psi)
    x, y, z = helper.density_to_cartesian(psi.density())
    self.assertTrue(math.isclose(x, -1.0, abs_tol=1e-6))
    self.assertTrue(math.isclose(y, 0.0, abs_tol=1e-6))
    self.assertTrue(math.isclose(z, 0.0, abs_tol=1e-6))
Beispiel #30
0
def basis_kick2():
  """Another way to look at this H-Cnot-H phase kick."""

  # This produces the vector [0, 1, 0, 0]
  psi = state.bitstring(0, 1)

  # Applying Hadamard: [0.5, -0.5, 0.5, -0.5]
  h2 = ops.Hadamard(2)
  psi = h2(psi)

  # Acting Cnot on this vector: [0.5, -0.5, -0.5, 0.5]
  psi = ops.Cnot()(psi)

  # Final Hadamard: [0, 0, 0, 1]
  psi = h2(psi)

  # which is |11>
  p11 = state.bitstring(1, 1)
  if not psi.is_close(p11):
    raise AssertionError('Something is wrong with the phase kick')