Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

StabilizerState.expectation_value should accept SparsePauliOp #12422

Open
kevinsung opened this issue May 16, 2024 · 0 comments
Open

StabilizerState.expectation_value should accept SparsePauliOp #12422

kevinsung opened this issue May 16, 2024 · 0 comments
Labels
mod: quantum info Related to the Quantum Info module (States & Operators) type: feature request New feature or request

Comments

@kevinsung
Copy link
Contributor

What should we add?

Currently, it only accepts Pauli. See

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

@kevinsung kevinsung added the type: feature request New feature or request label May 16, 2024
@ShellyGarion ShellyGarion added the mod: quantum info Related to the Quantum Info module (States & Operators) label Jun 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
mod: quantum info Related to the Quantum Info module (States & Operators) type: feature request New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants