Exemplo n.º 1
0
def hipster_multi():
    """Multi-qubit, optimized application."""

    nbits = 7
    for bits in helper.bitprod(nbits):
        psi = state.bitstring(*bits)
        for target in range(1, nbits):
            # Full matrix (O(n*n).
            op = (ops.Identity(target - 1) * ops.Cnot(target - 1, target) *
                  ops.Identity(nbits - target - 1))
            psi1 = op(psi)

            # Single Qubit (O(n))
            psi = apply_controlled_gate(ops.PauliX(), target - 1, target, psi)
            if not psi.is_close(psi1):
                raise AssertionError('Invalid Single Gate Application.')

    psi = state.bitstring(1, 1, 0, 0, 1)
    pn = ops.Cnot(1, 4)(psi, 1)
    if not pn.is_close(apply_controlled_gate(ops.PauliX(), 1, 4, psi)):
        raise AssertionError('Invalid Cnot')
    pn = ops.Cnot(4, 1)(psi, 1)
    if not pn.is_close(apply_controlled_gate(ops.PauliX(), 4, 1, psi)):
        raise AssertionError('Invalid Cnot')
    pn = ops.ControlledU(0, 1, ops.ControlledU(1, 4, ops.PauliX()))(psi)

    psi = state.qubit(alpha=0.6) * state.ones(2)
    pn = ops.Cnot(0, 2)(psi)
    if not pn.is_close(apply_controlled_gate(ops.PauliX(), 0, 2, psi)):
        raise AssertionError('Invalid Cnot')
Exemplo n.º 2
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))
Exemplo n.º 3
0
def compute_max_cut(n: int, nodes: List[int]) -> int:
    """Compute (inefficiently) the max cut, exhaustively."""

    max_cut = -1000
    for bits in helper.bitprod(n):
        # Collect in/out sets.
        iset = []
        oset = []
        for idx, val in enumerate(bits):
            iset.append(idx) if val == 0 else oset.append(idx)

        # Compute costs for this cut, record maximum.
        cut = 0
        for node in nodes:
            if node[0] in iset and node[1] in oset:
                cut += node[2]
            if node[1] in iset and node[0] in oset:
                cut += node[2]
        if cut > max_cut:
            max_cut_in, max_cut_out = iset.copy(), oset.copy()
            max_cut = cut
            max_bits = bits

    state = bin(helper.bits2val(max_bits))[2:].zfill(n)
    print('Max Cut. N: {}, Max: {:.1f}, {}-{}, |{}>'
          .format(n, np.real(max_cut), max_cut_in, max_cut_out,
                  state))
    return helper.bits2val(max_bits)
Exemplo n.º 4
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)))
Exemplo n.º 5
0
Arquivo: state.py Projeto: qcc4cp/qcc
    def maxprob(self) -> (List[float], float):
        """Find state with highest probability."""

        maxbits, maxprob = [], 0.0
        for bits in helper.bitprod(self.nbits):
            cur_prob = self.prob(*bits)
            if cur_prob > maxprob:
                maxbits, maxprob = bits, cur_prob
        return maxbits, maxprob
Exemplo n.º 6
0
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())
Exemplo n.º 7
0
def check_result(nbits: int, c: Tuple[bool], psi: state.State) -> None:
    """Check expected vs achieved results."""

    print(f'Expected: {c}')

    # The state with the 'flipped' bits will have probability 1.0.
    # It will be found on the ver first try.
    #
    for bits in helper.bitprod(nbits):
        if psi.prob(*bits) > 0.1:
            print('Found   : {} = {:.1f}'.format(bits[:-1], psi.prob(*bits)))
            if bits[:-1] != c:
                raise AssertionError('invalid result')
Exemplo n.º 8
0
def compute_partition(num_list: List[int]):
    """Compute paritions that add up."""

    solutions = []
    for bits in helper.bitprod(len(num_list)):
        iset = []
        oset = []
        for idx, val in enumerate(bits):
            (iset.append(num_list[idx])
             if val == 0 else oset.append(num_list[idx]))
        if sum(iset) == sum(oset):
            solutions.append(bits)
    return solutions
Exemplo n.º 9
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.')
Exemplo n.º 10
0
def create_unitaries(base, limit):
  """Create all combinations of all base gates, up to length 'limit'."""

  # Create bitstrings up to bitstring length limit-1:
  #  0, 1, 00, 01, 10, 11, 000, 001, 010, ...
  #
  # Multiply together the 2 base operators, according to their index.
  # Note: This can be optimized, by remembering the last 2^x results
  # and multiplying them with base gets 0, 1.
  #
  gate_list = []
  for width in range(limit):
    for bits in helper.bitprod(width):
      U = ops.Identity()
      for bit in bits:
        U = U @ base[bit]
      gate_list.append(U)
  return gate_list
Exemplo n.º 11
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)))
Exemplo n.º 12
0
Arquivo: state.py Projeto: qcc4cp/qcc
def dump_state(psi,
               desc: Optional[str] = None,
               prob_only: bool = True) -> None:
    """Dump probabilities for a state, as well as local qubit state."""

    if desc:
        print('|', end='')
        for i in range(psi.nbits):
            print(i % 10, end='')
        print(f'> \'{desc}\'')

    state_list: List[str] = []
    for bits in helper.bitprod(psi.nbits):
        if prob_only and (psi.prob(*bits) < 10e-6):
            continue

        state_list.append(
            '{:s}:  ampl: {:+.2f} prob: {:.2f} Phase: {:5.1f}'.format(
                state_to_string(bits), psi.ampl(*bits), psi.prob(*bits),
                psi.phase(*bits)))
    state_list.sort()
    print(*state_list, sep='\n')