Przejdź do głównej treści

OpenQASM 2 i Qiskit SDK

Wersje pakietów

Kod na tej stronie został opracowany przy użyciu poniższych wymagań. Zalecamy korzystanie z tych wersji lub nowszych.

qiskit[all]~=2.3.0
# Added by doQumentation — required packages for this notebook
!pip install -q qiskit

Qiskit SDK udostępnia narzędzia do konwersji między reprezentacjami OpenQASM programów kwantowych a klasą QuantumCircuit.

Importowanie programu OpenQASM 2 do Qiskit

Do importowania programów OpenQASM 2 do Qiskit służą dwie funkcje. Są to qasm2.load(), która przyjmuje nazwę pliku, oraz qasm2.loads(), która przyjmuje program OpenQASM 2 jako ciąg znaków.

import qiskit.qasm2

qiskit.qasm2.load(filename, include_path=('.',), include_input_directory='append', custom_instructions=(), custom_classical=(), strict=False)
qiskit.qasm2.loads(program, include_path=('.',), custom_instructions=(), custom_classical=(), strict=False)

Więcej informacji znajdziesz w OpenQASM 2 Qiskit API.

Importowanie prostych programów

W przypadku większości programów OpenQASM 2 możesz po prostu użyć qasm2.load i qasm2.loads z jednym argumentem.

Przykład: importowanie programu OpenQASM 2 jako ciąg znaków

Użyj qasm2.loads(), aby zaimportować program OpenQASM 2 jako ciąg znaków do Circuit:

import qiskit.qasm2

program = """
OPENQASM 2.0;
include "qelib1.inc";
qreg q[2];
creg c[2];

h q[0];
cx q[0], q[1];

measure q -> c;
"""
circuit = qiskit.qasm2.loads(program)
circuit.draw()
┌───┐     ┌─┐   
q_0: ┤ H ├──■──┤M├───
└───┘┌─┴─┐└╥┘┌─┐
q_1: ─────┤ X ├─╫─┤M├
└───┘ ║ └╥┘
c: 2/═══════════╩══╩═
0 1

Przykład: importowanie programu OpenQASM 2 z pliku

Użyj load(), aby zaimportować program OpenQASM 2 z pliku do Circuit:

import qiskit.qasm2
circuit = qiskit.qasm2.load("myfile.qasm")

Domyślnie importer OpenQASM 2 w Qiskit traktuje plik nagłówkowy "qelib1.inc" jako de facto bibliotekę standardową. Importer traktuje ten plik jako zawierający dokładnie te bramki, które zostały opisane w oryginalnym artykule definiującym OpenQASM 2. Qiskit użyje wbudowanych bramek z biblioteki Circuit do reprezentowania bramek zawartych w "qelib1.inc". Gate'y zdefiniowane w programie za pomocą ręcznych instrukcji gate OpenQASM 2 będą domyślnie konstruowane jako niestandardowe podklasy Gate Qiskit.

Możesz wskazać importerowi, jakich klas Gate ma używać dla napotkanych instrukcji gate. Możesz też użyć tego mechanizmu, aby traktować dodatkowe nazwy bramek jako „wbudowane", tzn. niewymagające jawnej definicji. Jeśli określisz, jakich klas Gate używać dla instrukcji gate spoza "qelib1.inc", wynikowy Circuit będzie zazwyczaj wydajniejszy w pracy.

ostrzeżenie

Od wersji Qiskit SDK v1.0 eksporter OpenQASM 2 w Qiskit (zob. Eksportowanie Circuit Qiskit do OpenQASM 2) nadal zachowuje się tak, jakby "qelib1.inc" zawierał więcej bramek niż w rzeczywistości. Oznacza to, że domyślne ustawienia importera mogą nie być w stanie zaimportować programu wyeksportowanego przez nasz eksporter. Zapoznaj się z konkretnym przykładem dotyczącym pracy z przestarzałym eksporterem, aby rozwiązać ten problem.

Ta rozbieżność to odziedziczone zachowanie Qiskit i zostanie rozwiązana w późniejszym wydaniu Qiskit.

Aby przekazać informacje o niestandardowej instrukcji do importera OpenQASM 2, użyj klasy qasm2.CustomInstruction. Wymaga ona czterech obowiązkowych informacji, w kolejności:

  • Nazwa bramki używana w programie OpenQASM 2
  • Liczba parametrów kątowych, jakie przyjmuje bramka
  • Liczba Qubitów, na których działa bramka
  • Klasa konstruktora lub funkcja Python dla bramki, przyjmująca parametry bramki (ale nie Qubity) jako osobne argumenty

