C贸digo fuente para qiskit.transpiler.passes.utils.minimum_point

# This code is part of Qiskit.
# (C) Copyright IBM 2023
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""Check if the DAG has reached a relative semi-stable point over previous runs."""

from copy import deepcopy
from dataclasses import dataclass
import math
from typing import Tuple

from qiskit.dagcircuit.dagcircuit import DAGCircuit
from qiskit.transpiler.basepasses import TransformationPass

[documentos]class MinimumPoint(TransformationPass): """Check if the DAG has reached a relative semi-stable point over previous runs This pass is similar to the :class:`~.FixedPoint` transpiler pass and is intended primarily to be used to set a loop break condition in the property set. However, unlike the :class:`~.FixedPoint` class which only sets the condition if 2 consecutive runs have the same value property set value this pass is designed to find a local minimum and use that instead. This pass is designed for an optimization loop where a fixed point may never get reached (for example if synthesis is used and there are multiple equivalent outputs for some cases). This pass will track the state of fields in the property set over its past executions and set a boolean field when either a fixed point is reached over the backtracking depth or selecting the minimum value found if the backtracking depth is reached. To do this it stores a deep copy of the current minimum DAG in the property set and when ``backtrack_depth`` number of executions is reached since the last minimum the output dag is set to that copy of the earlier minimum. Fields used by this pass in the property set are (all relative to the ``prefix`` argument): * ``{prefix}_minimum_point_state`` - Used to track the state of the minimpoint search * ``{prefix}_minimum_point`` - This value gets set to ``True`` when either a fixed point is reached over the ``backtrack_depth`` executions, or ``backtrack_depth`` was exceeded and an earlier minimum is restored. """ def __init__(self, property_set_list, prefix, backtrack_depth=5): """Initialize an instance of this pass Args: property_set_list (list): A list of property set keys that will be used to evaluate the local minimum. The values of these property set keys will be used as a tuple for comparison prefix (str): The prefix to use for the property set key that is used for tracking previous evaluations backtrack_depth (int): The maximum number of entries to store. If this number is reached and the next iteration doesn't have a decrease in the number of values the minimum of the previous n will be set as the output dag and ``minimum_point`` will be set to ``True`` in the property set """ super().__init__() self.property_set_list = property_set_list self.backtrack_name = f"{prefix}_minimum_point_state" self.minimum_reached = f"{prefix}_minimum_point" self.backtrack_depth = backtrack_depth
[documentos] def run(self, dag): """Run the MinimumPoint pass on `dag`.""" score = tuple(self.property_set[x] for x in self.property_set_list) state = self.property_set[self.backtrack_name] # The pass starts at None and the first iteration doesn't set a real # score so the overall loop is treated as a do-while to ensure we have # at least 2 iterations. if state is None: self.property_set[self.backtrack_name] = _MinimumPointState( dag=None, score=(math.inf,) * len(self.property_set_list), since=0 ) # If the score of this execution is worse than the previous execution # increment 'since' since we have not found a new minimum point elif score > state.score: state.since += 1 if state.since == self.backtrack_depth: self.property_set[self.minimum_reached] = True return self.property_set[self.backtrack_name].dag # If the score has decreased (gotten better) then this iteration is # better performing and this iteration should be the new minimum state. # So update the state to be this iteration and reset counter elif score < state.score: state.since = 1 state.score = score state.dag = deepcopy(dag) # If the current execution is equal to the previous minimum value then # we've reached an equivalent fixed point and we should use this iteration's # dag as the output and set the property set flag that we've found a minimum # point. elif score == state.score: self.property_set[self.minimum_reached] = True return dag return dag
@dataclass class _MinimumPointState: __slots__ = ("dag", "score", "since") dag: DAGCircuit score: Tuple[float, ...] since: int