Pular para o conteúdo principal

Biblioteca de circuitos

Versões dos pacotes

O código nesta página foi desenvolvido usando os seguintes requisitos. Recomendamos usar essas versões ou mais recentes.

qiskit[all]~=2.3.0

O SDK do Qiskit inclui uma biblioteca de circuitos populares para usar como blocos de construção nos seus próprios programas. Usar circuitos pré-definidos economiza tempo de pesquisa, escrita de código e depuração. A biblioteca inclui circuitos populares em computação quântica, circuitos difíceis de simular classicamente e circuitos úteis para benchmarking de hardware quântico.

Esta página lista as diferentes categorias de circuitos que a biblioteca fornece. Para uma lista completa de circuitos, consulte a documentação da API da biblioteca de circuitos.

Gates padrão

A biblioteca de circuitos também inclui gates quânticos padrão. Alguns são gates mais fundamentais (como o UGate), e outros são gates multi-qubit que geralmente precisam ser construídos a partir de gates de um e dois qubits. Para adicionar gates importados ao seu circuito, use o método append; o primeiro argumento é o gate, e o próximo argumento é uma lista de qubits aos quais aplicar o gate.

Por exemplo, o seguinte bloco de código cria um circuito com um gate de Hadamard e um gate multi-controlled-X.

# Added by doQumentation — required packages for this notebook
!pip install -q qiskit
from qiskit import QuantumCircuit
from qiskit.circuit.library import HGate, MCXGate

mcx_gate = MCXGate(3)
hadamard_gate = HGate()

qc = QuantumCircuit(4)
qc.append(hadamard_gate, [0])
qc.append(mcx_gate, [0, 1, 2, 3])
qc.draw("mpl")

Output of the previous code cell

Consulte Standard gates na documentação da API da biblioteca de circuitos.

Not sure what your gate's called? Try asking Qiskit Code Assistant.

Circuitos N-local

Esses circuitos alternam camadas de gates de rotação de qubit único com camadas de gates de emaranhamento multi-qubit.

Essa família de circuitos é popular em algoritmos quânticos variacionais porque pode produzir uma ampla gama de estados quânticos. Algoritmos variacionais ajustam os parâmetros dos gates para encontrar estados que possuem certas propriedades (como estados que representam uma boa solução para um problema de otimização). Para esse propósito, muitos circuitos na biblioteca são parametrizados, o que significa que você pode defini-los sem valores fixos.

O seguinte bloco de código importa um circuito n_local, no qual os gates de emaranhamento são gates de dois qubits. Esse circuito intercala blocos de gates de qubit único parametrizados, seguidos por blocos de emaranhamento de gates de dois qubits. O código a seguir cria um circuito de três qubits, com gates RX de qubit único e gates CZ de dois qubits.

from qiskit.circuit.library import n_local

two_local = n_local(3, "rx", "cz")
two_local.draw("mpl")

Output of the previous code cell

Você pode obter um objeto semelhante a uma lista dos parâmetros do circuito a partir do atributo parameters.

two_local.parameters
ParameterView([ParameterVectorElement(θ[0]), ParameterVectorElement(θ[1]), ParameterVectorElement(θ[2]), ParameterVectorElement(θ[3]), ParameterVectorElement(θ[4]), ParameterVectorElement(θ[5]), ParameterVectorElement(θ[6]), ParameterVectorElement(θ[7]), ParameterVectorElement(θ[8]), ParameterVectorElement(θ[9]), ParameterVectorElement(θ[10]), ParameterVectorElement(θ[11])])

Você também pode usar isso para atribuir esses parâmetros a valores reais usando um dicionário no formato { Parameter: number }. Para demonstrar, o seguinte bloco de código atribui cada parâmetro do circuito ao valor 0.

bound_circuit = two_local.assign_parameters(
{p: 0 for p in two_local.parameters}
)
bound_circuit.decompose().draw("mpl")

Output of the previous code cell

Para mais informações, consulte N-local gates na documentação da API da biblioteca de circuitos ou faça o curso de design de algoritmos variacionais no IBM Quantum Learning.

Circuitos de codificação de dados

Esses circuitos parametrizados codificam dados em estados quânticos para processamento por algoritmos de aprendizado de máquina quântico. Alguns circuitos suportados pelo Qiskit são:

  • Codificação por amplitude, que codifica cada número na amplitude de um estado de base. Isso pode armazenar 2n2^n números em um único estado, mas pode ser custoso de implementar.
  • Codificação por base, que codifica um inteiro kk preparando o estado de base correspondente k|k\rangle.
  • Codificação por ângulo, que define cada número nos dados como um ângulo de rotação em um circuito parametrizado.

A melhor abordagem depende das especificidades da sua aplicação. Nos computadores quânticos atuais, porém, frequentemente usamos circuitos de codificação por ângulo como o zz_feature_map.

from qiskit.circuit.library import zz_feature_map

