Pular para o conteúdo principal

QUICK-PDE: Uma Função Qiskit da ColibriTD

nota

As Funções Qiskit são um recurso experimental disponível para usuários dos planos IBM Quantum® Premium, Flex e On-Prem (via API da IBM Quantum Platform). Elas estão em status de versão prévia e sujeitas a alterações.

Visão geral

O solver de Equações Diferenciais Parciais (EDP) apresentado aqui faz parte da nossa plataforma Quantum Innovative Computing Kit (QUICK) (QUICK-PDE), e é disponibilizado como uma Função Qiskit. Com a função QUICK-PDE, você pode resolver equações diferenciais parciais específicas de domínio em QPUs da IBM Quantum. Esta função é baseada no algoritmo descrito no artigo de descrição do H-DES da ColibriTD. Esse algoritmo pode resolver problemas complexos de múltipla física, começando com Dinâmica de Fluidos Computacional (DFC) e Deformação de Materiais (DM), com outros casos de uso chegando em breve.

Para lidar com as equações diferenciais, as soluções tentativas são codificadas como combinações lineares de funções ortogonais (tipicamente polinômios de Chebyshev, e mais especificamente 2n2^n deles, onde nn é o número de qubits que codificam sua função), parametrizadas pelos ângulos de um Circuito Quântico Variacional (VQC). O ansatz gera um estado que codifica a função, avaliado por observáveis cujas combinações permitem calcular a função em todos os pontos. Você pode então avaliar a função de perda na qual as equações diferenciais são codificadas e ajustar os ângulos em um laço híbrido, como mostrado a seguir. As soluções tentativas se aproximam gradualmente das soluções reais até que você alcance um resultado satisfatório.

Fluxo de trabalho da função QUICK-PDE

Além desse laço híbrido, você também pode encadear diferentes otimizadores. Isso é útil quando você quer que um otimizador global encontre um bom conjunto de ângulos e, em seguida, um otimizador mais refinado siga um gradiente até o melhor conjunto de ângulos vizinhos. No caso de dinâmica de fluidos computacional (DFC), a sequência de otimização padrão produz os melhores resultados — mas no caso de deformação de materiais (DM), embora o padrão forneça bons resultados, você pode configurá-lo para benefícios específicos do problema.

Observe que, para cada variável da função, especificamos o número de qubits (com o qual você pode experimentar). Ao empilhar 10 circuitos idênticos e avaliar os 10 observáveis idênticos em qubits diferentes ao longo de um único circuito grande, você pode mitigar ruído dentro do processo de otimização CMA, confiando no método de aprendizado de ruído, e reduzir significativamente o número de shots necessários.

Entrada/saída

Dinâmica de Fluidos Computacional

A equação de Burgers invíscida modela fluidos não viscosos em escoamento da seguinte forma:

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

uu representa o campo de velocidade do fluido. Esse caso de uso tem uma condição de contorno temporal: você pode selecionar a condição inicial e então permitir que o sistema relaxe. Atualmente, as únicas condições iniciais aceitas são funções lineares: ax+bax + b.

Os argumentos para as equações diferenciais da DFC estão em uma grade fixa, como segue:

  • tt está entre 0 e 0,95 com 30 pontos de amostra. xx está entre 0 e 0,95 com um tamanho de passo de 0,2375.

Deformação de Materiais

Este caso de uso foca na deformação hipoelástica com o teste de tração unidimensional, no qual uma barra fixada no espaço é puxada em sua outra extremidade. Descrevemos o problema da seguinte forma:

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 o módulo volumétrico do material sendo esticado, nn o expoente de uma lei de potência, bb a força por unidade de massa, ϵ0\epsilon_0 o limite de tensão proporcional, σ0\sigma_0 o limite de deformação proporcional, uu a função de tensão e σ\sigma a função de deformação.

A barra considerada tem comprimento unitário. Este caso de uso tem uma condição de contorno para a tensão superficial tt, ou seja, a quantidade de trabalho necessária para esticar a barra.

Os argumentos para as equações diferenciais da DM estão em uma grade fixa, como segue:

  • xx está entre 0 e 1 com um tamanho de passo de 0,04.

Entrada

Para executar a Função Qiskit QUICK-PDE, você pode ajustar os seguintes parâmetros:

