Розрізання дроту у вигляді двокубітної інструкції `Move`
У цьому посібнику ми відновимо математичні сподівання семикубітної схеми, розбивши її на дві чотирикубітні схеми за допомогою розрізання дротів.
Ось кроки, які ми виконаємо в цьому шаблоні Qiskit:
- Крок 1: Відображення задачі на квантові схеми та оператори:
- Відобразити гамільтоніан на квантову схему.
- Крок 2: Оптимізація для цільового апаратного забезпечення [Використовує аддон cutting]:
- Розрізати схему та спостережувани й оператор.
- Транспілювати підексперименти для апаратного забезпечення.
- Крок 3: Виконання на цільовому апаратному забезпеченні:
- Запустити підексперименти, отримані на кроці 2, використовуючи примітив
Sampler.
- Запустити підексперименти, отримані на кроці 2, використовуючи примітив
- Крок 4: Постобробка результатів [Використовує аддон cutting]:
- Об'єднати результати кроку 3 для відновлення математичного сподівання відповідного спостережуваного оператора.
Крок 1: Відображення
Створення схеми для розрізання
Спочатку ми починаємо зі схеми, натхненної рис. 1(a) зі статті arXiv:2302.03366v1.
# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-addon-cutting qiskit-aer qiskit-ibm-runtime
import numpy as np
from qiskit import QuantumCircuit
qc_0 = QuantumCircuit(7)
for i in range(7):
qc_0.rx(np.pi / 4, i)
qc_0.cx(0, 3)
qc_0.cx(1, 3)
qc_0.cx(2, 3)
qc_0.cx(3, 4)
qc_0.cx(3, 5)
qc_0.cx(3, 6)
qc_0.cx(0, 3)
qc_0.cx(1, 3)
qc_0.cx(2, 3)
<qiskit.circuit.instructionset.InstructionSet at 0x7f16ab191a80>
qc_0.draw("mpl")

Задання спостережуваного оператора
from qiskit.quantum_info import SparsePauliOp
observable = SparsePauliOp(["ZIIIIII", "IIIZIII", "IIIIIIZ"])
Крок 2: Оптимізація
Створення нової схеми, де інструкції Move розміщені в бажаних місцях розрізання
З огляду на наведену вище схему, ми хочемо зробити два розрізи дроту на лінії середнього кубіта, щоб схема могла розділитися на дві схеми по чотири кубіти кожна. Один зі способів зробити це — вручну розмістити двокубітні інструкції Move, які переносять стан з одного кубітного дроту на інший. Інструкція Move концептуально еквівалентна операції скидання на другому кубіті, за якою слідує вентиль SWAP. Ефект цієї інструкції полягає в перенесенні стану першого (джерельного) кубіта на другий (цільовий) кубіт із відкиданням вхідного стану другого кубіта. Для правильної роботи важливо, щоб другий (цільовий) кубіт не мав заплутаності з рештою системи; інакше операція скидання призведе до часткового колапсу стану решти системи.
Тут ми будуємо нову схему з одним додатковим кубітом і операціями Move на своїх місцях. У цьому прикладі ми маємо можливість повторно використати кубіт: джерельний кубіт першої операції Move стає цільовим кубітом другої операції Move.
Примітка: Як альтернативу прямій роботі з інструкціями Move, можна обрати позначення розрізів дроту за допомогою однокубітної інструкції CutWire. Функція cut_wires існує для перетворення CutWire на інструкції Move на щойно виділених кубітах. Однак, на відміну від ручного методу, цей автоматичний метод не дозволяє повторно використовувати кубітні дроти. Дивись посібник щодо CutWire для отримання детальної інформації.
from qiskit_addon_cutting.instructions import Move
qc_1 = QuantumCircuit(8)
for i in [*range(4), *range(5, 8)]:
qc_1.rx(np.pi / 4, i)
qc_1.cx(0, 3)
qc_1.cx(1, 3)
qc_1.cx(2, 3)
qc_1.append(Move(), [3, 4])
qc_1.cx(4, 5)
qc_1.cx(4, 6)
qc_1.cx(4, 7)
qc_1.append(Move(), [4, 3])
qc_1.cx(0, 3)
qc_1.cx(1, 3)
qc_1.cx(2, 3)
qc_1.draw("mpl")

Створення спостережуваного оператора для нової схеми
Цей спостережуваний оператор відповідає observable, але ми маємо коректно врахувати додатковий кубітний дріт, що був доданий (тобто вставляємо "I" за індексом 4). Зауваж, що в Qiskit рядкове представлення кубіта-0 відповідає крайньому правому символу Паулі.
observable_expanded = SparsePauliOp(["ZIIIIIII", "IIIIZIII", "IIIIIIIZ"])