features = [0.2, 0.4, 0.8]
feature_map = zz_feature_map(feature_dimension=len(features))

encoded = feature_map.assign_parameters(features)
encoded.draw("mpl")

Output of the previous code cell

Consulte Data encoding circuits na documentação da API da biblioteca de circuitos.

Circuitos de evolução temporal

Esses circuitos simulam um estado quântico evoluindo no tempo. Use circuitos de evolução temporal para investigar efeitos físicos como transferência de calor ou transições de fase em um sistema. Circuitos de evolução temporal também são um bloco de construção fundamental de funções de onda de química (como estados de teste de cluster acoplado unitário) e do algoritmo QAOA que usamos para problemas de otimização.

from qiskit.circuit.library import PauliEvolutionGate
from qiskit.circuit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp

# Prepare an initial state with a Hadamard on the middle qubit
state = QuantumCircuit(3)
state.h(1)

hamiltonian = SparsePauliOp(["ZZI", "IZZ"])
evolution = PauliEvolutionGate(hamiltonian, time=1)

# Evolve state by appending the evolution gate
state.compose(evolution, inplace=True)

state.draw("mpl")

Output of the previous code cell

Leia a documentação da API do PauliEvolutionGate.

Circuitos de benchmarking e teoria da complexidade

Circuitos de benchmarking nos dão uma noção de quão bem nosso hardware está realmente funcionando, e circuitos de teoria da complexidade nos ajudam a entender o quão difíceis são os problemas que queremos resolver.

Por exemplo, o benchmark de "volume quântico" mede com qual precisão um computador quântico executa um tipo de circuito quântico aleatório. A pontuação do computador quântico aumenta com o tamanho do circuito que ele consegue executar de forma confiável. Isso leva em conta todos os aspectos do computador, incluindo contagem de qubits, fidelidade de instruções, conectividade de qubits e a pilha de software que transpila e pós-processa os resultados. Leia mais sobre volume quântico no artigo original sobre volume quântico.

O código a seguir mostra um exemplo de um circuito de volume quântico construído no Qiskit que roda em quatro qubits (os blocos unitary são gates de dois qubits aleatorizados).

from qiskit.circuit.library import quantum_volume

quantum_volume(4).draw("mpl")

Output of the previous code cell

A biblioteca de circuitos também inclui circuitos considerados difíceis de simular classicamente, como os circuitos de polinômio quântico instantâneo (iqp). Esses circuitos intercalam certos gates diagonais (na base computacional) entre blocos de gates de Hadamard.

Outros circuitos incluem grover_operator para uso no algoritmo de Grover, e o circuito fourier_checking para o problema de verificação de Fourier. Veja esses circuitos em Particular quantum circuits na documentação da API da biblioteca de circuitos.

Circuitos aritméticos

Operações aritméticas são funções clássicas, como adição de inteiros e operações bit a bit. Estas podem ser úteis com algoritmos como estimativa de amplitude para aplicações financeiras, e em algoritmos como o algoritmo HHL, que resolve sistemas lineares de equações.

Como exemplo, vamos tentar somar dois números de três bits usando um circuito de "ripple-carry" para realizar adição in-place (FullAdderGate). Esse somador adiciona dois números (que chamaremos de "A" e "B") e escreve o resultado no registrador que continha B. No exemplo a seguir, A=2 e B=3.

from qiskit.circuit.library import FullAdderGate
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister

adder = FullAdderGate(3) # Adder of 3-bit numbers

# Create the number A=2
reg_a = QuantumRegister(3, "a")
number_a = QuantumCircuit(reg_a)
number_a.initialize(2) # Number 2; |010>

# Create the number B=3
reg_b = QuantumRegister(3, "b")
number_b = QuantumCircuit(reg_b)
number_b.initialize(3) # Number 3; |011>

# Create a circuit to hold everything, including a classical register for
# the result
qregs = [
QuantumRegister(1, "cin"),
QuantumRegister(3, "a"),
QuantumRegister(3, "b"),
QuantumRegister(1, "cout"),
]
reg_result = ClassicalRegister(3)
circuit = QuantumCircuit(*qregs, reg_result)

# Compose number initializers with the adder. Adder stores the result to
# register B, so we'll measure those qubits.
circuit = (
circuit.compose(number_a, qubits=reg_a)
.compose(number_b, qubits=reg_b)
.compose(adder)
)
circuit.measure(reg_b, reg_result)
circuit.draw("mpl")

Output of the previous code cell

A simulação do circuito mostra que ele produz 5 em todas as 1024 execuções (ou seja, é medido com probabilidade 1.0).

from qiskit.primitives import StatevectorSampler

result = StatevectorSampler().run([circuit]).result()

print(f"Count data:\n {result[0].data.c0.get_int_counts()}")
Count data:
{5: 1024}

Consulte Arithmetic na documentação da API da biblioteca de circuitos.

Próximos passos

Recomendações