Jeśli importer napotka definicję gate pasującą do danej niestandardowej instrukcji, użyje tych niestandardowych informacji do odtworzenia obiektu bramki. Jeśli napotka instrukcję gate pasującą pod względem name do niestandardowej instrukcji, ale niezgodną zarówno z liczbą parametrów, jak i liczbą Qubitów, importer zgłosi wyjątek QASM2ParseError, sygnalizując niezgodność między dostarczonymi informacjami a programem.

Ponadto piąty argument builtin można opcjonalnie ustawić na True, aby bramka była automatycznie dostępna w programie OpenQASM 2, nawet jeśli nie jest jawnie zdefiniowana. Jeśli importer napotka jawną definicję gate dla wbudowanej niestandardowej instrukcji, zaakceptuje ją po cichu. Podobnie jak poprzednio, jeśli jawna definicja o tej samej nazwie nie jest zgodna z dostarczoną niestandardową instrukcją, zostanie zgłoszony wyjątek QASM2ParseError. Jest to przydatne dla zachowania zgodności ze starszymi eksporterami OpenQASM 2 oraz z innymi platformami kwantowymi, które traktują „bramki bazowe" swojego sprzętu jako instrukcje wbudowane.

Qiskit udostępnia atrybut danych do pracy z programami OpenQASM 2 wygenerowanymi przez starsze wersje możliwości eksportowania OpenQASM 2 Qiskit. Jest to qasm2.LEGACY_CUSTOM_INSTRUCTIONS, który można podać jako argument custom_instructions do qasm2.load() i qasm2.loads().

Przykład: importowanie programu utworzonego przez przestarzały eksporter Qiskit

Ten program OpenQASM 2 używa bramek, które nie znajdują się w oryginalnej wersji "qelib1.inc", bez ich deklarowania, ale są standardowymi bramkami w bibliotece Qiskit. Możesz użyć qasm2.LEGACY_CUSTOM_INSTRUCTIONS, aby łatwo wskazać importerowi zestaw bramek, których wcześniej używał eksporter OpenQASM 2 Qiskit.

from qiskit import qasm2

program = """
OPENQASM 2.0;
include "qelib1.inc";

qreg q[4];
creg c[4];

h q[0];
cx q[0], q[1];

// 'rxx' is not actually in `qelib1.inc`,
// but Qiskit used to behave as if it were.
rxx(0.75) q[2], q[3];

measure q -> c;
"""
circuit = qasm2.loads(
program,
custom_instructions=qasm2.LEGACY_CUSTOM_INSTRUCTIONS,
)

Przykład: użycie konkretnej klasy Gate podczas importowania programu OpenQASM 2

Qiskit nie może w ogólności zweryfikować, czy definicja w instrukcji gate OpenQASM 2 dokładnie odpowiada bramce ze standardowej biblioteki Qiskit. Zamiast tego Qiskit wybiera niestandardową bramkę na podstawie podanej definicji. Może to być mniej wydajne niż korzystanie z jednej z wbudowanych standardowych bramek lub niestandardowej bramki zdefiniowanej przez użytkownika. Możesz ręcznie przypisać konkretne klasy do instrukcji gate.

from qiskit import qasm2
from qiskit.circuit import Gate
from qiskit.circuit.library import RZXGate

# Define a custom gate that takes one qubit and two angles.
class MyGate(Gate):
def __init__(self, theta, phi):
super().__init__("my", 1, [theta, phi])

custom_instructions = [
# Link the OpenQASM 2 name 'my' with our custom gate.
qasm2.CustomInstruction("my", 2, 1, MyGate),
# Link the OpenQASM 2 name 'rzx' with Qiskit's
# built-in RZXGate.
qasm2.CustomInstruction("rzx", 1, 2, RZXGate),
]

program = """
OPENQASM 2.0;

gate my(theta, phi) q {
U(theta / 2, phi, -theta / 2) q;
}
gate rzx(theta) a, b {
// It doesn't matter what definition is
// supplied, if the parameters match;
// Qiskit will still use `RZXGate`.
}

qreg q[2];
my(0.25, 0.125) q[0];
rzx(pi) q[0], q[1];
"""

circuit = qasm2.loads(
program,
custom_instructions=custom_instructions,
)

