Docs
Ir a plataforma

Harmoniq · Ejemplos

Repositorio de circuitos cuánticos

Algoritmos canónicos implementados sobre el SDK de HarmoniQ. Cada ejemplo incluye teoría, diagrama de circuito y código listo para Swift, Kotlin, React y Python.

Swift Kotlin React Python

Fundamentos del entrelazamiento

Estado de Bell

Preparación del par entrelazado maximalmente |Φ⁺⟩. El ejemplo más sencillo de correlaciones cuánticas no clásicas.

HarmoniQ: configura la API key al iniciar la app y ejecuta el mismo circuito con HarmoniQ.quantum.executeCircuit (Swift/Kotlin/React) o HarmoniQ.quantum.execute_circuit (Python). Backend recomendado para 2 cúbits: hopper.

Algoritmos de oráculo

Deutsch-Jozsa

Determina si una función booleana es constante o balanceada con una sola consulta al oráculo. Ventaja cuántica exponencial sobre algoritmos clásicos deterministas.

HarmoniQ: misma API que Bell — lista de Gate y executeCircuit / execute_circuit. El primer bit de mostFrequent distingue constante (0…) vs balanceada (1…) con la función balanceada f(x)=x.

Swift

iOS 17.6+ · macOS 14.6+ · Swift 5.9+

El SDK para Swift está diseñado para aplicaciones iOS y macOS. Se distribuye mediante Swift Package Manager y expone una API asíncrona con async/await que se integra de forma natural con SwiftUI y UIKit.

Instalación

Opción 1 — Xcode (recomendado): Ve a File → Add Package Dependencies… e ingresa la URL del repositorio:

https://github.com/planq/HarmoniQ-Swift.git

Opción 2 — Package.swift:

Package.swift

// swift-tools-version: 5.9
import PackageDescription

let package = Package(
    name: "MiAppCuantica",
    platforms: [
        .iOS(.v17),
        .macOS(.v14),
    ],
    dependencies: [
        .package(
            url: "https://github.com/planq/HarmoniQ-Swift.git",
            from: "1.0.0"
        ),
    ],
    targets: [
        .target(
            name: "MiAppCuantica",
            dependencies: ["HarmoniQ"]
        ),
    ]
)

Configuración

Llama a HarmoniQ.configure(apiKey:) una sola vez al arrancar la app, normalmente en AppDelegate.application(_:didFinishLaunchingWithOptions:) o en el punto de entrada @main de SwiftUI. Puedes obtener tu API Key desde el panel de usuario en planq.com.blog.

Configuración inicial

import HarmoniQ

// Configuración básica (backend se selecciona en cada llamada)
HarmoniQ.configure(apiKey: "tu-api-key-de-planq")

// Opcionalmente, con backend por defecto:
HarmoniQ.configure(apiKey: "tu-api-key-de-planq", backend: "hopper")

Primer circuito: Deutsch-Jozsa

El algoritmo de Deutsch-Jozsa distingue si una función booleana es constante o balanceada con una sola consulta al oráculo. En el caso balanceado el resultado de medición es siempre |10⟩; en el constante es |00⟩. Es el ejemplo canónico de ventaja cuántica exponencial sobre algoritmos clásicos deterministas.

DeutschJozsa.swift

import HarmoniQ

// Circuito para función balanceada f(x) = x
let gates: [Gate] = [
    Gate(name: "x",    targets: [1]),
    Gate(name: "h",    targets: [0]),
    Gate(name: "h",    targets: [1]),
    Gate(name: "cnot", targets: [1], controls: [0]),
    Gate(name: "h",    targets: [0]),
]

do {
    let result = try await HarmoniQ.quantum.executeCircuit(
        provider: "hopper",  // "hopper" (20 q) o "hermann" (70 q)
        shots:    1024,
        qubits:   2,
        bits:     2,
        gates:    gates,
        basis:    "Z"
    )

    // Balanceada → "|10": 1024, constante → "|00": 1024
    print("Distribución:", result.counts)
    print("Estado dominante:", result.mostFrequent)
} catch {
    print("Error:", error)
}

Manejo de errores

HarmoniQ lanza valores tipados de HarmoniQError que puedes capturar con bloques catch específicos. Esto permite distinguir errores de configuración, autenticación, límites de tasa y fallos de red sin analizar cadenas de texto.

Manejo de errores

do {
    let result = try await HarmoniQ.quantum.executeCircuit(...)

} catch HarmoniQError.notConfigured {
    print("Llama a HarmoniQ.configure(apiKey:) antes de usar el SDK")

} catch HarmoniQError.invalidResponse {
    print("Respuesta inválida del servidor")

} catch HarmoniQError.httpError(let code) {
    switch code {
    case 401: print("API Key inválida o expirada")
    case 429: print("Límite de solicitudes excedido. Espera e intenta de nuevo")
    case 503: print("Servicio no disponible temporalmente")
    default:  print("Error HTTP \(code)")
    }

} catch {
    print("Error inesperado:", error.localizedDescription)
}

Kotlin

Android · Kotlin 1.9+ · Coroutines

