Saltar al contenido principal

QUICK-PDE: Una Qiskit Function de ColibriTD

nota

Las Qiskit Functions son una funcionalidad experimental disponible para los usuarios de los planes IBM Quantum® Premium, Flex y On-Prem (mediante la API de IBM Quantum Platform). Se encuentran en estado de versión preliminar y están sujetas a cambios.

Descripción general

El solucionador de Ecuaciones Diferenciales Parciales (PDE) que se presenta aquí forma parte de nuestra plataforma Quantum Innovative Computing Kit (QUICK) (QUICK-PDE) y está empaquetado como una Qiskit Function. Con la función QUICK-PDE puedes resolver ecuaciones diferenciales parciales específicas de dominio en QPUs de IBM Quantum. Esta función se basa en el algoritmo descrito en el artículo de descripción del H-DES de ColibriTD. Este algoritmo puede resolver problemas complejos de múltiples físicas, comenzando con Dinámica de Fluidos Computacional (CFD) y Deformación de Materiales (MD), con más casos de uso próximamente.

Para abordar las ecuaciones diferenciales, las soluciones de prueba se codifican como combinaciones lineales de funciones ortogonales (típicamente polinomios de Chebyshev, y más específicamente 2n2^n de ellos, donde nn es el número de qubits que codifican tu función), parametrizadas por los ángulos de un Circuito Cuántico Variable (VQC). El ansatz genera un estado que codifica la función, que se evalúa mediante observables cuyas combinaciones permiten evaluar la función en todos los puntos. Luego puedes evaluar la función de pérdida en la que se codifican las ecuaciones diferenciales y ajustar los ángulos en un bucle híbrido, como se muestra a continuación. Las soluciones de prueba se acercan gradualmente a las soluciones reales hasta alcanzar un resultado satisfactorio.

Flujo de trabajo de la función QUICK-PDE

Además de este bucle híbrido, también puedes encadenar distintos optimizadores. Esto es útil cuando quieres que un optimizador global encuentre un buen conjunto de ángulos y luego un optimizador más fino siga un gradiente hasta el mejor conjunto de ángulos vecinos. En el caso de la dinámica de fluidos computacional (CFD), la secuencia de optimización predeterminada produce los mejores resultados; en el caso de la deformación de materiales (MD), aunque la opción predeterminada proporciona buenos resultados, puedes configurarla con mayor detalle para obtener beneficios específicos del problema.

Ten en cuenta que para cada variable de la función especificamos el número de qubits (con el que puedes experimentar). Al apilar 10 circuitos idénticos y evaluar los 10 observables idénticos en diferentes qubits a lo largo de un gran circuito, puedes aplicar mitigación de ruido dentro del proceso de optimización CMA, apoyándote en el método del noise learner, y reducir significativamente el número de shots necesarios.

Entrada/salida

Dinámica de Fluidos Computacional

La ecuación de Burgers no viscosa modela fluidos no viscosos en movimiento de la siguiente manera:

ut+uux=0,\frac{\partial u}{\partial t} + u\frac{\partial u}{\partial x} = 0,

uu representa el campo de velocidad del fluido. Este caso de uso tiene una condición de frontera temporal: puedes seleccionar la condición inicial y luego permitir que el sistema se relaje. Actualmente, las únicas condiciones iniciales aceptadas son funciones lineales: ax+bax + b.

Los argumentos para las ecuaciones diferenciales de CFD se encuentran en una cuadrícula fija, de la siguiente manera:

  • tt está entre 0 y 0.95 con 30 puntos de muestreo. xx está entre 0 y 0.95 con un tamaño de paso de 0.2375.

Deformación de Materiales

Este caso de uso se centra en la deformación hipoelástica con el ensayo de tracción unidimensional, en el que una barra fija en el espacio es jalada por su otro extremo. Describimos el problema de la siguiente manera:

uσ3K23ϵ0(σσ03)n=0u' - \frac{\sigma}{3K} - \frac{2}{\sqrt{3}}\epsilon_0\left(\frac{\sigma'}{\sigma_0\sqrt{3}}\right)^n = 0

σb=0,\sigma' - b = 0,

KK representa el módulo volumétrico del material que se estira, nn el exponente de una ley de potencias, bb la fuerza por unidad de masa, ϵ0\epsilon_0 el límite de tensión proporcional, σ0\sigma_0 el límite de deformación proporcional, uu la función de tensión y σ\sigma la función de deformación.

