Cómo crear algoritmos cuánticos avanzados utilizando Qrisp con Grover Search, estimación de fase cuántica y QAOA

En este tutorial, presentamos un tutorial práctico avanzado que demuestra cómo usamos Qrisp para construir y ejecutar algoritmos cuánticos no triviales. Analizamos las abstracciones centrales de Qrisp para datos cuánticos, construimos estados entrelazados y luego implementamos progresivamente la búsqueda de Grover con cálculo automático, estimación de fase cuántica y un flujo de trabajo QAOA completo para el problema MaxCut. Además, nos enfocamos en escribir programas cuánticos expresivos de alto nivel mientras permitimos que Qrisp administre la construcción de circuitos, la lógica de control y la reversibilidad detrás de escena. Consulta los CÓDIGOS COMPLETOS aquí.

importar sistema, subproceso, matemáticas, aleatorio, ajuste de texto, definición de tiempo _pip_install(pkgs): cmd = [sys.executable, “-m”, “pip”, “install”, “-q”] + pkgs subprocess.check_call(cmd) print(“Instalando dependencias (qrisp, networkx, matplotlib, sympy)…”) _pip_install([“qrisp”, “networkx”, “matplotlib”, “sympy”]) print(” ✓ Installed\n”) importar numpy como np importar networkx como nx importar matplotlib.pyplot como plt desde qrisp importar ( QuantumVariable, QuantumFloat, QuantumChar, h, z, x, cx, p, control, QFT, multi_measurement, auto_uncompute ) desde qrisp.qaoa importar ( QAOAProblem, RX_mixer, create_maxcut_cost_operator, create_maxcut_cl_cost_function) del difusor de importación qrisp.grover

Comenzamos configurando el entorno de ejecución e instalando Qrisp junto con la pila científica mínima necesaria para ejecutar experimentos cuánticos. Importamos las primitivas centrales de Qrisp que nos permiten representar tipos de datos cuánticos, puertas y flujo de control. También preparamos las utilidades de optimización y Grover que posteriormente permitirán algoritmos variacionales y amplificación de amplitud. Consulta los CÓDIGOS COMPLETOS aquí.

def banner(título): print(“\n” + “=”*90) print(título) print(“=”*90) def topk_probs(prob_dict, k=10): elementos = ordenados(prob_dict.items(), clave=lambda kv: kv[1]reverso=Verdadero)[:k]
devolver elementos def print_topk(prob_dict, k=10, label=”Resultados principales”): items = topk_probs(prob_dict, k=k) print(label) para estado, problema en elementos: print(f” {state}: {prob:.4f}”) def bitstring_to_partition(bitstring): left = [i for i, b in enumerate(bitstring) if b == “0”]
derecha = [i for i, b in enumerate(bitstring) if b == “1”]
return izquierda, derecha def classic_maxcut_cost(G, bitstring): s = set(i para i, b in enumerate(bitstring) if b == “0”) cost = 0 for u, v in G.edges(): if (u in s) != (v in s): cost += 1 return cost banner(“SECCIÓN 1 — Qrisp Core: QuantumVariable, QuantumSession, GHZ State”) def GHZ(qv): h(qv)[0]) para i en rango(1, qv.size): cx(qv[0]qv[i]) qv = QuantumVariable(5) GHZ(qv) print(“Circuito (QuantumSession):”) print(qv.qs) print(“\nDistribución del estado (la impresión de QuantumVariable activa una vista dict similar a una medición):”) print(qv) meas = qv.get_measurement() print_topk(meas, k=6, label=”\nResultados medidos (aprox.)”) qch = Carácter Cuántico() h(qch[0]) print(“\nMuestra de medición de QuantumChar:”) print_topk(qch.get_measurement(), k=8)

Definimos funciones de utilidad que nos ayudan a inspeccionar distribuciones de probabilidad, interpretar cadenas de bits y evaluar costos clásicos para compararlos con resultados cuánticos. Luego construimos un estado GHZ para demostrar cómo Qrisp maneja el entrelazamiento y la composición de circuitos a través de abstracciones de alto nivel. También mostramos datos cuánticos tipificados utilizando QuantumChar, lo que refuerza cómo se pueden manipular y medir los valores cuánticos simbólicos. Consulta los CÓDIGOS COMPLETOS aquí.

banner(“SECCIÓN 2 — Grover + auto_uncompute: Resolver x^2 = 0.25 (Oráculo QuantumFloat)”) @auto_uncompute def sqrt_oracle(qf): cond = (qf * qf == 0.25) z(cond) qf = QuantumFloat(3, -1, firmado=True) n = qf.size iteraciones = int(0.25 * math.pi * math.sqrt((2**n) / 2)) print(f”QuantumFloat qubits: {n} | Iteraciones de Grover: {iteraciones}”) h(qf) for _ in range(iterations): sqrt_oracle(qf) difusor(qf) print(“\nDistribución de resultados de Grover (QuantumFloat imprime valores decodificados):”) print(qf) qf_meas = qf.get_measurement() print_topk(qf_meas, k=10, label=”\nTop valores medidos (decodificados por QuantumFloat):”)

Implementamos un oráculo de Grover utilizando no computación automática, lo que nos permite expresar lógica reversible sin limpiar manualmente los estados intermedios. Aplicamos amplificación de amplitud sobre un espacio de búsqueda QuantumFloat para resolver una ecuación no lineal simple mediante búsqueda cuántica. Finalmente inspeccionamos la distribución de medidas resultante para identificar las soluciones más probables producidas por el algoritmo de Grover. Consulta los CÓDIGOS COMPLETOS aquí.

