from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit

A = QuantumRegister(1, 'a')
B = QuantumRegister(1, 'b')
CarryIn = QuantumRegister(1, 'cin-sum')
cero = QuantumRegister(1, 'aux-cout')
adder = QuantumCircuit(A, B, CarryIn, cero)

adder.ccx(0, 1, 3)
adder.cx(0, 1)
adder.ccx(1, 2, 3)
adder.cx(1, 2)
adder.cx(0, 1)

adder.draw('mpl')

inicializacion = QuantumCircuit(4)

inicializacion.x(0)    # a   = 1
inicializacion.x(2)    # cin = 1
inicializacion.barrier()

inicializacion.draw('mpl')

suma = inicializacion.compose(adder)

suma.barrier()

suma.add_register(ClassicalRegister(2, 'res'))

suma.measure([2, 3], [0, 1])

suma.draw('mpl')

from qiskit import execute, Aer
from qiskit.tools.visualization import plot_histogram

job = execute(suma, Aer.get_backend('aer_simulator'), shots=1000)
counts = job.result().get_counts(suma)
print(counts)

plot_histogram(counts, title='Conteos del resultado de la suma') 

inicializacion2 = QuantumCircuit(4)
inicializacion2.x(0)    # a   = 1
inicializacion2.x(1)    # b   = 1
inicializacion2.x(2)    # cin = 1
inicializacion2.barrier()

suma2 = inicializacion2.compose(adder)
suma2.barrier()
suma2.add_register(ClassicalRegister(2, 'res'))
suma2.measure([2, 3], [0, 1])
display(suma2.draw('mpl'))

job = execute(suma2, Aer.get_backend('aer_simulator'), shots=1)  # con una sola ejecución es suficiente
counts2 = job.result().get_counts(suma2)
print(counts2)
plot_histogram(counts2, title='Conteos del resultado de la suma2') 

inicializacion3 = QuantumCircuit(4)
inicializacion3.h(0)        # a y b en estado de Bell
inicializacion3.cx(0, 1)
inicializacion3.h(2)        # estado en superposión: ( |0> + |1> ) / sqrt(2)
inicializacion3.barrier()

suma3 = inicializacion3.compose(adder)  # el 'adder' es el mismo
suma3.barrier()
suma3.add_register(ClassicalRegister(2, 'res'))
suma3.measure([2, 3], [0, 1])
display(suma3.draw('mpl'))

job = execute(suma3, Aer.get_backend('aer_simulator'), shots=1000)  # en este caso si necesitamos multiples shots
counts3 = job.result().get_counts(suma3)
print(counts3)
plot_histogram(counts3, title='Conteos del resultado de la suma3') 

from qiskit.circuit.library.arithmetic.adders import CDKMRippleCarryAdder

qiskit_adder = CDKMRippleCarryAdder(3, 'full', 'Sumador completo')

operando1 = QuantumRegister(3, 'o1')  # primer número a sumar
operando2 = QuantumRegister(3, 'o2')  # segundo número a sumar
aux = QuantumRegister(2, 'a')         # acarreo de entrada y de salida
cr = ClassicalRegister(4)             # para almacenar el resultado en bits clásicos

circ = QuantumCircuit(operando1, operando2, aux, cr)

circ.x([operando1[0], operando1[1]])  # 3 en binario: 011
circ.x([operando2[0], operando2[2]])  # 5 en binario: 101

# El orden esperado por la clase 'CDKMRippleCarryAdder' es: carry_in - 1er operando - 2do operando - carry_out
circ.append(qiskit_adder, [aux[0]] + operando1[0:3] + operando2[0:3] + [aux[1]])

circ.measure(operando2[0:3] + [aux[1]], cr) #  esta clase escribe el resultado en el 2do operando y en el carry_out
display(circ.draw('mpl'))

job = execute(circ, Aer.get_backend('aer_simulator'), shots=1000)
counts = job.result().get_counts(circ)
print(counts) # resultado es 8 en binario: 1000

plot_histogram(counts, title='Conteos del ejemplo con CDKMRippleCarryAdder') 

from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister

qr_alice = QuantumRegister(2, name="alicia")   # dos qubits de Alicia
qr_bob = QuantumRegister(1, name="bob")        # un qubit de Bob
crz = ClassicalRegister(1, name="crz")         # 2 bits clasicos
crx = ClassicalRegister(1, name="crx")         # en 2 diferentes registros

