示例#1
0
 def test_dft_adjoint(self):
   bits = [0, 1, 0, 1, 1, 0]
   psi = state.bitstring(*bits)
   psi = ops.Qft(6)(psi)
   psi = ops.Qft(6).adjoint()(psi)
   maxbits, _ = psi.maxprob()
   self.assertEqual(maxbits, tuple(bits))
示例#2
0
def run_experiment(nbits, t=8):
    """Run single phase estimation experiment."""

    # Make a unitary and find Eigen value/vector to estimate.
    #
    umat = scipy.stats.unitary_group.rvs(2**nbits)
    eigvals, eigvecs = np.linalg.eig(umat)
    u = ops.Operator(umat)

    # Pick Eigenvalue 'eigen_index' (any Eigenvalue / Eigenvector pair will work).
    eigen_index = 1
    phi = np.real(np.log(eigvals[eigen_index]) / (2j * np.pi))
    if phi < 0:
        phi += 1

    # Make state + circuit to estimate phi.
    # Pick Eigenvector 'eigen_index' to math the Eigenvalue.
    psi = state.zeros(t) * state.State(eigvecs[:, eigen_index])
    psi = phase1(psi, u, t)
    psi = ops.Qft(t).adjoint()(psi)

    # Find state with highest measurement probability and show results.
    #
    maxbits, maxprob = psi.maxprob()
    phi_estimate = sum(maxbits[i] * 2**(-i - 1) for i in range(t))

    delta = abs(phi - phi_estimate)
    print('Phase   : {:.4f}'.format(phi))
    print('Estimate: {:.4f} delta: {:.4f} probability: {:5.2f}%'.format(
        phi_estimate, delta, maxprob * 100.0))
    if delta > 0.02 and phi_estimate < 0.98:
        print('*** Warning: Delta is large')
示例#3
0
    def test_bloch_coords(self):
        psi = state.bitstring(1, 1)
        psi = ops.Qft(2)(psi)

        rho0 = ops.TraceOut(psi.density(), [1])
        rho1 = ops.TraceOut(psi.density(), [0])

        x0, _, _ = helper.density_to_cartesian(rho0)
        _, y1, _ = helper.density_to_cartesian(rho1)

        self.assertTrue(math.isclose(-1.0, x0, abs_tol=0.01))
        self.assertTrue(math.isclose(-1.0, y1, abs_tol=0.01))
示例#4
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))
示例#5
0
def run_experiment(nbits_phase, nbits_grover, solutions) -> None:
  """Run full experiment for a given number of solutions."""

  # Building the Grover Operator, see grover.py
  n = 2**nbits_grover
  zero_projector = np.zeros((n, n))
  zero_projector[0, 0] = 1
  op_zero = ops.Operator(zero_projector)

  f = make_f(nbits_grover, solutions)
  u = ops.OracleUf(nbits_grover + 1, f)

  # The state for the counting algorithm.
  # We reserve nbits for the phase estimation.
  # We also reserve nbits for the Oracle.
  # These numbers could be adjusted to achieve better
  # accuracy. Yet, this keeps the code a little bit simpler,
  # while trading off a few off-by-1 estimation errors.
  #
  # We also add the |1> for the Oracle.
  #
  psi = (state.zeros(nbits_phase) * state.zeros(nbits_grover) * state.ones(1))

  # Apply Hadamard to all the qubits.
  for i in range(nbits_phase + nbits_grover + 1):
    psi.apply(ops.Hadamard(), i)

  # Construct the Grover Operator.
  reflection = op_zero * 2.0 - ops.Identity(nbits_grover)
  hn = ops.Hadamard(nbits_grover)
  inversion = hn(reflection(hn)) * ops.Identity()
  grover = inversion(u)

  # Now that we have the Grover Operator, we have to perform
  # phase estimation. This loop is a copy from phase_estimation.py
  # with more comments there.
  #
  for idx, inv in enumerate(range(nbits_phase - 1, -1, -1)):
    u2 = grover
    for _ in range(idx):
      u2 = u2(u2)
    psi = ops.ControlledU(inv, nbits_phase, u2)(psi, inv)

  # Reverse QFT gives us the phase as a fraction of 2*Pi
  psi = ops.Qft(nbits_phase).adjoint()(psi)

  # Get the state with highest probability and compute the phase
  # as a binary fraction. Note that the probability increases
  # as M, the number of solutions, gets closer and closer to N,
  # the total mnumber of states.
  maxbits, maxprob = psi.maxprob()
  phi_estimate = sum(maxbits[i] * 2**(-i - 1) for i in range(nbits_phase))

  # We know that after phase estimation, this holds:
  #
  #    sin(phi/2) = sqrt(M/N)
  #             M = N * sin(phi/2)^2
  #
  # Hence we can compute M. We keep the result to 2 digit to visualize
  # the errors. Note that the phi_estimate is a fraction of 2*PI, hence
  # the 1/2 in above formula cancels out against the 2 and we compute:
  M = round(n * math.sin(phi_estimate * math.pi)**2, 2)

  print('Estimate: {:.4f} prob: {:5.2f}% --> M: {:5.2f}, want: {:2d}'.format(
      phi_estimate, maxprob * 100.0, M, solutions))