banner(“SECCIÓN 3 — Estimación de fase cuántica (QPE): U controlada + QFT inverso”) def QPE(psi: QuantumVariable, U, precisión: int): res = QuantumFloat(precisión, -precisión, firmado=Falso) h(res) para i en rango(precisión): con control(res[i]): para _ en rango(2**i): U(psi) QFT(res, inv=True) return res def U_ejemplo(psi): phi_1 = 0,5 phi_2 = 0,125 p(phi_1 * 2 * np.pi, psi[0]) p(phi_2 * 2 * np.pi, psi[1]) psi = QuantumVariable(2) h(psi) res = QPE(psi, U_ejemplo, precisión=3) print(“Medición conjunta de (psi, fase_estimación):”) mm = multi_medición([psi, res]) elementos = ordenados (mm.elementos (), clave = lambda kv: (-kv[1]str(kv[0]))) para (psi_bits, fase_val), problema en elementos: print(f” psi={psi_bits} fase≈{phase_val} prob={prob:.4f}”)

Construimos un proceso completo de estimación de fase cuántica combinando aplicaciones unitarias controladas con una transformada cuántica de Fourier inversa. Demostramos cómo la información de fase se codifica en un registro cuántico con precisión sintonizable utilizando QuantumFloat. Luego medimos conjuntamente el sistema y los registros de fase para interpretar las fases propias estimadas. Consulta los CÓDIGOS COMPLETOS aquí.

banner(“SECCIÓN 4 – QAOA MaxCut: QAOAProblem.run + mejor visualización de corte”) G = nx.erdos_renyi_graph(6, 0.65, seed=133) mientras que G.number_of_edges() < 5: G = nx.erdos_renyi_graph(6, 0.65, seed=random.randint(0, 9999)) print(f"Gráfico: |V|={G.number_of_nodes()} |E|={G.number_of_edges()}") print("Bordes:", lista(G.edges())[:12]"..." if G.number_of_edges() > 12 else “”) qarg = QuantumVariable(G.number_of_nodes()) qaoa_maxcut = QAOAProblem( cost_operator=create_maxcut_cost_operator(G), mezclador=RX_mixer, cl_cost_function=create_maxcut_cl_cost_function(G), ) profundidad = 3 max_iter = 25 t0 = time.time() resultados = qaoa_maxcut.run(qarg, profundidad=profundidad, max_iter=max_iter) t1 = time.time() print(f”\nQAOA terminó en {t1 – t0:.2f}s (profundidad={profundidad}, max_iter={max_iter})”) print(“Tamaño de distribución de medición devuelta:”, len(resultados)) cl_cost = create_maxcut_cl_cost_function(G) print(“\nTop 8 cortes candidatos (cadena de bits, problema, costo):”) top8 = sorted(results.items(), key=lambda kv: kv[1]reverso=Verdadero)[:8]
para bitstr, problema en top8: cost_val = cl_cost({bitstr: 1}) print(f” {bitstr} prob={prob:.4f} cut_edges≈{cost_val}”) best_bitstr = top8[0][0]

best_cost = classic_maxcut_cost(G, best_bitstr) left, right = bitstring_to_partition(best_bitstr) print(f”\nSolución más probable: {best_bitstr}”) print(f”Partición 0-side: {left}”) print(f”Partición 1-side: {right}”) print(f”Bordes cruzados clásicos (verificados): {best_cost}”) pos = nx.spring_layout(G, semilla=42) node_colors = [“#6929C4” if best_bitstr[i] == “0” else “#20306f” para i en G.nodes()]plt.figure(figsize=(6.5, 5.2)) nx.draw( G, pos, with_labels=True, node_color=node_colors, node_size=900, font_color=”white”, edge_color=”#CCCCCC”, ) plt.title(f”QAOA MaxCut (mejor bitstring = {best_bitstr}, cut={best_cost})”) plt.show() banner(“HECHO: ahora tiene los flujos de trabajo Grover + QPE + QAOA ejecutándose en Qrisp en Colab ✅”) print(“Consejo: intente aumentar la profundidad de QAOA, cambiar el gráfico o intercambiar mezcladores (RX/RY/XY) para explorar el comportamiento.”)

Formulamos el problema MaxCut como una instancia de QAOA utilizando las abstracciones orientadas a problemas de Qrisp y ejecutamos un ciclo de optimización híbrido cuántico-clásico. Analizamos la distribución de probabilidad devuelta para identificar candidatos de corte de alta calidad y verificarlos con una función de costos clásica. Concluimos visualizando el mejor corte, conectando resultados cuánticos abstractos a una estructura gráfica intuitiva.

Concluimos mostrando cómo un flujo de trabajo Qrisp único y coherente nos permite pasar de la preparación de estados cuánticos de bajo nivel a algoritmos variacionales modernos utilizados en la computación cuántica a corto plazo. Al combinar la no computación automática, operaciones controladas y abstracciones orientadas a problemas como QAOAProblem, demostramos cómo creamos rápidamente prototipos y experimentamos con algoritmos cuánticos avanzados. Además, este tutorial establece una base sólida para ampliar nuestro trabajo hacia circuitos más profundos, mezcladores alternativos y funciones de costos, y experimentos híbridos cuánticos-clásicos más complejos.

Consulta los CÓDIGOS COMPLETOS aquí. Además, no dude en seguirnos en Twitter y no olvide unirse a nuestro SubReddit de más de 100.000 ML y suscribirse a nuestro boletín. ¡Esperar! estas en telegrama? Ahora también puedes unirte a nosotros en Telegram.