-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Closed
Labels
mod: quantum infoRelated to the Quantum Info module (States & Operators)Related to the Quantum Info module (States & Operators)type: feature requestNew feature or requestNew feature or request
Description
What should we add?
Currently, it only accepts Pauli. See
qiskit/qiskit/quantum_info/states/stabilizerstate.py
Lines 257 to 320 in e28f30e
def expectation_value(self, oper: Pauli, qargs: None | list = None) -> complex: | |
"""Compute the expectation value of a Pauli operator. | |
Args: | |
oper (Pauli): a Pauli operator to evaluate expval. | |
qargs (None or list): subsystems to apply the operator on. | |
Returns: | |
complex: the expectation value (only 0 or 1 or -1 or i or -i). | |
Raises: | |
QiskitError: if oper is not a Pauli operator. | |
""" | |
if not isinstance(oper, Pauli): | |
raise QiskitError("Operator for expectation value is not a Pauli operator.") | |
num_qubits = self.clifford.num_qubits | |
if qargs is None: | |
qubits = range(num_qubits) | |
else: | |
qubits = qargs | |
# Construct Pauli on num_qubits | |
pauli = Pauli(num_qubits * "I") | |
phase = 0 | |
pauli_phase = (-1j) ** oper.phase if oper.phase else 1 | |
for pos, qubit in enumerate(qubits): | |
pauli.x[qubit] = oper.x[pos] | |
pauli.z[qubit] = oper.z[pos] | |
phase += pauli.x[qubit] & pauli.z[qubit] | |
# Check if there is a stabilizer that anti-commutes with an odd number of qubits | |
# If so the expectation value is 0 | |
for p in range(num_qubits): | |
num_anti = 0 | |
num_anti += np.count_nonzero(pauli.z & self.clifford.stab_x[p]) | |
num_anti += np.count_nonzero(pauli.x & self.clifford.stab_z[p]) | |
if num_anti % 2 == 1: | |
return 0 | |
# Otherwise pauli is (-1)^a prod_j S_j^b_j for Clifford stabilizers | |
# If pauli anti-commutes with D_j then b_j = 1. | |
# Multiply pauli by stabilizers with anti-commuting destabilizers | |
pauli_z = (pauli.z).copy() # Make a copy of pauli.z | |
for p in range(num_qubits): | |
# Check if destabilizer anti-commutes | |
num_anti = 0 | |
num_anti += np.count_nonzero(pauli.z & self.clifford.destab_x[p]) | |
num_anti += np.count_nonzero(pauli.x & self.clifford.destab_z[p]) | |
if num_anti % 2 == 0: | |
continue | |
# If anti-commutes multiply Pauli by stabilizer | |
phase += 2 * self.clifford.stab_phase[p] | |
phase += np.count_nonzero(self.clifford.stab_z[p] & self.clifford.stab_x[p]) | |
phase += 2 * np.count_nonzero(pauli_z & self.clifford.stab_x[p]) | |
pauli_z = pauli_z ^ self.clifford.stab_z[p] | |
# For valid stabilizers, `phase` can only be 0 (= 1) or 2 (= -1) at this point. | |
if phase % 4 != 0: | |
return -pauli_phase | |
return pauli_phase |
Metadata
Metadata
Assignees
Labels
mod: quantum infoRelated to the Quantum Info module (States & Operators)Related to the Quantum Info module (States & Operators)type: feature requestNew feature or requestNew feature or request