Przykład: definiowanie nowej wbudowanej bramki w programie OpenQASM 2

Jeśli argument builtin=True jest ustawiony, niestandardowa bramka nie musi mieć powiązanej definicji.

from qiskit import qasm2
from qiskit.circuit import Gate

# Define a custom gate that takes one qubit and two angles.
class MyGate(Gate):
def __init__(self, theta, phi):
super().__init__("my", 1, [theta, phi])

custom_instructions = [
qasm2.CustomInstruction("my", 2, 1, MyGate, builtin=True),
]

program = """
OPENQASM 2.0;
qreg q[1];

my(0.25, 0.125) q[0];
"""

circuit = qasm2.loads(
program,
custom_instructions=custom_instructions,
)

Definiowanie niestandardowych funkcji klasycznych

OpenQASM 2 zawiera pewne wbudowane funkcje klasyczne do użycia w argumentach bramek. Możesz rozszerzyć język o dodatkowe funkcje, używając argumentu custom_classical w qasm2.load() i qasm2.loads(), wraz z klasą qasm2.CustomClassical.

Aby zdefiniować niestandardową funkcję klasyczną, musisz podać:

  • Nazwę funkcji taką, jaka pojawia się w programie OpenQASM 2
  • Liczbę argumentów zmiennoprzecinkowych, jaką przyjmuje
  • Wywoływalny obiekt Python, który oblicza tę funkcję

Wszystkie zdefiniowane niestandardowe funkcje klasyczne są traktowane przez importer jako wbudowane w język OpenQASM 2. W języku OpenQASM 2 nie ma oficjalnego sposobu definiowania nowych funkcji; jest to rozszerzenie Qiskit.

Przykład: użycie niestandardowych instrukcji klasycznych

Poniżej podajemy dwie niestandardowe funkcje klasyczne. Pierwsza jest prosta i po prostu dodaje jeden do swojego wejścia. Druga to funkcja math.atan2, która reprezentuje operację matematyczną arctan(y/x)\arctan(y/x) z uwzględnieniem ćwiartki układu współrzędnych.

import math
from qiskit import qasm2

program = """
include "qelib1.inc";
qreg q[2];
rx(arctan(pi, 3 + add_one(0.2))) q[0];
cx q[0], q[1];
"""

def add_one(x):
return x + 1

customs = [
# Our `add_one` takes only one parameter.
qasm2.CustomClassical("add_one", 1, add_one),
# `arctan` takes two parameters, and `math.atan2` implements it.
qasm2.CustomClassical("arctan", 2, math.atan2),
]
circuit = qasm2.loads(program, custom_classical=customs)

Tryb ścisły

Domyślnie ten parser jest bardziej elastyczny niż oficjalna specyfikacja. Dopuszcza końcowe przecinki w listach parametrów, niepotrzebne (puste) średniki, pominięcie instrukcji wersji OPENQASM 2.0; oraz kilka innych udogodnień bez zgłaszania błędów. Możesz jednak włączyć tryb „zgodny z literą specyfikacji" za pomocą strict=True.

Eksportowanie Circuit Qiskit do OpenQASM 2

Qiskit może również wyeksportować QuantumCircuit do OpenQASM 2. Do zapisu do pliku służy funkcja qasm2.dump(), a do zapisu do ciągu znaków — qasm2.dumps(). Funkcje te mają obecnie bardzo prosty interfejs: przyjmują Circuit i, wyłącznie w przypadku qasm2.dump(), lokalizację, do której ma zostać zapisane wyjście.

ostrzeżenie

Eksporter OpenQASM 2 w Qiskit nadal zakłada przestarzałą, niestandardową wersję pliku nagłówkowego "qelib1.inc". Zostanie to rozwiązane w późniejszym wydaniu Qiskit, ale w międzyczasie, jeśli chcesz ponownie zaimportować program OpenQASM 2 utworzony w Qiskit, skorzystaj z powyższego przykładu pokazującego, jak poinformować importer o przestarzałych bramkach.

Przykład: eksportowanie Circuit do OpenQASM 2

from qiskit import QuantumCircuit, qasm2

# Define any circuit.
circuit = QuantumCircuit(2, 2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure([0, 1], [0, 1])

# Export to a string.
program = qasm2.dumps(circuit)

# Export to a file.
qasm2.dump(circuit, "my_file.qasm")

Następne kroki

Rekomendacje