La barra considerada tiene longitud unitaria. Este caso de uso tiene una condición de frontera para la tensión superficial tt, es decir, la cantidad de trabajo necesaria para estirar la barra.

Los argumentos para las ecuaciones diferenciales de MD se encuentran en una cuadrícula fija, de la siguiente manera:

  • xx está entre 0 y 1 con un tamaño de paso de 0.04.

Entrada

Para ejecutar la Qiskit Function QUICK-PDE, puedes ajustar los siguientes parámetros:

NombreTipoDescripciónEspecífico del caso de usoEjemplo
use_caseLiteral["MD", "CFD"]Selecciona el sistema de ecuaciones diferenciales a resolverNo"CFD"
parametersdict[str, Any]Parámetros de la ecuación diferencial (consulta la siguiente tabla para más detalles)No{"a": 1.0, "b": 1.0}
nb_qubitsOptional[dict[str, dict[str, int]]]Número de qubits por función y por variable. La función elige valores optimizados, pero si quieres probar una combinación diferente, puedes reemplazar los valores predeterminadosNo{"u": {"x": 1, "t":3}}
depthOptional[dict[str, int]]Profundidad del ansatz por función. La función elige valores optimizados, pero si quieres probar una combinación diferente, puedes reemplazar los valores predeterminadosNo{"u": 4}
optimizerOptional[list[str]]Optimizadores a utilizar, ya sea "CMAES" de la biblioteca Python cma o uno de los optimizadores de scipyMD"SLSQP"
shotsOptional[list[int]]Número de shots utilizados para ejecutar cada circuito. Como se necesitan varios pasos de optimización, la longitud de la lista debe ser igual al número de optimizadores usados (4 en el caso de CFD). Por defecto es [50_000] * nb_optimizers para MD y [5_00, 2_000, 5_000, 10_000] para CFDNo[15_000, 30_000]
optimizer_optionsOptional[dict[str, Any]]Opciones para pasar al optimizador. Los detalles de esta entrada dependen del optimizador usado; para más información consulta la documentación del optimizador correspondienteMD{"maxiter": 50 }
initializationOptional[Literal["RANDOM", "PHYSICALLY_INFORMED"]]Indica si empezar con ángulos aleatorios o ángulos elegidos de forma inteligente. Ten en cuenta que los ángulos elegidos de forma inteligente pueden no funcionar en el 100% de los casos. Por defecto es "PHYSICALLY_INFORMED".No"RANDOM"
backend_nameOptional[str]El nombre del backend a utilizar.No"ibm_torino"
modeOptional[Literal["job", "session", "batch"]]El modo de ejecución a utilizar. Por defecto es "job".No"job"

Los parámetros de la ecuación diferencial (parámetros físicos y condición de frontera) deben seguir el siguiente formato:

Caso de usoClaveTipo de valorDescripciónEjemplo
CFDafloatCoeficiente de los valores iniciales de uu1.0
CFDbfloatDesplazamiento de los valores iniciales de uu1.0
MDtfloattensión superficial12.0
MDKfloatmódulo volumétrico100.0
MDnintley de potencias4.0
MDbfloatfuerza por unidad de masa10.0
MDepsilon_0floatlímite de tensión proporcional0.1
MDsigma_0floatlímite de deformación proporcional5.0

Salida

La salida es un diccionario con la lista de puntos de muestreo, así como los valores de las funciones en cada uno de esos puntos:

# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib numpy qiskit-ibm-catalog
from numpy import array
solution = {
"functions": {
"u": array(
[
[0.01, 0.1, 1],
[0.02, 0.2, 2],
[0.03, 0.3, 3],
[0.04, 0.4, 4],
]
),
},
"samples": {
"t": array([0.1, 0.2, 0.3, 0.4]),
"x": array([0.5, 0.6, 0.7]),
},
}

La forma de un array de solución depende de los muestreos de las variables:

assert len(solution["functions"]["u"].shape) == len(solution["samples"])
for col_size, samples in zip(
solution["functions"]["u"].shape, solution["samples"].values()
):
assert col_size == len(samples)