circuito_teleportacion = QuantumCircuit(qr_alice, qr_bob, crz, crx)

circuito_teleportacion.draw('mpl')

def crear_estado_bell(circ, a, b):
    circ.h(a)     # poner el qubit a en el estado |+>
    circ.cx(a, b) # CNOT con control el qubit a y objetivo el qubit b

crear_estado_bell(circuito_teleportacion, 1, 2) # circuito, qubit a, qubit b

circuito_teleportacion.draw('mpl')

def compuertas_alicia(circ, psi, a):
    circ.barrier()
    circ.cx(psi, a)
    circ.h(psi)

compuertas_alicia(circuito_teleportacion, 0, 1)

circuito_teleportacion.draw('mpl')

def mediciones_y_envio(circ, psi, a):
    circ.barrier()
    circ.measure(psi, 0)
    circ.measure(a, 1)

mediciones_y_envio(circuito_teleportacion, 0, 1)

circuito_teleportacion.draw('mpl')

def compuertas_bob(circ, b, crz, crx):
    circ.barrier()
    circ.x(b).c_if(crx, 1)
    circ.z(b).c_if(crz, 1)

compuertas_bob(circuito_teleportacion, 2, crz, crx)

circuito_teleportacion.draw('mpl')

from qiskit.quantum_info import random_statevector
from qiskit.visualization import plot_histogram, plot_bloch_multivector, array_to_latex

# generamos un estado aleatorio (el que enviará Alicia Bob y al ser aleatorio ella no lo conoce)
psi = random_statevector(2)

# veamos que de que estado se trata

display(array_to_latex(psi, prefix="|\\psi\\rangle ="))

plot_bloch_multivector(psi)

from qiskit.extensions import Initialize

# crear una instruccion de inicializacion que coloque al qubit en el estado que generamos aleatoriamente
instruccion_inicializacion = Initialize(psi)
instruccion_inicializacion.label = "init"

# El protocolo completo:

# Configuración inicial
qr_alice = QuantumRegister(2, name="alicia")   # dos qubits de Alicia
qr_bob = QuantumRegister(1, name="bob")        # un qubit de Bob
crz = ClassicalRegister(1, name="crz")         # 2 bits clasicos
crx = ClassicalRegister(1, name="crx")         # en 2 diferentes registros
circuito_teleportacion = QuantumCircuit(qr_alice, qr_bob, crz, crx)

# Paso 0
# Iniciar el qubit a enviar
circuito_teleportacion.append(instruccion_inicializacion, [0])
circuito_teleportacion.barrier()

# Paso 1
# Crear el par entrelazado
crear_estado_bell(circuito_teleportacion, 1, 2) # circuito, qubit a, qubit b

# Paso 2
# "Enviar" q1 a Alicia y q2 a Bob
compuertas_alicia(circuito_teleportacion, 0, 1)

# Paso 3
# Alicia envia sus bits clásicos a Bob
mediciones_y_envio(circuito_teleportacion, 0, 1)

# Paso 4
# Bob decodifica su qubit
compuertas_bob(circuito_teleportacion, 2, crz, crx)


circuito_teleportacion.draw('mpl')

sim = Aer.get_backend('aer_simulator')
circuito_teleportacion.save_statevector()
out_vector = sim.run(circuito_teleportacion).result().get_statevector()
display(plot_bloch_multivector(out_vector))

out_vector.draw('latex')

reverso_instruccion_inicializacion = instruccion_inicializacion.gates_to_uncompute()

qr_alice = QuantumRegister(2, name="alicia")   # dos qubits de Alicia
qr_bob = QuantumRegister(1, name="bob")        # un qubit de Bob
crz = ClassicalRegister(1, name="crz")         # 2 bits clasicos
crx = ClassicalRegister(1, name="crx")         # en 2 diferentes registros
circuito_teleportacion = QuantumCircuit(qr_alice, qr_bob, crz, crx)

# Paso 0
# Iniciar el qubit a enviar
circuito_teleportacion.append(instruccion_inicializacion, [0])
circuito_teleportacion.barrier()

# Paso 1
# Crear el par entrelazado
crear_estado_bell(circuito_teleportacion, 1, 2) # circuito, qubit a, qubit b