El SDK de Kotlin aprovecha las coroutines de Kotlinx para exponer llamadas asíncronas sin callbacks. Todas las funciones de red son funciones suspend que se llaman dentro de un CoroutineScope o con launch/async.

Instalación

Agrega la dependencia en tu archivo build.gradle.kts a nivel de módulo:

build.gradle.kts

dependencies {
    implementation("com.planq:harmoniq-android:1.0.0")
    // Kotlinx Coroutines (requerido)
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
}

Asegúrate de que tu minSdk sea 26 o superior y de tener habilitado compileOptions { sourceCompatibility = JavaVersion.VERSION_17 }.

Configuración

Inicializa el SDK en tu clase Application para garantizar que la configuración esté disponible antes de cualquier llamada.

MyApplication.kt

import android.app.Application
import com.planq.harmoniq.HarmoniQ

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        HarmoniQ.configure(apiKey = "tu-api-key-de-planq")
    }
}

Registra MyApplication en tu AndroidManifest.xml con el atributo android:name=".MyApplication" en la etiqueta <application>.

Primer circuito: Deutsch-Jozsa

Las llamadas al SDK son funciones suspend; debes ejecutarlas dentro de un scope de coroutines. En un ViewModel usa viewModelScope.launch; en pruebas usa runTest de kotlinx-coroutines-test.

QuantumViewModel.kt

import com.planq.harmoniq.HarmoniQ
import com.planq.harmoniq.model.Gate

val gates = listOf(
    Gate(name = "x",    targets = listOf(1)),
    Gate(name = "h",    targets = listOf(0)),
    Gate(name = "h",    targets = listOf(1)),
    Gate(name = "cnot", targets = listOf(1), controls = listOf(0)),
    Gate(name = "h",    targets = listOf(0)),
)

viewModelScope.launch {
    val result = HarmoniQ.quantum.executeCircuit(
        provider = "hopper",
        shots    = 1024,
        qubits   = 2,
        bits     = 2,
        gates    = gates,
        basis    = "Z"
    )

    Log.d("HarmoniQ", "Distribución: ${result.counts}")
    Log.d("HarmoniQ", "Estado dominante: ${result.mostFrequent}")
}

Manejo de errores

Todas las excepciones de HarmoniQ heredan de HarmoniQException. Puedes capturar casos específicos o el tipo base según el nivel de detalle que necesites en tu lógica de negocio.

Manejo de errores — Kotlin

import com.planq.harmoniq.error.HarmoniQException
import com.planq.harmoniq.error.NotConfiguredException
import com.planq.harmoniq.error.HttpException

try {
    val result = HarmoniQ.quantum.executeCircuit(...)

} catch (e: NotConfiguredException) {
    Log.e("HarmoniQ", "API Key no configurada: ${e.message}")

} catch (e: HttpException) {
    when (e.statusCode) {
        401  -> Log.e("HarmoniQ", "API Key inválida o expirada")
        429  -> Log.e("HarmoniQ", "Límite de solicitudes excedido")
        503  -> Log.e("HarmoniQ", "Servicio no disponible")
        else -> Log.e("HarmoniQ", "Error HTTP ${e.statusCode}")
    }

} catch (e: HarmoniQException) {
    Log.e("HarmoniQ", "Error de ejecución: ${e.message}")

} catch (e: Exception) {
    Log.e("HarmoniQ", "Error inesperado: ${e.localizedMessage}")
}

React

TypeScript · React 18+ · Next.js compatible

El paquete @planq/harmoniq es un módulo ESM con tipos TypeScript completos. Funciona con React, Next.js, Vite y cualquier entorno que soporte módulos ES2022. Las llamadas de red son Promise-based y compatibles con async/await.

Instalación

npm install @planq/harmoniq

O con tu gestor de paquetes preferido:

Gestores de paquetes

# npm
npm install @planq/harmoniq

# yarn
yarn add @planq/harmoniq

# pnpm
pnpm add @planq/harmoniq

# bun
bun add @planq/harmoniq

Configuración

Crea un módulo de configuración que inicialice el SDK una vez. En Next.js, exporta la instancia desde lib/quantum.ts; en Vite, llama a configure() en el punto de entrada de tu app. Usa variables de entorno con el prefijo NEXT_PUBLIC_ (Next.js) o VITE_ (Vite) para no exponer la clave en el código fuente.

lib/quantum.ts

import { HarmoniQ } from '@planq/harmoniq'

HarmoniQ.configure({
  apiKey: process.env.NEXT_PUBLIC_PLANQ_API_KEY ?? '',
  // backend opcional; se especifica en cada llamada si no se define aquí
})

export { HarmoniQ }

Primer circuito: Deutsch-Jozsa

El ejemplo siguiente muestra un hook React que ejecuta el algoritmo de Deutsch-Jozsa y almacena los resultados en estado local. El componente renderiza la distribución de medición de forma reactiva.

useDeutschJozsa.ts

import { useState, useCallback } from 'react'
import { HarmoniQ } from './lib/quantum'
import type { Gate, ExecutionResult } from '@planq/harmoniq'

