Exemple #1
0
 def _default_options(cls) -> Options:
     """Default analysis options common to all analyzes."""
     options = Options()
     # figure names can be set for each analysis by calling
     # experiment_obj.analysis.set_options(figure_names=FIGURE_NAMES)
     options.figure_names = None
     return options
Exemple #2
0
    def test_parallel_options(self):
        """
        Test parallel experiments overriding sub-experiment run and transpile options.
        """
        # These options will all be overridden
        exp0 = FakeExperiment([0])
        exp0.set_transpile_options(optimization_level=1)
        exp2 = FakeExperiment([2])
        exp2.set_experiment_options(dummyoption="test")
        exp2.set_run_options(shots=2000)
        exp2.set_transpile_options(optimization_level=1)
        exp2.analysis.set_options(dummyoption="test")

        par_exp = ParallelExperiment([exp0, exp2])

        with self.assertWarnsRegex(
                Warning,
                "Sub-experiment run and transpile options"
                " are overridden by composite experiment options.",
        ):
            self.assertEqual(par_exp.experiment_options, Options())
            self.assertEqual(par_exp.run_options, Options(meas_level=2))
            self.assertEqual(par_exp.transpile_options,
                             Options(optimization_level=0))
            self.assertEqual(par_exp.analysis.options, Options())

            par_exp.run(FakeBackend())
    def test_parallel_options(self):
        """
        Test parallel experiments overriding sub-experiment run and transpile options.
        """
        # These options will all be overridden
        exp0 = FakeExperiment([0])
        exp0.set_transpile_options(optimization_level=1)
        exp2 = FakeExperiment([2])
        exp2.set_experiment_options(dummyoption="test")
        exp2.set_run_options(shots=2000)
        exp2.set_transpile_options(optimization_level=1)
        exp2.analysis.set_options(dummyoption="test")

        par_exp = ParallelExperiment([exp0, exp2])

        self.assertEqual(par_exp.experiment_options,
                         par_exp._default_experiment_options())
        self.assertEqual(par_exp.run_options, Options(meas_level=2))
        self.assertEqual(par_exp.transpile_options,
                         Options(optimization_level=0))
        self.assertEqual(par_exp.analysis.options,
                         par_exp.analysis._default_options())

        with self.assertWarns(UserWarning):
            expdata = par_exp.run(FakeBackend())
        self.assertExperimentDone(expdata)
Exemple #4
0
    def _default_parameters(cls) -> Options:
        """Parameters of trainable nodes.

        The parameters defined here should be assigned a `None` to
        indicate that the node has not been trained.
        """
        return Options()
 def _default_options(self):
     """Default options of the test backend."""
     return Options(
         shots=1024,
         meas_level=MeasLevel.KERNELED,
         meas_return="single",
     )
 def _default_analysis_options(cls) -> Options:
     """Default options for analysis of experiment results."""
     # Experiment subclasses can override this method if they need
     # to set specific analysis options defaults that are different
     # from the Analysis subclass `_default_options` values.
     if cls.__analysis_class__:
         return cls.__analysis_class__._default_options()
     return Options()
 def _default_experiment_options(cls) -> Options:
     """Default kwarg options for experiment"""
     # Experiment subclasses should override this method to return
     # an `Options` object containing all the supported options for
     # that experiment and their default values. Only options listed
     # here can be modified later by the different methods for
     # setting options.
     return Options()
Exemple #8
0
    def _default_analysis_options(cls) -> Options:
        """Default analysis options."""
        options = Options()
        options.result_parameters = [ParameterRepr("freq", "rabi_rate")]
        options.xlabel = "Amplitude"
        options.ylabel = "Signal (arb. units)"
        options.normalization = True

        return options
    def test_enable_restless(self):
        """Test the enable_restless method."""

        error = -np.pi * 0.01
        backend = MockRestlessFineAmp(error, np.pi, "x")

        amp_exp = FineXAmplitude(0, backend)
        amp_exp.enable_restless(rep_delay=2e-6)

        self.assertTrue(
            amp_exp.run_options,
            Options(meas_level=2,
                    rep_delay=2e-6,
                    init_qubits=False,
                    memory=True,
                    use_measure_esp=False),
        )
