Clasa Operator
Versiuni de pachete
Codul de pe această pagină a fost dezvoltat folosind cerințele de mai jos. Recomandăm utilizarea acestor versiuni sau a unora mai noi.
qiskit[all]~=2.3.0
Această pagină arată cum să folosești clasa Operator. Pentru o prezentare generală a reprezentărilor de operatori în Qiskit, inclusiv clasa Operator și altele, consultă Prezentare generală a claselor de operatori.
# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit
import numpy as np
from qiskit.circuit import QuantumCircuit
from qiskit.circuit.library import CXGate, RXGate, XGate
from qiskit.quantum_info import Operator, Pauli, process_fidelity
Conversia claselor în Operatori
Mai multe alte clase din Qiskit pot fi convertite direct într-un obiect Operator folosind metoda de inițializare a operatorului. De exemplu:
- Obiecte
Pauli - Obiecte
GateșiInstruction - Obiecte
QuantumCircuit
Reține că ultimul punct înseamnă că poți folosi clasa Operator ca simulator unitar pentru a calcula matricea unitară finală a unui Circuit cuantic, fără a fi nevoie să apelezi un Backend simulator. Dacă Circuit-ul conține operații nesuportate, se ridică o excepție. Operațiile nesuportate sunt: measure, reset, operații condiționale sau un Gate care nu are o definiție de matrice sau o descompunere în Gate-uri cu definiții de matrice.
# Create an Operator from a Pauli object
pauliXX = Pauli("XX")
Operator(pauliXX)
Operator([[0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j],
[0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j],
[0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j],
[1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j]],
input_dims=(2, 2), output_dims=(2, 2))
# Create an Operator for a Gate object
Operator(CXGate())
Operator([[1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
[0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j],
[0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j],
[0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j]],
input_dims=(2, 2), output_dims=(2, 2))
# Create an operator from a parameterized Gate object
Operator(RXGate(np.pi / 2))
Operator([[0.70710678+0.j , 0. -0.70710678j],
[0. -0.70710678j, 0.70710678+0.j ]],
input_dims=(2,), output_dims=(2,))
# Create an operator from a QuantumCircuit object
circ = QuantumCircuit(10)
circ.h(0)
for j in range(1, 10):
circ.cx(j - 1, j)
# Convert circuit to an operator by implicit unitary simulation
Operator(circ)
Operator([[ 0.70710678+0.j, 0.70710678+0.j, 0. +0.j, ...,
0. +0.j, 0. +0.j, 0. +0.j],
[ 0. +0.j, 0. +0.j, 0.70710678+0.j, ...,
0. +0.j, 0. +0.j, 0. +0.j],
[ 0. +0.j, 0. +0.j, 0. +0.j, ...,
0. +0.j, 0. +0.j, 0. +0.j],
...,
[ 0. +0.j, 0. +0.j, 0. +0.j, ...,
0. +0.j, 0. +0.j, 0. +0.j],
[ 0. +0.j, 0. +0.j, 0.70710678+0.j, ...,
0. +0.j, 0. +0.j, 0. +0.j],
[ 0.70710678+0.j, -0.70710678+0.j, 0. +0.j, ...,
0. +0.j, 0. +0.j, 0. +0.j]],
input_dims=(2, 2, 2, 2, 2, 2, 2, 2, 2, 2), output_dims=(2, 2, 2, 2, 2, 2, 2, 2, 2, 2))
Utilizarea Operatorilor în Circuit-uri
Operator-ii unitari pot fi inserați direct într-un QuantumCircuit folosind metoda QuantumCircuit.append. Aceasta convertește Operator-ul într-un obiect UnitaryGate, care este adăugat în Circuit.
Dacă operatorul nu este unitar, se ridică o excepție. Acest lucru poate fi verificat folosind funcția Operator.is_unitary(), care returnează True dacă operatorul este unitar și False în caz contrar.
# Create an operator
XX = Operator(Pauli("XX"))
# Add to a circuit
circ = QuantumCircuit(2, 2)
circ.append(XX, [0, 1])
circ.measure([0, 1], [0, 1])
circ.draw("mpl")
Reține că în exemplul de mai sus operatorul este inițializat dintr-un obiect Pauli. Totuși, obiectul Pauli poate fi inserat direct în Circuit și va fi convertit într-o secvență de Gate-uri Pauli cu un singur Qubit:
# Add to a circuit
circ2 = QuantumCircuit(2, 2)
circ2.append(Pauli("XX"), [0, 1])
circ2.measure([0, 1], [0, 1])
circ2.draw()
┌────────────┐┌─┐
q_0: ┤0 ├┤M├───
│ Pauli(XX) │└╥┘┌─┐
q_1: ┤1 ├─╫─┤M├
└────────────┘ ║ └╥┘
c: 2/═══════════════╩══╩═
0 1
Combine Operators
Operatorii pot fi combinați folosind mai multe metode.
Produs tensorial
Doi operatori și pot fi combinați într-un operator produs tensorial folosind funcția Operator.tensor. Rețineți că, dacă atât cât și sunt operatori pe un singur Qubit, atunci A.tensor(B) = va avea subsistemele indexate ca matricea pe subsistemul 0, și matricea pe subsistemul 1.
A = Operator(Pauli("X"))
B = Operator(Pauli("Z"))
A.tensor(B)
Operator([[ 0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j],
[ 0.+0.j, -0.+0.j, 0.+0.j, -1.+0.j],
[ 1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
[ 0.+0.j, -1.+0.j, 0.+0.j, -0.+0.j]],
input_dims=(2, 2), output_dims=(2, 2))
Expansiune tensorială
O operație strâns înrudită este Operator.expand, care acționează ca un produs tensorial, dar în ordine inversă. Astfel, pentru doi operatori și ai A.expand(B) = , unde subsistemele sunt indexate ca matricea pe subsistemul 0, și matricea pe subsistemul 1.
A = Operator(Pauli("X"))
B = Operator(Pauli("Z"))
A.expand(B)
Operator([[ 0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j],
[ 1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
[ 0.+0.j, 0.+0.j, -0.+0.j, -1.+0.j],
[ 0.+0.j, 0.+0.j, -1.+0.j, -0.+0.j]],
input_dims=(2, 2), output_dims=(2, 2))
Compoziție
Poți, de asemenea, să compui doi operatori și pentru a implementa înmulțirea matriceală folosind metoda Operator.compose. A.compose(B) returnează operatorul cu matricea :
A = Operator(Pauli("X"))
B = Operator(Pauli("Z"))
A.compose(B)
Operator([[ 0.+0.j, 1.+0.j],
[-1.+0.j, 0.+0.j]],
input_dims=(2,), output_dims=(2,))
Poți, de asemenea, să compui în ordine inversă, aplicând în fața lui folosind argumentul front al metodei compose: A.compose(B, front=True) = :
A = Operator(Pauli("X"))
B = Operator(Pauli("Z"))
A.compose(B, front=True)
Operator([[ 0.+0.j, -1.+0.j],
[ 1.+0.j, 0.+0.j]],
input_dims=(2,), output_dims=(2,))
Compoziție pe subsisteme
Rețineți că compoziția anterioară necesită ca dimensiunea totală de ieșire a primului operator să fie egală cu dimensiunea totală de intrare a operatorului compus (și similar, dimensiunea de ieșire a lui trebuie să fie egală cu dimensiunea de intrare a lui când se compune cu front=True).
Poți, de asemenea, să compui un operator mai mic cu o selecție de subsisteme ale unui operator mai mare folosind argumentul qargs al metodei compose, cu sau fără front=True. În acest caz, dimensiunile relevante de intrare și ieșire ale subsistemelor compuse trebuie să corespundă. Rețineți că operatorul mai mic trebuie să fie întotdeauna argumentul metodei compose.
De exemplu, pentru a compune o Gate pe doi qubiți cu un operator pe trei qubiți:
# Compose XZ with a 3-qubit identity operator
op = Operator(np.eye(2**3))
XZ = Operator(Pauli("XZ"))
op.compose(XZ, qargs=[0, 2])
Operator([[ 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j,
0.+0.j],
[ 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, -1.+0.j, 0.+0.j,
0.+0.j],
[ 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j,
0.+0.j],
[ 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
-1.+0.j],
[ 1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
0.+0.j],
[ 0.+0.j, -1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
0.+0.j],
[ 0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
0.+0.j],
[ 0.+0.j, 0.+0.j, 0.+0.j, -1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
0.+0.j]],
input_dims=(2, 2, 2), output_dims=(2, 2, 2))
# Compose YX in front of the previous operator
op = Operator(np.eye(2**3))
YX = Operator(Pauli("YX"))
op.compose(YX, qargs=[0, 2], front=True)
Operator([[0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.-1.j, 0.+0.j, 0.+0.j],
[0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.-1.j, 0.+0.j, 0.+0.j, 0.+0.j],
[0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.-1.j],
[0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.-1.j, 0.+0.j],
[0.+0.j, 0.+1.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
[0.+1.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
[0.+0.j, 0.+0.j, 0.+0.j, 0.+1.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
[0.+0.j, 0.+0.j, 0.+1.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j]],
input_dims=(2, 2, 2), output_dims=(2, 2, 2))
Combinații liniare
Operatorii pot fi, de asemenea, combinați folosind operatori liniari standard pentru adunare, scădere și înmulțire cu scalari numere complexe.
XX = Operator(Pauli("XX"))
YY = Operator(Pauli("YY"))
ZZ = Operator(Pauli("ZZ"))
op = 0.5 * (XX + YY - 3 * ZZ)
op
Operator([[-1.5+0.j, 0. +0.j, 0. +0.j, 0. +0.j],
[ 0. +0.j, 1.5+0.j, 1. +0.j, 0. +0.j],
[ 0. +0.j, 1. +0.j, 1.5+0.j, 0. +0.j],
[ 0. +0.j, 0. +0.j, 0. +0.j, -1.5+0.j]],
input_dims=(2, 2), output_dims=(2, 2))
Un aspect important este că, în timp ce tensor, expand și compose păstrează unitaritatea operatorilor unitari, combinațiile liniare nu o fac; prin urmare, adunarea a doi operatori unitari va produce, în general, un operator ne-unitar:
op.is_unitary()
False
Conversie implicită la Operators
Rețineți că pentru toate metodele de mai jos, dacă al doilea obiect nu este deja un obiect Operator, acesta este convertit implicit într-unul de către metodă. Aceasta înseamnă că matricele pot fi transmise direct fără a fi convertite explicit într-un Operator mai întâi. Dacă conversia nu este posibilă, este generată o excepție.
# Compose with a matrix passed as a list
Operator(np.eye(2)).compose([[0, 1], [1, 0]])
Operator([[0.+0.j, 1.+0.j],
[1.+0.j, 0.+0.j]],
input_dims=(2,), output_dims=(2,))
Compară Operators
Operatorii implementează o metodă de egalitate care poate fi folosită pentru a verifica dacă doi operatori sunt aproximativ egali.
Operator(Pauli("X")) == Operator(XGate())
True
Rețineți că aceasta verifică dacă fiecare element al matricei operatorilor este aproximativ egal; doi operatori unitari care diferă printr-o fază globală nu sunt considerați egali:
Operator(XGate()) == np.exp(1j * 0.5) * Operator(XGate())
False
Fidelitate de proces
Poți, de asemenea, să compari operatorii folosind funcția process_fidelity din modulul Quantum Information. Aceasta este o cantitate din teoria informației care măsoară cât de apropiați sunt doi canale cuantice unul de celălalt, iar în cazul operatorilor unitari nu depinde de faza globală.
# Two operators which differ only by phase
op_a = Operator(XGate())
op_b = np.exp(1j * 0.5) * Operator(XGate())
# Compute process fidelity
F = process_fidelity(op_a, op_b)
print("Process fidelity =", F)
Process fidelity = 1.0
Rețineți că fidelitatea de proces este în general o măsură valabilă a apropierii doar dacă operatorii de intrare sunt unitari (sau CP în cazul canalelor cuantice), și este generată o excepție dacă intrările nu sunt CP.
Pași următori
- Explorează referința Operator API.