# Paso 2
# "Enviar" q1 a Alicia y q2 a Bob
compuertas_alicia(circuito_teleportacion, 0, 1)

# Paso 3
# Alicia envia sus bits clásicos a Bob
mediciones_y_envio(circuito_teleportacion, 0, 1)

# Paso 4
# Bob decodifica su qubit
compuertas_bob(circuito_teleportacion, 2, crz, crx)

circuito_teleportacion.append(reverso_instruccion_inicializacion, [2])

circuito_teleportacion.draw('mpl')

cr_result = ClassicalRegister(1)
circuito_teleportacion.add_register(cr_result)
circuito_teleportacion.measure(2, 2)
circuito_teleportacion.draw('mpl')

from qiskit.result import marginal_counts
from qiskit import transpile

t_qc = transpile(circuito_teleportacion, sim)
t_qc.save_statevector()
counts = sim.run(t_qc).result().get_counts()
qubit_counts = [marginal_counts(counts, [qubit]) for qubit in range(3)]
plot_histogram(qubit_counts)

n = 3           # cantidad de bits para la función f

from qiskit import QuantumCircuit
import numpy as np


#---------------------
## Oráculo Constante
#---------------------

const_oraculo = QuantumCircuit(n+1)   # +1 qubit que corresponde al segundo registro

# en este caso, la entrada no tiene efecto en la salida, por lo que simplemente 
# configuramos aleatoriamente el qubit de salida en 0 o 1:

output = np.random.randint(2)
if output == 1:
    const_oraculo.x(n)          # aplicar X al qubits de salida (un solo resultado para todas las entradas)

const_oraculo.draw('mpl')

#---------------------
## Oráculo Balanceado
#---------------------

balan_oraculo = QuantumCircuit(n+1)


# podemos crear un oráculo balanceado usando CNOTs con cada qubit de entrada como control
# y el bit de salida como objetivo. Podemos variar los estados de entrada que dan 0 o 1 
# encerrando algunos de los controles con compuertas X. Primero elijamos una cadena binaria de 
# longitud n que dicte qué controles ajustar:

b_str = "101"

# agregar las compuertas X en la posción donde hay un 1
for qubit in range(len(b_str)):
    if b_str[qubit] == '1':
        balan_oraculo.x(qubit)
balan_oraculo.barrier()

# ahora, aplicamos las compuertas CNOT, usando cada qubit de entrada como control y el 
# qubit de salida como objetivo:
for qubit in range(n):
    balan_oraculo.cx(qubit, n)

balan_oraculo.barrier()

# finalmente, aplicamos compuertas X para terminar de envolver los controles:
for qubit in range(len(b_str)):
    if b_str[qubit] == '1':
        balan_oraculo.x(qubit)

balan_oraculo.draw('mpl')

dj_circuit = QuantumCircuit(n+1, n)          # n+1=4 qubits, n=3 bits clásicos

dj_circuit.x(n)                              # colocar el último qubits (segundo registro) en el estado |1>

dj_circuit.barrier()
dj_circuit.draw('mpl')

# Aplicar las compuertas H al primer registro
for qubit in range(n):
    dj_circuit.h(qubit)

# Aplicar H al segundo registro, H|1> = |->
dj_circuit.h(n)

dj_circuit.barrier()
dj_circuit.draw('mpl')

def dj_oraculo(dj_circuit, caso):
    
    if caso == 'balanceado':
        circuit_return = dj_circuit.compose(balan_oraculo)
    else:
        circuit_return = dj_circuit.compose(const_oraculo)
        
    circuit_return.barrier()
    
    return circuit_return

# generemos un circuito con el oráculo constante
dj_circ_constante = dj_oraculo(dj_circuit, 'constante')

# generemos un circuito con el oráculo balanceado
dj_circ_balanceado = dj_oraculo(dj_circuit, 'balanceado')


dj_circ_balanceado.draw('mpl')

#---------------------
## Oráculo Balanceado
#---------------------

# Aplicar nuevaente compuertas H al primer registro (en el circuito que ya tienen el oráculo)
for qubit in range(n):
    dj_circ_balanceado.h(qubit)
    
dj_circ_balanceado.barrier()
dj_circ_balanceado.draw('mpl')