Exemple #10
0
 def _default_options(cls):
     """Default options of the test backend."""
     return Options(shots=1024)
Exemple #11
0
 def _default_options(cls) -> Options:
     return Options()
 def _default_experiment_options(cls) -> Options:
     return Options(dummyoption=None)
Exemple #13
0
def get_processor(experiment_data: ExperimentData,
                  analysis_options: Options) -> DataProcessor:
    """Get a DataProcessor that produces a continuous signal given the options.

    Args:
        experiment_data: The experiment data that holds all the data and metadata needed
            to determine the data processor to use to process the data for analysis.
        analysis_options: The analysis options with which to analyze the data. The options that
            are relevant for the configuration of a data processor are:
            - normalization (bool): A boolean to specify if the data should be normalized to
              the interval [0, 1]. The default is True. This option is only relevant if
              kerneled data is used.
            - dimensionality_reduction: An optional string or instance of :class:`ProjectorType`
              to represent the dimensionality reduction node for Kerneled data. For the
              supported nodes, see :class:`ProjectorType`. Typically, these nodes convert
              complex IQ data to real data, for example by performing a singular-value
              decomposition. This argument is only needed for Kerneled data (i.e. level 1)
              and can thus be ignored if Classified data (the default) is used.
            - outcome (string): The measurement outcome that will be passed to a Probability node.
              The default value is a string of 1's where the length of the string is the number of
              qubits, e.g. '111' for three qubits.

    Returns:
        An instance of DataProcessor capable of processing the data for the corresponding job.

    Notes:
        The `physical_qubits` argument is extracted from the `experiment_data`
        metadata and is used to determine the default `outcome` to extract from
        classified data if it was not given in the analysis options.

    Raises:
        DataProcessorError: if the measurement level is not supported.
    """
    metadata = experiment_data.metadata
    if "job_metadata" in metadata:
        # Backwards compatibility for old experiment data
        # remove job metadata and add required fields to new location in metadata
        job_meta = metadata.pop("job_metadata")
        run_options = job_meta[-1].get("run_options", {})
        for opt in ["meas_level", "meas_return"]:
            if opt in run_options:
                metadata[opt] = run_options[opt]
        warnings.warn(
            "The analyzed ExperimentData contains deprecated data processor "
            " job_metadata which has been been updated to current metadat format. "
            "If this data was loaded from a database servide you should re-save it "
            "to update the metadata in the database.",
            DeprecationWarning,
        )

    meas_level = metadata.get("meas_level", MeasLevel.CLASSIFIED)
    meas_return = metadata.get("meas_return", MeasReturnType.AVERAGE)
    normalize = analysis_options.get("normalization", True)
    dimensionality_reduction = analysis_options.get("dimensionality_reduction",
                                                    ProjectorType.SVD)

    if meas_level == MeasLevel.CLASSIFIED:
        num_qubits = len(metadata.get("physical_qubits", [0]))
        outcome = analysis_options.get("outcome", "1" * num_qubits)
        return DataProcessor("counts", [nodes.Probability(outcome)])

    if meas_level == MeasLevel.KERNELED:
        return get_kerneled_processor(dimensionality_reduction, meas_return,
                                      normalize)

    raise DataProcessorError(f"Unsupported measurement level {meas_level}.")
 def _default_run_options(cls) -> Options:
     """Default options values for the experiment :meth:`run` method."""
     return Options(meas_level=MeasLevel.CLASSIFIED)
 def _default_transpile_options(cls) -> Options:
     """Default transpiler options for transpilation of circuits"""
     # Experiment subclasses can override this method if they need
     # to set specific default transpiler options to transpile the
     # experiment circuits.
     return Options(optimization_level=0)
Exemple #16
0
    def _default_analysis_options(cls) -> Options:
        """Default analysis options."""
        options = Options()
        options.normalization = True

        return options
 def _default_options(cls):
     return Options()
