Exemplo n.º 1
0
def period_find(a, N):
    """Finds the period of a in modulo N arithmetic

    This is quantum part of Shor's algorithm.It takes two registers,
    puts first in superposition of states with Hadamards so: |k>|0>
    with k being all possible choices. It then does a controlled mod and
    a QFT to determine the order of a.
    """
    epsilon = .5
    #picks out t's such that maintains accuracy within epsilon
    t = int(2 * math.ceil(log(N, 2)))
    # make the first half of register be 0's |000...000>
    start = [0 for x in range(t)]
    #Put second half into superposition of states so we have |1>x|0> + |2>x|0> + ... |k>x>|0> + ... + |2**n-1>x|0>
    factor = 1 / sqrt(2**t)
    qubits = 0
    for i in range(2**t):
        qbitArray = arr(i, t) + start
        qubits = qubits + Qubit(*qbitArray)
    circuit = (factor * qubits).expand()
    #Controlled second half of register so that we have:
    # |1>x|a**1 %N> + |2>x|a**2 %N> + ... + |k>x|a**k %N >+ ... + |2**n-1=k>x|a**k % n>
    circuit = CMod(t, a, N) * circuit
    #will measure first half of register giving one of the a**k%N's
    circuit = apply_operators(circuit)
    print "controlled Mod'd"
    for i in range(t):
        circuit = measure_partial_oneshot(circuit, i)
        # circuit = measure(i)*circuit
    # circuit = apply_operators(circuit)
    print "measured 1"
    #Now apply Inverse Quantum Fourier Transform on the second half of the register
    circuit = apply_operators(QFT(t, t * 2).decompose() * circuit,
                              floatingPoint=True)
    print "QFT'd"
    for i in range(t):
        circuit = measure_partial_oneshot(circuit, i + t)
        # circuit = measure(i+t)*circuit
    # circuit = apply_operators(circuit)
    print circuit
    if isinstance(circuit, Qubit):
        register = circuit
    elif isinstance(circuit, Mul):
        register = circuit.args[-1]
    else:
        register = circuit.args[-1].args[-1]

    print register
    n = 1
    answer = 0
    for i in range(len(register) / 2):
        answer += n * register[i + t]
        n = n << 1
    if answer == 0:
        raise OrderFindingException(
            "Order finder returned 0. Happens with chance %f" % epsilon)
    #turn answer into r using continued fractions
    g = getr(answer, 2**t, N)
    print g
    return g
Exemplo n.º 2
0
def period_find(a, N):
    """Finds the period of a in modulo N arithmetic

    This is quantum part of Shor's algorithm.It takes two registers,
    puts first in superposition of states with Hadamards so: ``|k>|0>``
    with k being all possible choices. It then does a controlled mod and
    a QFT to determine the order of a.
    """
    epsilon = .5
    #picks out t's such that maintains accuracy within epsilon
    t = int(2*math.ceil(log(N, 2)))
    # make the first half of register be 0's |000...000>
    start = [0 for x in range(t)]
    #Put second half into superposition of states so we have |1>x|0> + |2>x|0> + ... |k>x>|0> + ... + |2**n-1>x|0>
    factor = 1/sqrt(2**t)
    qubits = 0
    for i in range(2**t):
        qbitArray = arr(i, t) + start
        qubits = qubits + Qubit(*qbitArray)
    circuit = (factor*qubits).expand()
    #Controlled second half of register so that we have:
    # |1>x|a**1 %N> + |2>x|a**2 %N> + ... + |k>x|a**k %N >+ ... + |2**n-1=k>x|a**k % n>
    circuit = CMod(t, a, N)*circuit
    #will measure first half of register giving one of the a**k%N's
    circuit = qapply(circuit)
    print "controlled Mod'd"
    for i in range(t):
        circuit = measure_partial_oneshot(circuit, i)
        # circuit = measure(i)*circuit
    # circuit = qapply(circuit)
    print "measured 1"
    #Now apply Inverse Quantum Fourier Transform on the second half of the register
    circuit = qapply(QFT(t, t*2).decompose()*circuit, floatingPoint=True)
    print "QFT'd"
    for i in range(t):
        circuit = measure_partial_oneshot(circuit, i + t)
        # circuit = measure(i+t)*circuit
    # circuit = qapply(circuit)
    print circuit
    if isinstance(circuit, Qubit):
        register = circuit
    elif isinstance(circuit, Mul):
        register = circuit.args[-1]
    else:
        register = circuit.args[-1].args[-1]

    print register
    n = 1
    answer = 0
    for i in range(len(register)/2):
        answer += n*register[i + t]
        n = n << 1
    if answer == 0:
        raise OrderFindingException(
            "Order finder returned 0. Happens with chance %f" % epsilon)
    #turn answer into r using continued fractions
    g = getr(answer, 2**t, N)
    print g
    return g
