Основы Cirq
Стереотипные программисты обычно не любят мышь, поэтому и для программирования квантовых компьютеров есть не только drag-n-drop интерфейс построения схем, но и специализированные языки программирования (Quipper, Silq, Q# и т.д.), и библиотеки для языков программирования общего назначения (Qiskit, PennyLane, Strawberry Fields).
В нашем курсе мы будем пользоваться библиотекой Cirq от Google для языка программирования Python.
Установка и запуск
Библиотека требует Python версии 3.7 и выше. Установите его для своей ОС: Linux, Mac OS X, Windows.
Желательно использовать виртуальное окружение, чтобы не засорять глобальный набор пакетов.
Установите cirq при помощи pip:
python -m pip install cirq
Проверить, что всё работает, можно при помощи следующей команды:
python -c 'import cirq_google; print(cirq_google.Sycamore)'
Первая программа
Для описания схем нужны кубиты и гейты, которые выполняют над кубитами операции.
import cirq # Создаём кубит с именем q qubit = cirq.NamedQubit('q') # Схема применяет гейт Адамара и измеряет результат в m circuit = cirq.Circuit(cirq.H(qubit), cirq.measure(qubit, key='m')) print("Circuit:") print(circuit) # Эмулируем работу схемы несколько раз simulator = cirq.Simulator() result = simulator.run(circuit, repetitions=20) print("Results:") print(result)
Запуск и моделирование
Библиотека «заточена» под работу на реальных квантовых устройствах, поэтому
результаты запуска будут возвращать те значения, которые выдал бы идеальный
квантовый компьютер (работающий без шумов и ошибок). Функции, в названии которых
есть run
, обычно имеют именно такое поведение. В этом случае легко тестировать
программы, используя классический компьютер, а затем запуская для работы уже на
квантовом компьютере (доступном, например, в облаке).
Также доступна и моделирование работы компьютера, которое вычисляет вектор
состояния. В названии функций для моделирования обычно есть слово simulate
.
Запуск схемы вы уже видели в прошлом разделе, поэтому посмотрим на код для моделирования создания состояния Белла \(1/\sqrt{2} * (|00\rangle + |11\rangle)\):
import cirq bell_circuit = cirq.Circuit() q0, q1 = cirq.LineQubit.range(2) bell_circuit.append(cirq.H(q0)) bell_circuit.append(cirq.CNOT(q0, q1)) print('Circuit:') print(bell_circuit) # Initialize Simulator s = cirq.Simulator() print('Simulate the circuit:') results = s.simulate(bell_circuit) print(results)
Кубиты и гейты, устройства и моменты
Кубиты
# Для отдельных кубитов можно задать имена. Это полезно, если ваш алгоритм # абстрактный или не оптимизирован под конкретную реализацию квантового # компьютера (где могут быть ограничения на кубиты, к которым применяются # операции) q0 = cirq.NamedQubit('source') q1 = cirq.NamedQubit('target') print(q0,q1) # Можно создать кубиты в цепочке, задав для каждого номер или интервал q3 = cirq.LineQubit(3) # здесь создаются кубиты LineQubit(0), LineQubit(1), LineQubit(2) q0, q1, q2 = cirq.LineQubit.range(3) # Можно создать кубиты в сетке, по отдельности q4_5 = cirq.GridQubit(4, 5) # или все сразу. Код создаёт 16 кубитов от (0,0) до (3,3) qubits = cirq.GridQubit.square(4)
Устройства
В библиотеке есть определения имеющихся квантовых устройств, например, компьютера Sycamore от Google. Линии на схеме задают пары кубитов, между которыми возможны двухкубитовые операции.
import cirq_google print(cirq_google.Sycamore)
Гейты
Для большинства «стандартных» гейтов в библиотеке есть соответствующие объекты,
например, cirq.H
для гейта Адамара. Гейт, применённый к каким-либо
кубитам, в cirq называется операцией (например, cirq.H(q0)
— это
гейт Адамара, применённый к кубиту q0
).
Схемы задаются при помощи класса Circuit
, к которому можно добавлять гейты,
используя метод append
:
circuit = cirq.Circuit() qubits = cirq.LineQubit.range(3) circuit.append(cirq.H(qubits[0])) circuit.append(cirq.H(qubits[1])) circuit.append(cirq.H(qubits[2])) print(circuit)
В append
можно передавать операции по отдельности или итерируемые объекты с
операциями:
circuit2 = cirq.Circuit() ops = [cirq.H(q) for q in cirq.LineQubit.range(3)] circuit2.append(ops) print(circuit2)
Моменты
Схемы состоят из моментов Moment
— наборов операций, которые можно выполнять
параллельно. Обычно cirq пытается использовать самый ранний момент для
применения операции.
При этом если кубит уже использовался в более ранней операции, то в схеме создаётся новый момент.
print(cirq.Circuit(cirq.SWAP(q, q + 1) for q in cirq.LineQubit.range(3)))