Konstruowanie Circuit
Wersje pakietów
Kod na tej stronie został opracowany z użyciem poniższych wymagań. Zalecamy korzystanie z tych wersji lub nowszych.
qiskit[all]~=2.3.0
Ta strona dokładniej omawia klasę QuantumCircuit w SDK Qiskit, w tym kilka bardziej zaawansowanych metod, których możesz użyć do tworzenia kwantowych Circuit.
Czym jest kwantowy Circuit?
Prosty kwantowy Circuit to zbiór Qubitów i lista instrukcji działających na tych Qubitach. Aby to zobrazować, poniższa komórka tworzy nowy Circuit z dwoma nowymi Qubitami, a następnie wyświetla atrybut qubits tego Circuit, który jest listą obiektów Qubit w kolejności od najmniej znaczącego bitu do najbardziej znaczącego bitu .
# Added by doQumentation — required packages for this notebook
!pip install -q qiskit
from qiskit import QuantumCircuit
qc = QuantumCircuit(2)
qc.qubits
[<Qubit register=(2, "q"), index=0>, <Qubit register=(2, "q"), index=1>]
Wiele obiektów QuantumRegister i ClassicalRegister można łączyć, aby tworzyć Circuit. Każdy obiekt QuantumRegister i ClassicalRegister może również mieć nazwę.
from qiskit.circuit import QuantumRegister, ClassicalRegister
qr1 = QuantumRegister(2, "qreg1") # Create a QuantumRegister with 2 qubits
qr2 = QuantumRegister(1, "qreg2") # Create a QuantumRegister with 1 qubit
cr1 = ClassicalRegister(3, "creg1") # Create a ClassicalRegister with 3 cbits
combined_circ = QuantumCircuit(
qr1, qr2, cr1
) # Create a quantum circuit with 2 QuantumRegisters and 1 ClassicalRegister
combined_circ.qubits
[<Qubit register=(2, "qreg1"), index=0>,
<Qubit register=(2, "qreg1"), index=1>,
<Qubit register=(1, "qreg2"), index=0>]
Indeks i rejestr Qubita możesz znaleźć, korzystając z metody find_bit Circuit i jej atrybutów.
desired_qubit = qr2[0] # Qubit 0 of register 'qreg2'
print("Index:", combined_circ.find_bit(desired_qubit).index)
print("Register:", combined_circ.find_bit(desired_qubit).registers)
Index: 2
Register: [(QuantumRegister(1, 'qreg2'), 0)]
Dodanie instrukcji do Circuit dołącza ją do atrybutu data tego Circuit. Poniższe dane wyjściowe komórki pokazują, że data jest listą obiektów CircuitInstruction, z których każdy ma atrybut operation oraz atrybut qubits.
qc.x(0) # Add X-gate to qubit 0
qc.data
[CircuitInstruction(operation=Instruction(name='x', num_qubits=1, num_clbits=0, params=[]), qubits=(<Qubit register=(2, "q"), index=0>,), clbits=())]
Najprostszym sposobem wyświetlenia tych informacji jest metoda draw, która zwraca wizualizację Circuit. Zobacz stronę Wizualizacja Circuit, aby poznać różne sposoby wyświetlania kwantowych Circuit.
qc.draw("mpl")
Obiekty instrukcji Circuit mogą zawierać „definicyjne" Circuit opisujące instrukcję za pomocą bardziej podstawowych instrukcji. Na przykład Gate X jest zdefiniowany jako szczególny przypadek Gate U3, będącego bardziej ogólnym Gate dla jednego Qubita.
# Draw definition circuit of 0th instruction in `qc`
qc.data[0].operation.definition.draw("mpl")
Instrukcje i Circuit są podobne w tym sensie, że oba opisują operacje na bitach i Qubitach, ale służą różnym celom:
- Instrukcje są traktowane jako stałe, a ich metody zazwyczaj zwracają nowe instrukcje (bez modyfikowania oryginalnego obiektu).
- Circuit są zaprojektowane tak, aby budować je w wielu liniach kodu, a metody
QuantumCircuitczęsto modyfikują istniejący obiekt.
Czym jest głębokość Circuit?
Głębokość (depth()) kwantowego Circuit to miara liczby „warstw" Gate kwantowych wykonywanych równolegle, potrzebnych do ukończenia obliczeń zdefiniowanych przez ten Circuit. Ponieważ implementacja Gate kwantowych zajmuje czas, głębokość Circuit w przybliżeniu odpowiada ilości czasu potrzebnej komputerowi kwantowemu na wykonanie tego Circuit. Dlatego głębokość Circuit jest jedną z ważnych wielkości używanych do oceny, czy dany Circuit może być uruchomiony na urządzeniu.
Pozostała część tej strony ilustruje, jak manipulować kwantowymi Circuit.
Budowanie Circuit
Metody takie jak QuantumCircuit.h i QuantumCircuit.cx dodają konkretne instrukcje do Circuit. Aby bardziej ogólnie dodawać instrukcje do Circuit, użyj metody append. Przyjmuje ona instrukcję i listę Qubitów, do których ma być zastosowana. Zobacz dokumentację API biblioteki Circuit, aby zapoznać się z listą obsługiwanych instrukcji.
from qiskit.circuit.library import HGate
qc = QuantumCircuit(1)
qc.append(
HGate(), # New HGate instruction
[0], # Apply to qubit 0
)
qc.draw("mpl")
Aby połączyć dwa Circuit, użyj metody compose. Przyjmuje ona inny obiekt QuantumCircuit oraz opcjonalną listę mapowań Qubitów.
qc_a = QuantumCircuit(4)
qc_a.x(0)
qc_b = QuantumCircuit(2, name="qc_b")
qc_b.y(0)
qc_b.z(1)
# compose qubits (0, 1) of qc_a to qubits (1, 3) of qc_b respectively
combined = qc_a.compose(qc_b, qubits=[1, 3])
combined.draw("mpl")
Możesz też chcieć skompilować Circuit do instrukcji, aby utrzymać porządek w swoich Circuit. Circuit możesz przekonwertować na instrukcję za pomocą metody to_instruction, a następnie dołączyć ją do innego Circuit tak jak każdą inną instrukcję. Circuit narysowany w poniższej komórce jest funkcjonalnie równoważny Circuit narysowanemu w poprzedniej komórce.
inst = qc_b.to_instruction()
qc_a.append(inst, [1, 3])
qc_a.draw("mpl")
Jeśli twój Circuit jest unitarny, możesz przekonwertować go na obiekt Gate za pomocą metody to_gate. Obiekty Gate to szczególne typy instrukcji, które mają pewne dodatkowe funkcje, takie jak metoda control, która dodaje kwantowe sterowanie.
gate = qc_b.to_gate().control()
qc_a.append(gate, [0, 1, 3])
qc_a.draw("mpl")
Aby zobaczyć, co się dzieje, możesz użyć metody decompose, która rozbudowuje każdą instrukcję do jej definicji.
Metoda decompose zwraca nowy Circuit i nie modyfikuje Circuit, na którym działa.
qc_a.decompose().draw("mpl")
Pomiar Qubitów
Pomiary służą do próbkowania stanów poszczególnych Qubitów i przesyłania wyników do rejestru klasycznego. Pamiętaj, że jeśli przesyłasz Circuit do prymitywu Sampler, pomiary są wymagane. Natomiast Circuit przesyłane do prymitywu Estimator nie mogą zawierać pomiarów.
Qubity można mierzyć trzema metodami: measure, measure_all i measure_active. Aby dowiedzieć się, jak wizualizować wyniki pomiarów, zobacz stronę Wizualizacja wyników.
-
QuantumCircuit.measure: mierzy każdy Qubit podany w pierwszym argumencie na klasyczny bit wskazany jako drugi argument. Ta metoda pozwala na pełną kontrolę nad tym, gdzie jest przechowywany wynik pomiaru. -
QuantumCircuit.measure_all: nie przyjmuje żadnego argumentu i może być używana dla kwantowych Circuit bez wcześniej zdefiniowanych bitów klasycznych. Tworzy klasyczne przewody i przechowuje wyniki pomiarów w kolejności. Na przykład pomiar Qubita jest przechowywany w cbicie ). Dodaje również barierę przed pomiarem. -
QuantumCircuit.measure_active: podobna domeasure_all, ale mierzy tylko Qubity, które mają operacje.
qc1 = QuantumCircuit(2, 2)
qc1.measure(0, 1)
qc1.draw("mpl", cregbundle=False)
qc2 = QuantumCircuit(2)
qc2.measure_all()
qc2.draw("mpl", cregbundle=False)
qc3 = QuantumCircuit(2)
qc3.x(1)
qc3.measure_active()
qc3.draw("mpl", cregbundle=False)
Parametryzowane Circuit
Wiele kwantowych algorytmów krótkoterminowych polega na wykonywaniu wielu wariantów kwantowego Circuit. Ponieważ konstruowanie i optymalizowanie dużych Circuit może być kosztowne obliczeniowo, Qiskit obsługuje Circuit parametryzowane. Takie Circuit mają niezdefiniowane parametry, których wartości nie trzeba podawać aż do tuż przed wykonaniem Circuit. Dzięki temu można przenieść konstruowanie i optymalizowanie Circuit poza główną pętlę programu. Poniższa komórka tworzy i wyświetla parametryzowany Circuit.
from qiskit.transpiler import generate_preset_pass_manager
from qiskit.circuit import Parameter
angle = Parameter("angle") # undefined number
# Create and optimize circuit once
qc = QuantumCircuit(1)
qc.rx(angle, 0)
qc = generate_preset_pass_manager(
optimization_level=3, basis_gates=["u", "cx"]
).run(qc)
qc.draw("mpl")
Poniższa komórka tworzy wiele wariantów tego Circuit i wyświetla jeden z nich.
circuits = []
for value in range(100):
circuits.append(qc.assign_parameters({angle: value}))
circuits[0].draw("mpl")
Listę niezdefiniowanych parametrów Circuit znajdziesz w jego atrybucie parameters.
qc.parameters
ParameterView([Parameter(angle)])
Zmiana nazwy parametru
Domyślnie nazwy parametrów parametryzowanego Circuit mają przedrostek x — na przykład x[0]. Możesz zmieniać nazwy po ich zdefiniowaniu, jak pokazano w poniższym przykładzie.
from qiskit.circuit.library import z_feature_map
from qiskit.circuit import ParameterVector
# Define a parameterized circuit with default names
# For example, x[0]
circuit = z_feature_map(2)
# Set new parameter names
# They will now be prefixed by `hi` instead
# For example, hi[0]
training_params = ParameterVector("hi", 2)
# Assign parameter names to the quantum circuit
circuit = circuit.assign_parameters(parameters=training_params)
Następne kroki
- Aby dowiedzieć się więcej o kwantowych algorytmach krótkoterminowych, weź udział w kursie Projektowanie algorytmów wariacyjnych.
- Zobacz przykład użycia Circuit w samouczku Algorytm Grovera.
- Pracuj z prostymi Circuit przy użyciu IBM Quantum Composer.