const GATES: Gate[] = [
  { name: 'x',    targets: [1] },
  { name: 'h',    targets: [0] },
  { name: 'h',    targets: [1] },
  { name: 'cnot', targets: [1], controls: [0] },
  { name: 'h',    targets: [0] },
]

export function useDeutschJozsa() {
  const [result, setResult] = useState<ExecutionResult | null>(null)
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState<string | null>(null)

  const run = useCallback(async () => {
    setLoading(true)
    setError(null)
    try {
      const res = await HarmoniQ.quantum.executeCircuit({
        provider: 'hopper',
        shots:    1024,
        qubits:   2,
        bits:     2,
        gates:    GATES,
        basis:    'Z',
      })
      setResult(res)
    } catch (e) {
      setError(e instanceof Error ? e.message : 'Error desconocido')
    } finally {
      setLoading(false)
    }
  }, [])

  return { result, loading, error, run }
}

Manejo de errores

El SDK lanza instancias de HarmoniQError con un campo code del enumerado ErrorCode. Esto permite distinguir casos sin analizar mensajes de texto y facilita la localización.

Manejo de errores — TypeScript

import { HarmoniQError, ErrorCode } from '@planq/harmoniq'

try {
  const result = await HarmoniQ.quantum.executeCircuit({ ... })

} catch (error) {
  if (error instanceof HarmoniQError) {
    switch (error.code) {
      case ErrorCode.NotConfigured:
        console.error('Llama a HarmoniQ.configure() antes de usar el SDK')
        break
      case ErrorCode.Unauthorized:
        console.error('API Key inválida o expirada')
        break
      case ErrorCode.RateLimited:
        console.error('Límite de solicitudes excedido. Espera antes de reintentar')
        break
      default:
        console.error('Error HarmoniQ:', error.message)
    }
  } else {
    console.error('Error inesperado:', error)
  }
}

Python

Python 3.10+ · asyncio · Jupyter compatible

El paquete Python es síncrono por defecto pero ofrece una interfaz async opcional para entornos basados en asyncio. También incluye utilidades de visualización (plot_histogram, plot_bloch) pensadas para flujos de trabajo en Jupyter Notebook.

Instalación

pip install harmoniq

Gestores de paquetes

# pip (PyPI)
pip install harmoniq

# conda
conda install -c planq harmoniq

# Poetry
poetry add harmoniq

# uv (recomendado para entornos rápidos)
uv add harmoniq

Requiere Python ≥ 3.10. Para usar las utilidades de visualización instala también pip install harmoniq[viz], que incluye matplotlib y ipywidgets.

Configuración

Puedes configurar el SDK de tres formas: llamada directa, variable de entorno PLANQ_API_KEY (cargada automáticamente al importar el módulo), o archivo ~/.planq/credentials.toml generado por el CLI de PlanQ.

Configuración — Python

import harmoniq

# Opción 1: llamada directa
harmoniq.configure(api_key="tu-api-key-de-planq")

# Opción 2: variable de entorno (sin llamada explícita)
# export PLANQ_API_KEY="tu-api-key-de-planq"

# Opción 3: con backend por defecto
harmoniq.configure(api_key="tu-api-key-de-planq", backend="hopper")

Primer circuito: Deutsch-Jozsa

Python usa snake_case en lugar de camelCase: el método es execute_circuit y el atributo del resultado es most_frequent. En Jupyter puedes llamar a result.plot_histogram() directamente para visualizar la distribución.

deutsch_jozsa.py

from harmoniq import HarmoniQ, Gate

gates = [
    Gate(name="x",    targets=[1]),
    Gate(name="h",    targets=[0]),
    Gate(name="h",    targets=[1]),
    Gate(name="cnot", targets=[1], controls=[0]),
    Gate(name="h",    targets=[0]),
]

result = HarmoniQ.quantum.execute_circuit(
    provider="hopper",   # "hopper" (20 q) o "hermann" (70 q)
    shots=1024,
    qubits=2,
    bits=2,
    gates=gates,
    basis="Z",
)

print("Distribución:", result.counts)
print("Estado dominante:", result.most_frequent)

# En Jupyter Notebook:
# result.plot_histogram()   → gráfica de barras de la distribución
# result.plot_bloch()       → esfera de Bloch para circuitos de 1 cúbit

Manejo de errores

El SDK lanza excepciones específicas que heredan de HarmoniQError. Puedes capturar la clase base o subtipos concretos para implementar lógica de reintento o notificación al usuario.

Manejo de errores — Python

from harmoniq import HarmoniQ
from harmoniq.errors import (
    HarmoniQError,
    NotConfiguredError,
    UnauthorizedError,
    RateLimitError,
)

try:
    result = HarmoniQ.quantum.execute_circuit(...)

except NotConfiguredError:
    print("Llama a harmoniq.configure(api_key=...) antes de usar el SDK")

except UnauthorizedError:
    print("API Key inválida o expirada. Genera una nueva en planq.com")

except RateLimitError as e:
    print(f"Límite excedido. Reintenta en {e.retry_after}s")

except HarmoniQError as e:
    print(f"Error de ejecución [{e.status_code}]: {e.message}")

except Exception as e:
    print(f"Error inesperado: {e}")