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

Delegate CircuitResult.probabilities() to the backend #618

Merged
merged 2 commits into from
Jul 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions src/qibo/backends/abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ def execute_distributed_circuit(self, circuit, initial_state=None, nshots=None):
raise_error(NotImplementedError)

@abc.abstractmethod
def get_state_repr(self, result): # pragma: no cover
def circuit_result_representation(self, result): # pragma: no cover
"""Represent a quantum state based on circuit execution results.

Args:
Expand All @@ -194,7 +194,7 @@ def get_state_repr(self, result): # pragma: no cover
raise_error(NotImplementedError)

@abc.abstractmethod
def get_state_tensor(self, result): # pragma: no cover
def circuit_result_tensor(self, result): # pragma: no cover
"""State vector or density matrix representing a quantum state as an array.

Args:
Expand All @@ -203,6 +203,17 @@ def get_state_tensor(self, result): # pragma: no cover
"""
raise_error(NotImplementedError)

@abc.abstractmethod
def circuit_result_probabilities(self, result, qubits=None): # pragma: no cover
"""Calculates measurement probabilities by tracing out qubits.

Args:
result (:class:`qibo.states.CircuitResult`): Result object that contains
the data required to represent the state.
qubits (list, set): Set of qubits that are measured.
"""
raise_error(NotImplementedError)

@abc.abstractmethod
def calculate_symbolic(self, state, nqubits, decimals=5, cutoff=1e-10, max_terms=20): # pragma: no cover
"""Dirac representation of a state vector."""
Expand Down
14 changes: 12 additions & 2 deletions src/qibo/backends/numpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,12 +389,22 @@ def execute_circuit_repeated(self, circuit, initial_state=None, nshots=None):
def execute_distributed_circuit(self, circuit, initial_state=None, nshots=None, return_array=False):
raise_error(NotImplementedError, f"{self} does not support distributed execution.")

def get_state_repr(self, result):
def circuit_result_representation(self, result):
return result.symbolic()

def get_state_tensor(self, result):
def circuit_result_tensor(self, result):
return result.execution_result

def circuit_result_probabilities(self, result, qubits=None):
if qubits is None: # pragma: no cover
qubits = result.circuit.measurement_gate.qubits

state = self.circuit_result_tensor(result)
if result.density_matrix:
return self.calculate_probabilities_density_matrix(state, qubits, result.nqubits)
else:
return self.calculate_probabilities(state, qubits, result.nqubits)

def calculate_symbolic(self, state, nqubits, decimals=5, cutoff=1e-10, max_terms=20):
state = self.to_numpy(state)
terms = []
Expand Down
17 changes: 4 additions & 13 deletions src/qibo/states.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def state(self, numpy=False, decimals=-1, cutoff=1e-10, max_terms=20):
basis, otherwise a string with the Dirac representation of the state
in the computational basis.
"""
tensor = self.backend.get_state_tensor(self)
tensor = self.backend.circuit_result_tensor(self)
if decimals >= 0:
return self.symbolic(decimals, cutoff, max_terms)
if numpy:
Expand All @@ -63,15 +63,15 @@ def symbolic(self, decimals=5, cutoff=1e-10, max_terms=20):
Returns:
A string representing the state in the computational basis.
"""
state = self.backend.get_state_tensor(self)
state = self.backend.circuit_result_tensor(self)
if self.density_matrix:
terms = self.backend.calculate_symbolic_density_matrix(state, self.nqubits, decimals, cutoff, max_terms)
else:
terms = self.backend.calculate_symbolic(state, self.nqubits, decimals, cutoff, max_terms)
return " + ".join(terms)

def __repr__(self):
return self.backend.get_state_repr(self)
return self.backend.circuit_result_representation(self)

def __array__(self):
"""State's tensor representation as an array."""
Expand All @@ -80,19 +80,10 @@ def __array__(self):
def probabilities(self, qubits=None):
"""Calculates measurement probabilities by tracing out qubits.

Exactly one of the following arguments should be given.

Args:
qubits (list, set): Set of qubits that are measured.
"""
if qubits is None: # pragma: no cover
qubits = self.circuit.measurement_gate.qubits

state = self.backend.get_state_tensor(self)
if self.density_matrix:
return self.backend.calculate_probabilities_density_matrix(state, qubits, self.nqubits)
else:
return self.backend.calculate_probabilities(state, qubits, self.nqubits)
return self.backend.circuit_result_probabilities(self, qubits)

def samples(self, binary=True, registers=False):
"""Returns raw measurement samples.
Expand Down