#---------------------
## Oráculo Constante
#---------------------

# Aplicar nuevaente compuertas H al primer registro (en el circuito que ya tienen el oráculo)
for qubit in range(n):
    dj_circ_constante.h(qubit)

dj_circ_constante.barrier()
dj_circ_constante.draw('mpl')

#---------------------
## Oráculo Balanceado
#---------------------

# agregamos mediciones al primer registro
for i in range(n):
    dj_circ_balanceado.measure(i, i)
    
dj_circ_balanceado.draw('mpl')

#---------------------
## Oráculo Constante
#---------------------

# agregamos mediciones al primer registro
for i in range(n):
    dj_circ_constante.measure(i, i)
    
dj_circ_constante.draw('mpl')

from qiskit import Aer

aer_sim = Aer.get_backend('aer_simulator')


#---------------------
## Oráculo Constante
#---------------------

results = aer_sim.run(dj_circ_constante).result()
respuesta = results.get_counts()

plot_histogram(respuesta)

#---------------------
## Oráculo Balanceado
#---------------------

results = aer_sim.run(dj_circ_balanceado).result()
respuesta = results.get_counts()

plot_histogram(respuesta)

from qiskit import QuantumCircuit

n = 2

grover_circuit = QuantumCircuit(n)

def initialize_s(qc, qubits):
    # Aplicar una compuerta H a los 'qubits' in qc
    for q in qubits:
        #
    return qc

grover_circuit = initialize_s(grover_circuit, [0,1])
grover_circuit.draw('mpl')

grover_circuit.barrier()
grover_circuit.cz(0,1) # oráculo
grover_circuit.barrier()

grover_circuit.draw('mpl')

# operador de difusión (U_s)
grover_circuit.h([0,1])
grover_circuit.z([0,1])
grover_circuit.cz(0,1)
grover_circuit.h([0,1])

grover_circuit.draw('mpl')

from qiskit import Aer
from qiskit.visualization import array_to_latex

# revisamos el estado al final del circuito

sv_sim = Aer.get_backend('statevector_simulator')

result = sv_sim.run(grover_circuit).result()
statevec = result.get_statevector()
array_to_latex(statevec, prefix="|\\psi\\rangle =")

# agregamos las mediciones a todos los qubits
grover_circuit.measure_all()

grover_circuit.draw('mpl')

# simulamos la ejecución del circuito

qasm_sim = Aer.get_backend('qasm_simulator')
result = qasm_sim.run(grover_circuit).result()
counts = result.get_counts()
plot_histogram(counts)

# crear el oráculo

qc = QuantumCircuit(3)
qc.cz(0, 2)
qc.cz(1, 2)
oracle_ex3 = qc.to_gate()
oracle_ex3.name = "U$_\omega$"

# función para un difusor general

def diffuser(nqubits):
    qc = QuantumCircuit(nqubits)
    # Aplicar la transformación |s> -> |00..0> (H-gates)
    for qubit in range(nqubits):
        qc.h(qubit)
    # Aplicar la transformación |00..0> -> |11..1> (X-gates)
    for qubit in range(nqubits):
        qc.x(qubit)
    # Aplicar múltiples compuertas Z controladas
    qc.h(nqubits-1)
    qc.mct(list(range(nqubits-1)), nqubits-1)  # toffoli con multicontrol
    qc.h(nqubits-1)
    # Aplicar la transformación |11..1> -> |00..0>
    for qubit in range(nqubits):
        qc.x(qubit)
    # Aplicar la transformación |00..0> -> |s>
    for qubit in range(nqubits):
        qc.h(qubit)
    # Regresar el difusor como compuerta
    U_s = qc.to_gate()
    U_s.name = "U$_s$"
    return U_s

# Ejemplo para circuito de 3 qubits

n = 3
grover_circuit = QuantumCircuit(n)
grover_circuit = initialize_s(grover_circuit, [0, 1, 2])
grover_circuit.append(oracle_ex3, [0, 1, 2])
grover_circuit.append(diffuser(n), [0, 1, 2])
grover_circuit.measure_all()

grover_circuit.draw('mpl')

# simulamos la ejecución del circuito

qasm_sim = Aer.get_backend('qasm_simulator')
transpiled_grover_circuit = transpile(grover_circuit, qasm_sim) # necesario para transpilar las compuertas Uw y Us
results = qasm_sim.run(transpiled_grover_circuit).result()
counts = results.get_counts()
plot_histogram(counts)