Exemple #18
0
def get_processor(
    experiment_data: ExperimentData,
    analysis_options: Options,
    index: int = -1,
) -> DataProcessor:
    """Get a DataProcessor that produces a continuous signal given the options.

    Args:
        experiment_data: The experiment data that holds all the data and metadata needed
            to determine the data processor to use to process the data for analysis.
        analysis_options: The analysis options with which to analyze the data. The options that
            are relevant for the configuration of a data processor are:
            - normalization (bool): A boolean to specify if the data should be normalized to
              the interval [0, 1]. The default is True. This option is only relevant if
              kerneled data is used.
            - dimensionality_reduction: An optional string or instance of :class:`ProjectorType`
              to represent the dimensionality reduction node for Kerneled data. For the
              supported nodes, see :class:`ProjectorType`. Typically, these nodes convert
              complex IQ data to real data, for example by performing a singular-value
              decomposition. This argument is only needed for Kerneled data (i.e. level 1)
              and can thus be ignored if Classified data (the default) is used.
            - outcome (string): The measurement outcome that will be passed to a Probability node.
              The default value is a string of 1's where the length of the string is the number of
              qubits, e.g. '111' for three qubits.
        index: The index of the job for which to get a data processor. The default value is -1.

    Returns:
        An instance of DataProcessor capable of processing the data for the corresponding job.

    Notes:
        The `num_qubits` argument is extracted from the `experiment_data` metadata and is used
        to determine the default `outcome` to extract from classified data if it was not given in the
        analysis options.

    Raises:
        DataProcessorError: if the measurement level is not supported.
        DataProcessorError: if the wrong dimensionality reduction for kerneled data
            is specified.
    """
    run_options = experiment_data.metadata["job_metadata"][index].get(
        "run_options", {})

    meas_level = run_options.get("meas_level", MeasLevel.CLASSIFIED)
    meas_return = run_options.get("meas_return", MeasReturnType.AVERAGE)
    normalize = analysis_options.get("normalization", True)
    dimensionality_reduction = analysis_options.get("dimensionality_reduction",
                                                    ProjectorType.SVD)

    if meas_level == MeasLevel.CLASSIFIED:
        num_qubits = experiment_data.metadata.get("num_qubits", 1)
        outcome = analysis_options.get("outcome", "1" * num_qubits)
        return DataProcessor("counts", [nodes.Probability(outcome)])

    if meas_level == MeasLevel.KERNELED:

        try:
            if isinstance(dimensionality_reduction, ProjectorType):
                projector_name = dimensionality_reduction.name
            else:
                projector_name = dimensionality_reduction

            projector = ProjectorType[projector_name].value

        except KeyError as error:
            raise DataProcessorError(
                f"Invalid dimensionality reduction: {dimensionality_reduction}."
            ) from error

        if meas_return == "single":
            processor = DataProcessor("memory",
                                      [nodes.AverageData(axis=1),
                                       projector()])
        else:
            processor = DataProcessor("memory", [projector()])

        if normalize:
            processor.append(nodes.MinMaxNormalize())

        return processor

    raise DataProcessorError(f"Unsupported measurement level {meas_level}.")