NomeTipoDescriçãoEspecífico do caso de usoExemplo
use_caseLiteral["MD", "CFD"]Opção para selecionar o sistema de equações diferenciais a resolverNão"CFD"
parametersdict[str, Any]Parâmetros da equação diferencial (veja a próxima tabela para mais detalhes)Não{"a": 1.0, "b": 1.0}
nb_qubitsOptional[dict[str, dict[str, int]]]Número de qubits por função e por variável. Valores otimizados são escolhidos pela função, mas se você quiser tentar encontrar uma combinação melhor, pode substituir os valores padrãoNão{"u": {"x": 1, "t":3}}
depthOptional[dict[str, int]]Profundidade do ansatz por função. Valores otimizados são escolhidos pela função, mas se você quiser tentar encontrar uma combinação melhor, pode substituir os valores padrãoNão{"u": 4}
optimizerOptional[list[str]]Otimizadores a serem usados, sendo "CMAES" da biblioteca python cma ou um dos otimizadores do scipyDM"SLSQP"
shotsOptional[list[int]]Número de shots usados para executar cada circuito. Como vários passos de otimização são necessários, o comprimento da lista deve ser igual ao número de otimizadores usados (4 no caso de DFC). O padrão é [50_000] * nb_optimizers para DM e [5_00, 2_000, 5_000, 10_000] para DFCNão[15_000, 30_000]
optimizer_optionsOptional[dict[str, Any]]Opções a passar para o otimizador. Os detalhes desta entrada dependem do otimizador usado; para especificidades, consulte a documentação do otimizador utilizadoDM{"maxiter": 50 }
initializationOptional[Literal["RANDOM", "PHYSICALLY_INFORMED"]]Se deve começar com ângulos aleatórios ou ângulos escolhidos de forma inteligente. Atenção: ângulos escolhidos de forma inteligente podem não funcionar em 100% dos casos. O padrão é "PHYSICALLY_INFORMED".Não"RANDOM"
backend_nameOptional[str]O nome do backend a usar.Não"ibm_torino"
modeOptional[Literal["job", "session", "batch"]]O modo de execução a usar. O padrão é "job".Não"job"

Os parâmetros da equação diferencial (parâmetros físicos e condição de contorno) devem seguir o formato fornecido:

Caso de usoChaveTipo do valorDescriçãoExemplo
DFCafloatCoeficiente dos valores iniciais de uu1.0
DFCbfloatDeslocamento dos valores iniciais de uu1.0
DMtfloattensão superficial12.0
DMKfloatmódulo volumétrico100.0
DMnintlei de potência4.0
DMbfloatforça por unidade de massa10.0
DMepsilon_0floatlimite de tensão proporcional0.1
DMsigma_0floatlimite de deformação proporcional5.0

Saída

A saída é um dicionário com a lista de pontos de amostra, bem como os valores das funções em cada um desses pontos:

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

O formato de um array de solução depende das amostras das variáveis:

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)

O mapeamento entre os pontos de amostra das variáveis da função e as dimensões do array de solução é feito em ordem alfanumérica do nome da variável. Por exemplo, se as variáveis são "t" e "x", uma linha de solution["functions"]["u"] representa os valores da solução para um "t" fixo, e uma coluna de solution["functions"]["u"] representa os valores da solução para um "x" fixo.

A seguir há um exemplo de como obter o valor da função para um 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

A tabela a seguir apresenta estatísticas sobre várias execuções da nossa função.

ExemploNúmero de qubitsInicializaçãoErroTempo total (min)Uso do runtime (min)
Equação de Burgers invíscida50PHYSICALLY_INFORMED10210^{-2}6625
Teste de tração hipoelástico 1D18RANDOM10210^{-2}123100

Primeiros passos

Preencha o formulário para solicitar acesso à função QUICK-PDE. Em seguida, assumindo que você já salvou sua conta em seu ambiente local, selecione a função da seguinte forma:

from qiskit_ibm_catalog import QiskitFunctionsCatalog

catalog = QiskitFunctionsCatalog(channel="ibm_quantum_platform")

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

Exemplos

Para começar, experimente um dos seguintes exemplos:

Dinâmica de Fluidos Computacional (DFC)

Quando as condições iniciais são definidas como u(0,x)=xu(0,x) = x, os resultados são os seguintes:

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

Verifique o status ou retorne os resultados da carga de trabalho da sua Função Qiskit da seguinte forma:

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

Saída da célula de código anterior

Deformação de Materiais

O caso de uso de deformação de materiais requer os parâmetros físicos do seu material e a força aplicada, da seguinte forma:

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

Saída da célula de código anterior

Recuperar mensagens de erro

Se o status da sua carga de trabalho for ERROR, use job.error_message() para recuperar a mensagem de erro e ajudar na depuração, da seguinte forma:

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'

Obter suporte

Para suporte, entre em contato com qiskit-function-support@colibritd.com.

Próximos passos

Recomendações