from qiskit.algorithms import AmplificationProblem

# el estado que se desea encontrar '11'
good_state = ['11']

# especificar el oráculo que marca el estado '11' como la solución correcta
oracle = QuantumCircuit(2)
oracle.cz(0, 1)

# definir el algorito de Grover
problem = AmplificationProblem(oracle, is_good_state=good_state)

# veamos el operador Grover que será usado para resolver el problema
problem.grover_operator.decompose().draw(output='mpl')

from qiskit.algorithms import Grover

aer_simulator = Aer.get_backend('aer_simulator')
grover = Grover(quantum_instance=aer_simulator)    # definir una instancia de `Grover` con el problema
result = grover.amplify(problem)
print('tipo del resultado:', type(result))
print()
print('¡Éxito!' if result.oracle_evaluation else '¡Falló!')
print()
print('Medición más grande:', result.top_measurement)

plot_histogram(result.circuit_results)

import matplotlib.pyplot as plt


N = 35
a = 3

xvals = range(35)
yvals = [np.mod(a**x, N) for x in xvals]

fig, ax = plt.subplots()
ax.plot(xvals, yvals, linewidth=1, linestyle='dotted', marker='x')
ax.set(xlabel='$x$', ylabel='$%i^x$ mod $%i$' % (a, N), title="Ejemplo de función periódica")

try: # graficar 'r'
    r = yvals[1:].index(1) + 1 
    plt.annotate('', xy=(0, 1), xytext=(r, 1), arrowprops=dict(arrowstyle='<->'))
    plt.annotate('$r=%i$' % r, xy=(r/3, 1.5))
except ValueError:
    print('No se pudo encontrar el período, revisa que a < N y no tengan factores comunes')

ax.set(xlabel='Cantidad de aplicaciones de U', ylabel='Estado final del registro',
       title="Efecto de aplicaciones sucesivas de U")
fig

def c_amod15(a, power):
    # Multiplicación conrolada por a mod 15
    if a not in [2,4,7,8,11,13]:
        raise ValueError("'a' debe ser 2,4,7,8,11 o 13")
    U = QuantumCircuit(4)        
    for iteration in range(power):
        if a in [2,13]:
            U.swap(0,1)
            U.swap(1,2)
            U.swap(2,3)
        if a in [7,8]:
            U.swap(2,3)
            U.swap(1,2)
            U.swap(0,1)
        if a in [4, 11]:
            U.swap(1,3)
            U.swap(0,2)
        if a in [7,11,13]:
            for q in range(4):
                U.x(q)
    U = U.to_gate()
    U.name = "%i^%i mod 15" % (a, power)
    c_U = U.control()
    return c_U

n_count = 8  # número de qubits de conteo
a = 7