def find_r(x, N):
    """

    Encontra o período de x em aritimética módulo N.
    Essa é a parte realmente quântica da solução.

    Põe a primeira parte do registrador em um estado de superposição |j> |0>,
    com j = 0 to 2 ** n - 1, usando a porta Hadamard.
    Depois aplica a porta Vx e IQFT para determinar a ordem de x.

    """

    # Calcula o número de qubits necessários
    n = int(math.ceil(log(N, 2)))
    t = int(math.ceil(2 * log(N, 2)))

    print("n: ", n)
    print("t: ", t)

    # Cria o registrador
    register = Qubit(IntQubit(0, t + n))
    print("register: ", register)

    # Põe a segunda metade do registrado em superposição |1>|0> + |2>|0> + ... |j>|0> + ... + |2 ** n - 1>|0>
    print("Aplicando Hadamard...")
    circuit = 1
    for i in reversed(list(range(n, n + t))):
        circuit = HadamardGate(i) * circuit
    circuit = qapply(circuit * register)
    print("Circuit Hadamard:\n", circuit.simplify())

    # Calcula os valores para a primeira metade do registrador |1>|x ** 1 % N> + |2>|x ** 2 % N> + ... + |k>|x ** k % N >+ ... + |2 ** n - 1 = j>|x ** j % N>
    print("Aplicando Vx...")
    circuit = qapply(Vx(n, t, x, N) * circuit)
    print("Circuit Vx:\n", circuit.simplify())

    # Faz a medição da primeira metade do registrador obtendo um dos [x ** j % N's]
    print("Medindo 0->n ...")
    circuit = measure_partial_oneshot(circuit, range(n))
    print("Circuit 0->n:\n", circuit.simplify())

    # Aplica a Transformada de Fourier Quântica Inversa na segunda metade do registrador
    print("Aplicando a transformada inversa...")
    circuit = qapply(IQFT(n, n + t).decompose() * circuit)
    print("Circuit IQFT:\n", circuit.simplify())

    # Faz a medição da segunda metade do registrador um dos valores da transformada

    while (
            True
    ):  # O correto seria repetir a rotina inteira, mas é suficiente repetir a medição.
        # Num computador quântico real o estado colapsaria e não seria possível medi-lo novamente.
        print("Medindo n->n+t ...")

        #measurement = measure_partial_oneshot(circuit, range(n, n + t))
        measurement = measure_all_oneshot(circuit)

        print(measurement.simplify())

        if isinstance(measurement, Qubit):
            register = measurement
        elif isinstance(measurement, Mul):
            register = measurement.args[-1]
        else:
            register = measurement.args[-1].args[-1]

        print("Medicao: ", register)

        # Converte o qubit de binário para decimal
        k = 1
        answer = 0
        for i in range(t):
            answer += k * register[n + i]
            k = k << 1

        print("Medicao: ", answer)

        if answer != 0:
            break

    print("2^t: ", 2**t)
    # Lista os termos da fração continuada
    fraction = continued_fraction(answer, 2**t)

    # A soma dos termos da fração continuada é a razão entre dois
    # números primos entre si (p e q onde MDC(p, q) == 1) que
    # multiplicados resultam N (somar apenas os termos menores ou iguais a N)
    r = 0
    for x in fraction:
        if (x > N):
            break
        else:
            print("fraction: ", x)
            r = r + x

    return r