Exemple #19
0
class RestlessMixin:
    """A mixin to facilitate restless experiments.

    This class defines the following methods

        - :meth:`enable_restless`
        - :meth:`_get_restless_processor`
        - :meth:`_t1_check`

    A restless enabled experiment is an experiment that can be run in a restless
    measurement setting. In restless measurements, the qubit is not reset after
    each measurement. Instead, the outcome of the previous quantum non-demolition
    measurement is the initial state for the current circuit. Restless measurements
    therefore require special data processing which is provided by sub-classes of
    the :code:`RestlessNode`. Restless experiments are a fast alternative for
    several calibration and characterization tasks, for details see
    https://arxiv.org/pdf/2202.06981.pdf.
    This class makes it possible for users to enter a restless run-mode without having
    to manually set all the required run options and the data processor. The required options
    are ``rep_delay``, ``init_qubits``, ``memory``, and ``meas_level``. Furthermore,
    subclasses can override the :meth:`_get_restless_processor` method if they require more
    complex restless data processing such as two-qubit calibrations. In addition, this
    class makes it easy to determine if restless measurements are supported for a given
    experiments.
    """

    analysis: BaseAnalysis
    _default_run_options: Options()
    set_run_options: Callable
    _backend: Backend
    _physical_qubits: Sequence[int]
    _num_qubits: int

    def enable_restless(self,
                        rep_delay: Optional[float] = None,
                        override_processor_by_restless: bool = True):
        """Enables a restless experiment by setting the restless run options and the
        restless data processor.

        Args:
            rep_delay: The repetition delay. This is the delay between a measurement
                and the subsequent quantum circuit. Since the backends have
                dynamic repetition rates, the repetition delay can be set to a small
                value which is required for restless experiments. Typical values are
                1 us or less.
            override_processor_by_restless: If False, a data processor that is specified in the
                analysis options of the experiment is not overridden by the restless data
                processor. The default is True.

        Raises:
            DataProcessorError: if the attribute rep_delay_range is not defined for the backend.
            DataProcessorError: if a data processor has already been set but
                override_processor_by_restless is True.
            DataProcessorError: if the experiment analysis does not have the data_processor
                option.
            DataProcessorError: if the rep_delay is equal to or greater than the
                T1 time of one of the physical qubits in the experiment.
        """
        try:
            if not rep_delay:
                rep_delay = self._backend.configuration().rep_delay_range[0]
        except AttributeError as error:
            raise DataProcessorError(
                "The restless experiment can not be enabled because "
                "the attribute rep_delay_range is not defined for this backend "
                "and a minimum rep_delay can not be set.") from error

        # The excited state promotion readout analysis option is set to
        # False because it is not compatible with a restless experiment.
        if self._t1_check(rep_delay):
            meas_level = self._default_run_options().get(
                "meas_level", MeasLevel.CLASSIFIED)
            meas_return = self._default_run_options().get(
                "meas_return", MeasReturnType.SINGLE)
            if not self.analysis.options.get("data_processor", None):
                self.set_run_options(
                    rep_delay=rep_delay,
                    init_qubits=False,
                    memory=True,
                    meas_level=meas_level,
                    meas_return=meas_return,
                    use_measure_esp=False,
                )
                if hasattr(self.analysis.options, "data_processor"):
                    self.analysis.set_options(
                        data_processor=self._get_restless_processor(
                            meas_level=meas_level))
                else:
                    raise DataProcessorError(
                        "The restless data processor can not be set since the experiment analysis"
                        "does not have the data_processor option.")
            else:
                if not override_processor_by_restless:
                    self.set_run_options(
                        rep_delay=rep_delay,
                        init_qubits=False,
                        memory=True,
                        meas_level=meas_level,
                        meas_return=meas_return,
                        use_measure_esp=False,
                    )
                else:
                    raise DataProcessorError(
                        "Cannot enable restless. Data processor has already been set and "
                        "override_processor_by_restless is True.")
        else:
            raise DataProcessorError(
                f"The specified repetition delay {rep_delay} is equal to or greater "
                f"than the T1 time of one of the physical qubits"
                f"{self._physical_qubits} in the experiment. Consider choosing "
                f"a smaller repetition delay for the restless experiment.")

    def _get_restless_processor(self,
                                meas_level: int = MeasLevel.CLASSIFIED
                                ) -> DataProcessor:
        """Returns the restless experiments data processor.

        Notes:
            Sub-classes can override this method if they need more complex data processing.
        """
        outcome = self.analysis.options.get("outcome", "1" * self._num_qubits)
        meas_return = self.analysis.options.get("meas_return",
                                                MeasReturnType.SINGLE)
        normalize = self.analysis.options.get("normalization", True)
        dimensionality_reduction = self.analysis.options.get(
            "dimensionality_reduction", ProjectorType.SVD)

        if meas_level == MeasLevel.KERNELED:
            return get_kerneled_processor(dimensionality_reduction,
                                          meas_return, normalize,
                                          [nodes.RestlessToIQ()])

        else:
            return DataProcessor(
                "memory",
                [
                    nodes.RestlessToCounts(self._num_qubits),
                    nodes.Probability(outcome),
                ],
            )

    def _t1_check(self, rep_delay: float) -> bool:
        """Check that repetition delay < T1 of the physical qubits in the experiment.

        Args:
            rep_delay: The repetition delay. This is the delay between a measurement
                    and the subsequent quantum circuit.

        Returns:
            True if the repetition delay is smaller than the qubit T1 times.

        Raises:
            DataProcessorError: if the T1 values are not defined for the qubits of
                the used backend.
        """

        try:
            t1_values = [
                self._backend.properties().qubit_property(physical_qubit)["T1"]
                [0] for physical_qubit in self._physical_qubits
            ]

            if all(rep_delay / t1_value < 1.0 for t1_value in t1_values):
                return True
        except AttributeError as error:
            raise DataProcessorError(
                "The restless experiment can not be enabled since "
                "T1 values are not defined for the qubits of the used backend."
            ) from error

        return False
