Aller au contenu principal

QUICK-PDE : une fonction Qiskit par ColibriTD

remarque

Les fonctions Qiskit sont une fonctionnalité expérimentale disponible pour les utilisateurs des plans IBM Quantum® Premium, Flex et On-Prem (via l'API IBM Quantum Platform). Elles sont en version préliminaire et sont susceptibles d'évoluer.

Vue d'ensemble

Le solveur d'équations aux dérivées partielles (EDP) présenté ici fait partie de notre plateforme Quantum Innovative Computing Kit (QUICK) (QUICK-PDE), et est packagé sous forme de fonction Qiskit. Avec la fonction QUICK-PDE, tu peux résoudre des équations aux dérivées partielles spécifiques à un domaine sur les QPU IBM Quantum. Cette fonction repose sur l'algorithme décrit dans l'article de présentation H-DES de ColibriTD. Cet algorithme peut résoudre des problèmes multi-physiques complexes, en commençant par la Dynamique des Fluides Numérique (CFD) et la Déformation des Matériaux (MD), avec d'autres cas d'usage à venir.

Pour traiter les équations différentielles, les solutions d'essai sont encodées comme des combinaisons linéaires de fonctions orthogonales (généralement des polynômes de Chebyshev, et plus précisément 2n2^n d'entre eux, où nn est le nombre de qubits encodant ta fonction), paramétrées par les angles d'un Circuit Quantique Variable (VQC). L'ansatz génère un état encodant la fonction, qui est évalué par des observables dont les combinaisons permettent d'évaluer la fonction en tous les points. Tu peux ensuite évaluer la fonction de perte dans laquelle les équations différentielles sont encodées, et affiner les angles dans une boucle hybride, comme illustré ci-dessous. Les solutions d'essai se rapprochent progressivement des solutions réelles jusqu'à obtenir un résultat satisfaisant.

Flux de travail de la fonction QUICK-PDE

En plus de cette boucle hybride, tu peux également enchaîner différents optimiseurs. C'est utile lorsque tu veux qu'un optimiseur global trouve un bon ensemble d'angles, puis qu'un optimiseur plus précis suive un gradient vers le meilleur ensemble d'angles voisins. Dans le cas de la dynamique des fluides numérique (CFD), la séquence d'optimisation par défaut produit les meilleurs résultats — mais dans le cas de la déformation des matériaux (MD), bien que les valeurs par défaut donnent de bons résultats, tu peux la configurer davantage pour des bénéfices propres au problème.

À noter que pour chaque variable de la fonction, on spécifie un nombre de qubits (que tu peux ajuster). En empilant 10 circuits identiques et en évaluant les 10 observables identiques sur des qubits différents dans un seul grand circuit, tu peux atténuer le bruit dans le cadre du processus d'optimisation CMA, en s'appuyant sur la méthode de l'apprentissage du bruit, et réduire significativement le nombre de shots nécessaires.

Entrée/sortie

Dynamique des Fluides Numérique

L'équation de Burgers non visqueuse modélise l'écoulement de fluides non visqueux de la façon suivante :

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

uu représente le champ de vitesse du fluide. Ce cas d'usage comporte une condition aux limites temporelle : tu peux sélectionner la condition initiale et laisser le système se relaxer. Actuellement, les seules conditions initiales acceptées sont les fonctions linéaires : ax+bax + b.

Les arguments des équations différentielles de CFD sont définis sur une grille fixe, comme suit :

  • tt est compris entre 0 et 0,95 avec 30 points d'échantillonnage. xx est compris entre 0 et 0,95 avec un pas de 0,2375.

Déformation des Matériaux

Ce cas d'usage porte sur la déformation hypoélastique avec le test de traction unidimensionnel, dans lequel une barre fixée dans l'espace est tirée à son autre extrémité. On décrit le problème comme suit :

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 représente le module de compressibilité du matériau étiré, nn l'exposant d'une loi de puissance, bb la force par unité de masse, ϵ0\epsilon_0 la limite de contrainte proportionnelle, σ0\sigma_0 la limite de déformation proportionnelle, uu la fonction de contrainte, et σ\sigma la fonction de déformation.

La barre considérée est de longueur unitaire. Ce cas d'usage comporte une condition aux limites pour la contrainte de surface tt, soit la quantité de travail nécessaire pour étirer la barre.

Les arguments des équations différentielles de MD sont définis sur une grille fixe, comme suit :

  • xx est compris entre 0 et 1 avec un pas de 0,04.

Entrée

Pour exécuter la fonction Qiskit QUICK-PDE, tu peux ajuster les paramètres suivants :

