示例#1
0
def get_processor(
    meas_level: MeasLevel = MeasLevel.CLASSIFIED,
    meas_return: str = "avg",
    normalize: bool = True,
) -> DataProcessor:
    """Get a DataProcessor that produces a continuous signal given the options.

    Args:
        meas_level: The measurement level of the data to process.
        meas_return: The measurement return (single or avg) of the data to process.
        normalize: Add a data normalization node to the Kerneled data processor.

    Returns:
        An instance of DataProcessor capable of dealing with the given options.

    Raises:
        DataProcessorError: if the measurement level is not supported.
    """
    if meas_level == MeasLevel.CLASSIFIED:
        return DataProcessor("counts", [Probability("1")])

    if meas_level == MeasLevel.KERNELED:
        if meas_return == "single":
            processor = DataProcessor("memory", [AverageData(axis=1), SVD()])
        else:
            processor = DataProcessor("memory", [SVD()])

        if normalize:
            processor.append(MinMaxNormalize())

        return processor

    raise DataProcessorError(f"Unsupported measurement level {meas_level}.")
    def test_to_imag(self):
        """Test that we can average the data."""
        processor = DataProcessor("memory")
        processor.append(ToImag(scale=1e-3))

        exp_data = ExperimentData(FakeExperiment())
        exp_data.add_data(self.result_lvl1)

        new_data, error = processor(exp_data.data(0))

        expected_old = {
            "memory": [
                [[1103260.0, -11378508.0], [2959012.0, -16488753.0]],
                [[442170.0, -19283206.0], [-5279410.0, -15339630.0]],
                [[3016514.0, -14548009.0], [-3404756.0, -16743348.0]],
            ],
            "metadata": {
                "experiment_type": "fake_test_experiment"
            },
            "job_id":
            "job-123",
            "meas_level":
            1,
            "shots":
            3,
        }

        expected_new = np.array([
            [-11378.508, -16488.753],
            [-19283.206000000002, -15339.630000000001],
            [-14548.009, -16743.348],
        ])

        self.assertEqual(exp_data.data(0), expected_old)
        self.assertTrue(np.allclose(new_data, expected_new))
        self.assertIsNone(error)

        # Test that we can call with history.
        new_data, error, history = processor.call_with_history(
            exp_data.data(0))
        self.assertEqual(exp_data.data(0), expected_old)
        self.assertTrue(np.allclose(new_data, expected_new))

        self.assertEqual(history[0][0], "ToImag")
        self.assertTrue(np.allclose(history[0][1], expected_new))

        # Test to imaginary on more than one datum
        new_data, error = processor(exp_data.data())

        expected_new = np.array([
            [[-11378.508, -16488.753], [-19283.206, -15339.630],
             [-14548.009, -16743.348]],
            [[-16630.257, -13752.518], [-16031.913, -15840.465],
             [-14955.998, -14538.923]],
        ])

        self.assertTrue(np.allclose(new_data, expected_new))
示例#3
0
    def test_validation(self):
        """Test the validation mechanism."""

        for validate, error in [(False, AttributeError), (True, DataProcessorError)]:
            processor = DataProcessor("counts")
            processor.append(Probability("00", validate=validate))

            with self.assertRaises(error):
                processor({"counts": [0, 1, 2]})
示例#4
0
    def test_populations(self):
        """Test that counts are properly converted to a population."""

        processor = DataProcessor("counts")
        processor.append(Probability("00"))

        new_data = processor(self.exp_data_lvl2.data[0])

        self.assertEqual(new_data[0], 0.4)
        self.assertEqual(new_data[1], 0.4 * (1 - 0.4) / 10)
    def test_populations(self):
        """Test that counts are properly converted to a population."""

        processor = DataProcessor("counts")
        processor.append(Probability("00"))

        # Test on a single datum.
        new_data, error = processor(self.exp_data_lvl2.data(0))

        self.assertEqual(new_data, 0.4)
        self.assertEqual(error, np.sqrt(0.4 * (1 - 0.4) / 10))

        # Test on all the data
        new_data, error = processor(self.exp_data_lvl2.data())
        self.assertTrue(np.allclose(new_data, np.array([0.4, 0.2])))
示例#6
0
    def test_populations(self):
        """Test that counts are properly converted to a population."""

        processor = DataProcessor("counts")
        processor.append(Probability("00", alpha_prior=1.0))

        # Test on a single datum.
        new_data = processor(self.exp_data_lvl2.data(0))

        self.assertAlmostEqual(float(unp.nominal_values(new_data)), 0.41666667)
        self.assertAlmostEqual(float(unp.std_devs(new_data)), 0.13673544235706114)

        # Test on all the data
        new_data = processor(self.exp_data_lvl2.data())
        np.testing.assert_array_almost_equal(
            unp.nominal_values(new_data),
            np.array([0.41666667, 0.25]),
        )
示例#7
0
    def test_to_imag(self):
        """Test that we can average the data."""
        processor = DataProcessor("memory")
        processor.append(ToImag(scale=1e-3))

        exp_data = ExperimentData(FakeExperiment())
        exp_data.add_data(self.result_lvl1)

        new_data = processor(exp_data.data[0])

        expected_old = {
            "memory": [
                [[1103260.0, -11378508.0], [2959012.0, -16488753.0]],
                [[442170.0, -19283206.0], [-5279410.0, -15339630.0]],
                [[3016514.0, -14548009.0], [-3404756.0, -16743348.0]],
            ],
            "metadata": {
                "experiment_type": "fake_test_experiment",
                "x_values": 0.0
            },
        }

        expected_new = np.array([
            [-11378.508, -16488.753],
            [-19283.206000000002, -15339.630000000001],
            [-14548.009, -16743.348],
        ])

        self.assertEqual(exp_data.data[0], expected_old)
        self.assertTrue(np.allclose(new_data, expected_new))

        # Test that we can call with history.
        new_data, history = processor.call_with_history(exp_data.data[0])
        self.assertEqual(exp_data.data[0], expected_old)
        self.assertTrue(np.allclose(new_data, expected_new))

        self.assertEqual(history[0][0], "ToImag")
        self.assertTrue(np.allclose(history[0][1], expected_new))
示例#8
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}.")