Source code for qarp.cutting._post_processing

"""Abstract PostProcessing base class for QPD-based circuit cutting."""

from abc import ABC, abstractmethod

from qarp.operators import QubitOperator

from ._auto_cut_finder import CutterResult


[docs] class PostProcessing(ABC): def __init__( self, cutter_result: CutterResult, observable: QubitOperator, verbose: bool = True, ) -> None: """ Args: cutter_result: Result of the circuit cutting step. observable: Hamiltonian / observable for the expectation value, as a ``qarp.operators.QubitOperator`` (not openfermion's — convert with ``qarp.operators.compat.from_openfermion()`` first). verbose: Print runtime information. """ assert cutter_result.subcircuits is not None assert len(cutter_result.subcircuits) > 1, "Circuit has not been cut yet." if not isinstance(observable, QubitOperator): obs_type = type(observable) raise TypeError( f"observable must be a qarp.operators.QubitOperator instance, got " f"{obs_type.__module__}.{obs_type.__qualname__} — same class name, " "different (incompatible) type. If converting from openfermion, use " "qarp.operators.compat.from_openfermion() first." ) # idxs[i] = global qubit indices belonging to subcircuit i self.idxs = cutter_result.subcircuit_qubits self.custom_commands = cutter_result.custom_commands self.subcircuits = cutter_result.subcircuits # list of (cmds, n_qubits) self.n_subcircuits = cutter_result.n_subcircuits self.n_cuts = cutter_result.n_cuts self.cut_info = cutter_result.cut_info self.verbose = verbose self.observable = observable self._experiments = None # list of command lists (one per full experiment) self._jobs = None # dict {str(i_sub): list of (cmds, n_qubits)} self._coefficients = None
[docs] @abstractmethod def decompose(self): raise NotImplementedError
[docs] @abstractmethod def compute(self, **kwargs) -> float: raise NotImplementedError
@property def jobs(self): if self._jobs is not None: return self._jobs raise RuntimeError("Cuts have not been processed yet; call decompose() first.") @jobs.setter def jobs(self, value): if not isinstance(value, dict): raise ValueError("jobs must be a dict") self._jobs = value @property def experiments(self): if self._experiments is not None: return self._experiments raise RuntimeError("Cuts have not been processed yet; call decompose() first.") @experiments.setter def experiments(self, value): if not isinstance(value[0], list): raise ValueError("experiments must be a list of command lists") self._experiments = value @property def coefficients(self): if self._coefficients is not None: return self._coefficients raise RuntimeError("Cuts have not been processed yet; call decompose() first.") @coefficients.setter def coefficients(self, value): self._coefficients = value