NomTypeDescriptionSpécifique au cas d'usageExemple
use_caseLiteral["MD", "CFD"]Sélectionne le système d'équations différentielles à résoudreNon"CFD"
parametersdict[str, Any]Paramètres de l'équation différentielle (voir le tableau suivant pour plus de détails)Non{"a": 1.0, "b": 1.0}
nb_qubitsOptional[dict[str, dict[str, int]]]Nombre de qubits par fonction et par variable. Des valeurs optimisées sont choisies par la fonction, mais si tu veux essayer de trouver une meilleure combinaison, tu peux remplacer les valeurs par défautNon{"u": {"x": 1, "t":3}}
depthOptional[dict[str, int]]Profondeur de l'ansatz par fonction. Des valeurs optimisées sont choisies par la fonction, mais si tu veux essayer de trouver une meilleure combinaison, tu peux remplacer les valeurs par défautNon{"u": 4}
optimizerOptional[list[str]]Optimiseurs à utiliser, soit "CMAES" de la bibliothèque Python cma, soit l'un des optimiseurs de scipyMD"SLSQP"
shotsOptional[list[int]]Nombre de shots utilisés pour exécuter chaque circuit. Comme plusieurs étapes d'optimisation sont nécessaires, la longueur de la liste doit être égale au nombre d'optimiseurs utilisés (4 dans le cas CFD). Par défaut [50_000] * nb_optimizers pour MD et [5_00, 2_000, 5_000, 10_000] pour CFDNon[15_000, 30_000]
optimizer_optionsOptional[dict[str, Any]]Options à transmettre à l'optimiseur. Le détail de cette entrée dépend de l'optimiseur utilisé ; pour les spécificités, consulte la documentation de l'optimiseur concernéMD{"maxiter": 50 }
initializationOptional[Literal["RANDOM", "PHYSICALLY_INFORMED"]]Indique s'il faut démarrer avec des angles aléatoires ou des angles choisis intelligemment. Attention : les angles choisis intelligemment peuvent ne pas fonctionner dans 100 % des cas. Par défaut "PHYSICALLY_INFORMED".Non"RANDOM"
backend_nameOptional[str]Le nom du backend à utiliser.Non"ibm_torino"
modeOptional[Literal["job", "session", "batch"]]Le mode d'exécution à utiliser. Par défaut "job".Non"job"

Les paramètres de l'équation différentielle (paramètres physiques et condition aux limites) doivent respecter le format suivant :

Cas d'usageCléType de valeurDescriptionExemple
CFDafloatCoefficient des valeurs initiales de uu1.0
CFDbfloatDécalage des valeurs initiales de uu1.0
MDtfloatcontrainte de surface12.0
MDKfloatmodule de compressibilité100.0
MDnintloi de puissance4.0
MDbfloatforce par unité de masse10.0
MDepsilon_0floatlimite de contrainte proportionnelle0.1
MDsigma_0floatlimite de déformation proportionnelle5.0

Sortie

La sortie est un dictionnaire contenant la liste des points d'échantillonnage ainsi que les valeurs des fonctions en chacun de ces points :

# 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 forme d'un tableau de solution dépend des échantillons des 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 correspondance entre les points d'échantillonnage des variables de la fonction et les dimensions du tableau de solution est établie dans l'ordre alphanumérique du nom de la variable. Par exemple, si les variables sont "t" et "x", une ligne de solution["functions"]["u"] représente les valeurs de la solution pour un "t" fixé, et une colonne de solution["functions"]["u"] représente les valeurs de la solution pour un "x" fixé.

Voici un exemple illustrant comment obtenir la valeur de la fonction pour un ensemble de coordonnées spécifiques :

# 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

Le tableau suivant présente des statistiques sur diverses exécutions de notre fonction.

ExempleNombre de qubitsInitialisationErreurTemps total (min)Utilisation du runtime (min)
Équation de Burgers non visqueuse50PHYSICALLY_INFORMED10210^{-2}6625
Test de traction 1D hypoélastique18RANDOM10210^{-2}123100

Prise en main

Remplis le formulaire pour demander l'accès à la fonction QUICK-PDE. Ensuite, en supposant que tu as déjà enregistré ton compte dans ton environnement local, sélectionne la fonction comme suit :

from qiskit_ibm_catalog import QiskitFunctionsCatalog

catalog = QiskitFunctionsCatalog(channel="ibm_quantum_platform")

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

Exemples

Pour commencer, essaie l'un des exemples suivants :

Dynamique des Fluides Numérique (CFD)

Lorsque les conditions initiales sont définies à u(0,x)=xu(0,x) = x, les résultats sont les suivants :

# 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})

Vérifie le statut de ta charge de travail de fonction Qiskit ou récupère les résultats comme suit :

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()

Sortie de la cellule de code précédente

Déformation des Matériaux

Le cas d'usage de la déformation des matériaux nécessite les paramètres physiques de ton matériau et la force appliquée, comme suit :

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()

Sortie de la cellule de code précédente

Récupérer les messages d'erreur

Si le statut de ta charge de travail est ERROR, utilise job.error_message() pour récupérer le message d'erreur et faciliter le débogage, comme suit :

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'

Obtenir de l'aide

Pour toute assistance, contacte qiskit-function-support@colibritd.com.

Prochaines étapes

Recommandations