def qft_dagger(n):
    # QFT daga de n qubits, los prmero n qubits en circ
    qc = QuantumCircuit(n)
    for qubit in range(n//2):
        qc.swap(qubit, n-qubit-1)
    for j in range(n):
        for m in range(j):
            qc.cp(-np.pi/float(2**(j-m)), m, j)
        qc.h(j)
    qc.name = "QFT†"
    return qc

# Crear el circuito final


# circuito con n_count qubits de conteo
# más 4 qubits para que U actúe sobre ellos
qc = QuantumCircuit(n_count + 4, n_count)

# inicializar los qubits de conteo
# en el estado |+>
for q in range(n_count):
    qc.h(q)
    
# y un registro auxiliar en el estado |1>
qc.x(3+n_count)

# aplicar las U controladas
for q in range(n_count):
    qc.append(c_amod15(a, 2**q), 
             [q] + [i+n_count for i in range(4)])

# aplicar QFT daga
qc.append(qft_dagger(n_count), range(n_count))

# medir el circuito
qc.measure(range(n_count), range(n_count))
qc.draw('mpl', fold=-1)  # -1 significa 'no separar'

aer_sim = Aer.get_backend('aer_simulator')
t_qc = transpile(qc, aer_sim)
results = aer_sim.run(t_qc).result()
counts = results.get_counts()
plot_histogram(counts)

import pandas as pd

rows, measured_phases = [], []
for output in counts:
    decimal = int(output, 2)  # Convert (base 2) string to decimal
    phase = decimal/(2**n_count)  # Find corresponding eigenvalue
    measured_phases.append(phase)
    # Add these values to the rows in our table:
    rows.append([f"{output}(bin) = {decimal:>3}(dec)", 
                 f"{decimal}/{2**n_count} = {phase:.2f}"])
# Print the rows in a table
headers=["Salida del registro", "Fase"]
df = pd.DataFrame(rows, columns=headers)
print(df)

from fractions import Fraction

Fraction(0.666)

# Obtener la fracción que más se asemeje a 0.666
# con denominador < 15
Fraction(0.666).limit_denominator(15)

rows = []
for phase in measured_phases:
    frac = Fraction(phase).limit_denominator(15)
    rows.append([phase, f"{frac.numerator}/{frac.denominator}", frac.denominator])
# Print as a table
headers=["Fase", "Fracción", "Suposición para r"]
df = pd.DataFrame(rows, columns=headers)
print(df)

def a2jmodN(a, j, N):
    # Calcular a^{2^j} (mod N) con 'repeated squaring'
    for i in range(j):
        a = np.mod(a**2, N)
    return a

a2jmodN(7, 2049, 53)

N = 15

from numpy.random import randint

np.random.seed(1) # Para hacer reproducibles los resultados
a = randint(2, 15)
print(a)

# ahora, comprobamos que no es ya un factor no trivial de N

from math import gcd # máximo común divisor b(greatest common divisor)
gcd(a, N)

def qpe_amod15(a):
    n_count = 8
    qc = QuantumCircuit(4+n_count, n_count)
    for q in range(n_count):
        qc.h(q)     # Inicializar qubits en el estado |+>
    qc.x(3+n_count) #  un registro auxiliar en el estado |1>
    for q in range(n_count): # aplicar operaciones U controladas
        qc.append(c_amod15(a, 2**q), 
                 [q] + [i+n_count for i in range(4)])
    qc.append(qft_dagger(n_count), range(n_count)) # aplicar la QFT inversa
    qc.measure(range(n_count), range(n_count))
    # simular los resultados
    aer_sim = Aer.get_backend('aer_simulator')
    # Configurar 'memory=True' permite ver una lista de cada lectura secuencial
    t_qc = transpile(qc, aer_sim)
    result = aer_sim.run(t_qc, shots=1, memory=True).result()
    readings = result.get_memory()
    print("Lectura del registro: " + readings[0])
    phase = int(readings[0],2)/(2**n_count)
    print("Fase correspondiente: %f" % phase)
    return phase

# a partir de esta fase, podemos encontrar fácilmente una suposición para r:

phase = qpe_amod15(a) # fase = s/r
Fraction(phase).limit_denominator(15) # el denominador debería decirnos r (eso esperamos)

frac = Fraction(phase).limit_denominator(15)
s, r = frac.numerator, frac.denominator
print(r)

guesses = [gcd(a**(r//2)-1, N), gcd(a**(r//2)+1, N)]
print(guesses)

a = 7
factor_found = False
attempt = 0
while not factor_found:
    attempt += 1
    print("Intento %i:" % attempt)
    phase = qpe_amod15(a) # fase = s/r
    frac = Fraction(phase).limit_denominator(N) # el denominador debería decirnos r (eso esperamos)
    r = frac.denominator
    print("Resultado: r = %i" % r)
    if phase != 0:
        # las suposiciones para los factores son gcd(x^{r/2} ±1 , 15)
        guesses = [gcd(a**(r//2)-1, N), gcd(a**(r//2)+1, N)]
        print("Factores supuestos: %i and %i" % (guesses[0], guesses[1]))
        for guess in guesses:
            if guess not in [1,N] and (N % guess) == 0: # Check to see if guess is a factor
                print("*** Factor encontrado no trivial: %i ***" % guess)
                factor_found = True

from qiskit.utils import QuantumInstance
from qiskit.algorithms import Shor


N = 15

backend = Aer.get_backend('aer_simulator')
quantum_instance = QuantumInstance(backend, shots=1024)

shor = Shor(quantum_instance=quantum_instance)

result = shor.factor(N)

print(f"La lista de factores de {N} calculada por el algoritmo de Shor es {result.factors[0]}.")