La correspondencia entre los puntos de muestreo de las variables de la función y la dimensión del array de solución se establece en orden alfanumérico del nombre de la variable. Por ejemplo, si las variables son "t" y "x", una fila de solution["functions"]["u"] representa los valores de la solución para un "t" fijo, y una columna de solution["functions"]["u"] representa los valores de la solución para un "x" fijo.

A continuación se muestra un ejemplo de cómo obtener el valor de la función para un conjunto específico de coordenadas:

# u(t=0.2, x=0.7) == 2
assert solution["samples"]["t"][1] == 0.2
assert solution["samples"]["x"][2] == 0.7
assert solution["functions"]["u"][1, 2] == 2

Benchmarks

La siguiente tabla presenta estadísticas de varias ejecuciones de nuestra función.

EjemploNúmero de qubitsInicializaciónErrorTiempo total (min)Uso de runtime (min)
Ecuación de Burgers no viscosa50PHYSICALLY_INFORMED10210^{-2}6625
Ensayo de tracción hipoelástica 1D18RANDOM10210^{-2}123100

Comenzar

Rellena el formulario para solicitar acceso a la función QUICK-PDE. Luego, suponiendo que ya has guardado tu cuenta en tu entorno local, selecciona la función de la siguiente manera:

from qiskit_ibm_catalog import QiskitFunctionsCatalog

catalog = QiskitFunctionsCatalog(channel="ibm_quantum_platform")

quick = catalog.load("colibritd/quick-pde")

Ejemplos

Para empezar, prueba uno de los siguientes ejemplos:

Dinámica de Fluidos Computacional (CFD)

Cuando las condiciones iniciales se establecen como u(0,x)=xu(0,x) = x, los resultados son los siguientes:

# launch the simulation with initial conditions u(0,x) = a*x + b
job = quick.run(use_case="cfd", physical_parameters={"a": 1.0, "b": 0.0})

Verifica el estado de la carga de trabajo de tu Qiskit Function u obtén los resultados de la siguiente manera:

print(job.status())
solution = job.result()
'QUEUED'
import numpy as np
import matplotlib.pyplot as plt

_ = plt.figure()
ax = plt.axes(projection="3d")

# plot the solution using the 3d plotting capabilities of pyplot
t, x = np.meshgrid(solution["samples"]["t"], solution["samples"]["x"])
ax.plot_surface(
t,
x,
solution["functions"]["u"],
edgecolor="royalblue",
lw=0.25,
rstride=26,
cstride=26,
alpha=0.3,
)
ax.scatter(t, x, solution["functions"]["u"], marker=".")
ax.set(xlabel="t", ylabel="x", zlabel="u(t,x)")

plt.show()

Resultado de la celda de código anterior

Deformación de Materiales

El caso de uso de deformación de materiales requiere los parámetros físicos del material y la fuerza aplicada, de la siguiente manera:

import matplotlib.pyplot as plt

# select the properties of your material
job = quick.run(
use_case="md",
physical_parameters={
"t": 12.0,
"K": 100.0,
"n": 4.0,
"b": 10.0,
"epsilon_0": 0.1,
"sigma_0": 5.0,
},
)

# plot the result
solution = job.result()

_ = plt.figure()
stress_plot = plt.subplot(211)
plt.plot(solution["samples"]["x"], solution["functions"]["u"])
strain_plot = plt.subplot(212)
plt.plot(solution["samples"]["x"], solution["functions"]["sigma"])

plt.show()

Resultado de la celda de código anterior

Obtener mensajes de error

Si el estado de tu carga de trabajo es ERROR, usa job.error_message() para obtener el mensaje de error que te ayude a depurar, de la siguiente manera:

job = quick.run(use_case="mdf", physical_params={})

print(job.error_message())

# or write a wrapper around it for a more human readable version
def pprint_error(job):
print("".join(eval(job.error_message())["error"]))

print("___")
pprint_error(job)
{"error": ["qiskit.exceptions.QiskitError: 'Unknown argument \"physical_params\", did you make a typo? -- https://docs.quantum.ibm.com/errors#1804'\n"]}
___
qiskit.exceptions.QiskitError: 'Unknown argument "physical_params", did you make a typo? -- https://docs.quantum.ibm.com/errors#1804'

Obtener soporte

Para obtener soporte, contacta a qiskit-function-support@colibritd.com.

Próximos pasos

Recomendaciones