Corte de circuitos para condições de contorno periódicas
Estimativa de uso: Dois minutos em um processador Eagle (NOTA: Isso é apenas uma estimativa. Seu tempo de execução pode variar.)
Contexto
Neste notebook, consideramos a simulação de uma cadeia periódica de qubits onde há uma operação de dois qubits entre cada dois qubits adjacentes, incluindo o primeiro e o último. Cadeias periódicas são frequentemente encontradas em problemas de física e química, como modelos de Ising e simulação molecular.
Os dispositivos IBM Quantum® atuais são planares. É possível incorporar algumas cadeias periódicas diretamente na topologia onde o primeiro e o último qubits são vizinhos. No entanto, para problemas grandes o suficiente, o primeiro e o último qubits podem estar distantes, exigindo assim muitos gates SWAP para a operação de 2 qubits entre esses dois qubits. Tal problema de contorno periódico foi estudado em este artigo.
Neste notebook, mostramos o uso de corte de circuitos para lidar com tal problema de cadeia periódica em escala útil onde o primeiro e o último qubits não são vizinhos. Cortar essa conectividade de longo alcance evita os gates SWAP extras ao custo de executar múltiplas instâncias do circuito e algum pós-processamento clássico. Em resumo, o corte pode ser incorporado para calcular logicamente as operações de 2 qubits de longa distância. Em outras palavras, essa abordagem leva a um aumento efetivo na conectividade do mapa de acoplamento, levando assim a um número menor de gates SWAP.
Observe que existem dois tipos de cortes - cortar o fio de um circuito (chamado de wire cutting), ou substituir um gate de 2 qubits por múltiplas operações de qubit único (chamado de gate cutting). Neste notebook, vamos nos concentrar no gate cutting. Para mais detalhes sobre gate cutting, consulte os materiais explicativos no qiskit-addon-cutting, e as referências correspondentes. Para mais detalhes sobre wire cutting, consulte o tutorial Wire cutting for expectation values estimation, ou os tutoriais em qiskit-addon-cutting.
Requisitos
Antes de iniciar este tutorial, certifique-se de ter o seguinte instalado:
- Qiskit SDK v1.2 ou posterior (
pip install qiskit) - Qiskit Runtime v0.3 ou posterior (
pip install qiskit-ibm-runtime) - Circuit cutting Qiskit addon v.9.0 ou posterior (
pip install qiskit-addon-cutting)
Configuração
# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib numpy qiskit qiskit-addon-cutting qiskit-ibm-runtime
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
from qiskit.transpiler import PassManager
from qiskit.transpiler.passes import (
BasisTranslator,
Optimize1qGatesDecomposition,
)
from qiskit.circuit.equivalence_library import (
SessionEquivalenceLibrary as sel,
)
from qiskit.converters import circuit_to_dag, dag_to_circuit
from qiskit.result import sampled_expectation_value
from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit.circuit.library import TwoLocal
from qiskit_addon_cutting import (
cut_gates,
generate_cutting_experiments,
reconstruct_expectation_values,
)
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime import SamplerV2, SamplerOptions, Batch
Passo 1: Mapear entradas clássicas para um problema quântico
Aqui, vamos gerar um circuito TwoLocal e definir alguns observáveis.
- Entrada: Parâmetros para criar um circuito
- Saída: Circuito abstrato e observáveis
Consideramos um entangler map eficiente em hardware para o circuito TwoLocal com conectividade periódica entre o último e o primeiro qubits do entangler map. Esta interação de longo alcance pode levar a gates SWAP extras durante a transpilação, aumentando assim a profundidade do circuito.
Selecionar backend e layout inicial
service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, min_num_qubits=127
)
Para este notebook, vamos considerar uma cadeia 1D periódica de 109 qubits, que é a cadeia 1D mais longa na topologia de um dispositivo IBM Quantum de 127 qubits. Não é possível arranjar uma cadeia periódica de 109 qubits em um dispositivo de 127 qubits de modo que o primeiro e o último qubits sejam vizinhos sem incorporar gates SWAP extras.
init_layout = [
13,
12,
11,
10,
9,
8,
7,
6,
5,
4,
3,
2,
1,
0,
14,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
36,
51,
50,
49,
48,
47,
46,
45,
44,
43,
42,
41,
40,
39,
38,
37,
52,
56,
57,
58,
59,
60,
61,
62,
63,
64,
65,
66,
67,
68,
69,
70,
74,
89,
88,
87,
86,
85,
84,
83,
82,
81,
80,
79,
78,
77,
76,
75,
90,
94,
95,
96,
97,
98,
99,
100,
101,
102,
103,
104,
105,
106,
107,
108,
112,
126,
125,
124,
123,
122,
121,
120,
119,
118,
117,
116,
115,
114,
113,
]
# the number of qubits in the circuit is governed by the length of the initial layout
num_qubits = len(init_layout)
num_qubits
109
Construir o entangler map para o circuito TwoLocal
coupling_map = [(i, i + 1) for i in range(0, len(init_layout) - 1)]
coupling_map.append(
(len(init_layout) - 1, 0)
) # adding in the periodic connectivity
O circuito TwoLocal permite a repetição dos rotation_blocks e do entangler map múltiplas vezes. Para este caso, o número de repetições determina o número de gates periódicos que precisam ser cortados. Como o overhead de amostragem aumenta exponencialmente com o número de cortes (consulte o tutorial Wire cutting for expectation values estimation para mais detalhes), vamos fixar o número de repetições em 2 neste notebook.
num_reps = 2
entangler_map = []
for even_edge in coupling_map[0 : len(coupling_map) : 2]:
entangler_map.append(even_edge)
for odd_edge in coupling_map[1 : len(coupling_map) : 2]:
entangler_map.append(odd_edge)
ansatz = TwoLocal(
num_qubits=num_qubits,
rotation_blocks="rx",
entanglement_blocks="cx",
entanglement=entangler_map,
reps=num_reps,
).decompose()
ansatz.draw("mpl", fold=-1)

Para verificar a qualidade do resultado usando corte de circuito, precisamos conhecer o resultado ideal. O circuito atual escolhido está além da simulação clássica de força bruta. Portanto, fixamos os parâmetros do circuito cuidadosamente para torná-lo clifford.
Vamos atribuir o valor de parâmetro para as primeiras duas camadas de gates Rx, e o valor para a última camada. Isso garante que o resultado ideal deste circuito seja , sendo o número de qubits. Portanto, os valores esperados de e , onde é o índice do qubit, são e respectivamente.
params_last_layer = [np.pi] * ansatz.num_qubits
params = [0] * (ansatz.num_parameters - ansatz.num_qubits)
params.extend(params_last_layer)
ansatz.assign_parameters(params, inplace=True)
Selecionar observáveis
Para quantificar os benefícios do gate cutting, medimos os valores esperados dos observáveis e