Exemple #20
0
    def _default_options(cls) -> Options:
        """Return default draw options.

        Draw Options:
            axis (Any): Arbitrary object that can be used as a drawing canvas.
            subplots (Tuple[int, int]): Number of rows and columns when the experimental
                result is drawn in the multiple windows.
            xlabel (Union[str, List[str]]): X-axis label string of the output figure.
                If there are multiple columns in the canvas, this could be a list of labels.
            ylabel (Union[str, List[str]]): Y-axis label string of the output figure.
                If there are multiple rows in the canvas, this could be a list of labels.
            xlim (Tuple[float, float]): Min and max value of the horizontal axis.
                If not provided, it is automatically scaled based on the input data points.
            ylim (Tuple[float, float]): Min and max value of the vertical axis.
                If not provided, it is automatically scaled based on the input data points.
            xval_unit (str): SI unit of x values. No prefix is needed here.
                For example, when the x values represent time, this option will be just "s"
                rather than "ms". In the output figure, the prefix is automatically selected
                based on the maximum value in this axis. If your x values are in [1e-3, 1e-4],
                they are displayed as [1 ms, 10 ms]. This option is likely provided by the
                analysis class rather than end-users. However, users can still override
                if they need different unit notation. By default, this option is set to ``None``,
                and no scaling is applied. If nothing is provided, the axis numbers will be
                displayed in the scientific notation.
            yval_unit (str): Unit of y values. See ``xval_unit`` for details.
            figsize (Tuple[int, int]): A tuple of two numbers representing the size of
                the output figure (width, height). Note that this is applicable
                only when ``axis`` object is not provided. If any canvas object is provided,
                the figure size associated with the axis is preferentially applied.
            legend_loc (str): Vertical and horizontal location of the curve legend window in
                a single string separated by a space. This defaults to ``center right``.
                Vertical position can be ``upper``, ``center``, ``lower``.
                Horizontal position can be ``right``, ``center``, ``left``.
            tick_label_size (int): Size of text representing the axis tick numbers.
            axis_label_size (int): Size of text representing the axis label.
            fit_report_rpos (Tuple[int, int]): A tuple of numbers showing the location of
                the fit report window. These numbers are horizontal and vertical position
                of the top left corner of the window in the relative coordinate
                on the output figure, i.e. ``[0, 1]``.
                The fit report window shows the selected fit parameters and the reduced
                chi-squared value.
            fit_report_text_size (int): Size of text in the fit report window.
            plot_sigma (List[Tuple[float, float]]): A list of two number tuples
                showing the configuration to write confidence intervals for the fit curve.
                The first argument is the relative sigma (n_sigma), and the second argument is
                the transparency of the interval plot in ``[0, 1]``.
                Multiple n_sigma intervals can be drawn for the single curve.
        """
        return Options(
            axis=None,
            subplots=(1, 1),
            xlabel=None,
            ylabel=None,
            xlim=None,
            ylim=None,
            xval_unit=None,
            yval_unit=None,
            figsize=(8, 5),
            legend_loc="center right",
            tick_label_size=14,
            axis_label_size=16,
            fit_report_rpos=(0.6, 0.95),
            fit_report_text_size=14,
            plot_sigma=[(1.0, 0.7), (3.0, 0.3)],
        )