Example #1
0
    def test_svd_on_averaged(self):
        """Use IQ data gathered from the hardware."""
        # This data is primarily oriented along the real axis with a slight tilt.
        # There is a large offset in the imaginary dimension when comparing qubits
        # 0 and 1. The data below is averaged IQ data on two qubits.
        iq_data = [
            [[-6.20601501e14, -1.33257051e15], [-1.70921324e15, -4.05881657e15]],
            [[-5.80546502e14, -1.33492509e15], [-1.65094637e15, -4.05926942e15]],
            [[-4.04649069e14, -1.33191056e15], [-1.29680377e15, -4.03604815e15]],
            [[-2.22203874e14, -1.30291309e15], [-8.57663429e14, -3.97784973e15]],
            [[-2.92074029e13, -1.28578530e15], [-9.78824053e13, -3.92071056e15]],
            [[1.98056981e14, -1.26883024e15], [3.77157017e14, -3.87460328e15]],
            [[4.29955888e14, -1.25022995e15], [1.02340118e15, -3.79508679e15]],
            [[6.38981344e14, -1.25084614e15], [1.68918514e15, -3.78961044e15]],
            [[7.09988897e14, -1.21906634e15], [1.91914171e15, -3.73670664e15]],
            [[7.63169115e14, -1.20797552e15], [2.03772603e15, -3.74653863e15]],
        ]

        self.create_experiment_data(iq_data)

        iq_svd = SVD()
        iq_svd.train(np.asarray([datum["memory"] for datum in self.iq_experiment.data()]))

        np.testing.assert_array_almost_equal(
            iq_svd.parameters.main_axes[0], np.array([0.99633018, 0.08559302])
        )
        np.testing.assert_array_almost_equal(
            iq_svd.parameters.main_axes[1], np.array([0.99627747, 0.0862044])
        )
Example #2
0
    def test_simple_data(self):
        """
        A simple setting where the IQ data of qubit 0 is oriented along (1,1) and
        the IQ data of qubit 1 is oriented along (1,-1).
        """

        iq_data = [[[0.0, 0.0], [0.0, 0.0]], [[1.0, 1.0], [-1.0, 1.0]],
                   [[-1.0, -1.0], [1.0, -1.0]]]

        self.create_experiment(iq_data)

        iq_svd = SVD()
        iq_svd.train([datum["memory"] for datum in self.iq_experiment.data()])

        # qubit 0 IQ data is oriented along (1,1)
        self.assertTrue(
            np.allclose(iq_svd._main_axes[0],
                        np.array([-1, -1]) / np.sqrt(2)))

        # qubit 1 IQ data is oriented along (1, -1)
        self.assertTrue(
            np.allclose(iq_svd._main_axes[1],
                        np.array([-1, 1]) / np.sqrt(2)))

        processed, _ = iq_svd(np.array([[1, 1], [1, -1]]))
        expected = np.array([-1, -1]) / np.sqrt(2)
        self.assertTrue(np.allclose(processed, expected))

        processed, _ = iq_svd(np.array([[2, 2], [2, -2]]))
        self.assertTrue(np.allclose(processed, expected * 2))

        # Check that orthogonal data gives 0.
        processed, _ = iq_svd(np.array([[1, -1], [1, 1]]))
        expected = np.array([0, 0])
        self.assertTrue(np.allclose(processed, expected))
Example #3
0
    def test_json_trained(self):
        """Check if trained data processor is serializable and still work."""
        test_data = {"memory": [[1, 1]]}

        node = SVD()
        node.set_parameters(
            main_axes=np.array([[1, 0]]), scales=[1.0], i_means=[0.0], q_means=[0.0]
        )
        processor = DataProcessor("memory", data_actions=[node])
        self.assertRoundTripSerializable(processor, check_func=self.json_equiv)

        serialized = json.dumps(processor, cls=ExperimentEncoder)
        loaded_processor = json.loads(serialized, cls=ExperimentDecoder)

        ref_out = processor(data=test_data)
        loaded_out = loaded_processor(data=test_data)

        np.testing.assert_array_almost_equal(
            unp.nominal_values(ref_out),
            unp.nominal_values(loaded_out),
        )

        np.testing.assert_array_almost_equal(
            unp.std_devs(ref_out),
            unp.std_devs(loaded_out),
        )
Example #4
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}.")
Example #5
0
    def test_distorted_iq_data(self):
        """Test if uncertainty can consider correlation.

        SVD projects IQ data onto I-axis, and input different data sets that
        have the same mean and same variance but squeezed along different axis.
        """
        svd_node = SVD()
        svd_node._scales = [1.0]
        svd_node._main_axes = [np.array([1, 0])]
        svd_node._means = [(0.0, 0.0)]

        processor = DataProcessor("memory", [AverageData(axis=1), svd_node])

        dist_i_axis = {
            "memory": [[[-1, 0]], [[-0.5, 0]], [[0.0, 0]], [[0.5, 0]], [[1,
                                                                         0]]]
        }
        dist_q_axis = {
            "memory": [[[0, -1]], [[0, -0.5]], [[0, 0.0]], [[0, 0.5]], [[0,
                                                                         1]]]
        }

        out_i = processor(dist_i_axis)
        self.assertAlmostEqual(out_i[0].nominal_value, 0.0)
        self.assertAlmostEqual(out_i[0].std_dev, 0.31622776601683794)

        out_q = processor(dist_q_axis)
        self.assertAlmostEqual(out_q[0].nominal_value, 0.0)
        self.assertAlmostEqual(out_q[0].std_dev, 0.0)
Example #6
0
    def test_on_single_shot(self):
        """Test the SVD node on single shot data."""

        # The data has the shape
        iq_data = [
            # Circuit no. 1, 5 shots
            [
                [[-84858304.0, -111158232.0]],
                [[-92671216.0, -74032944.0]],
                [[-74049176.0, -22372804.0]],
                [[-87495592.0, -72437616.0]],
                [[-52787048.0, -63746976.0]],
            ],
            # Circuit no. 2, 5 shots
            [
                [[-70452328.0, -91318008.0]],
                [[-82281464.0, -72478736.0]],
                [[-107760368.0, -77817680.0]],
                [[-47410012.0, -48451952.0]],
                [[68308432.0, -72074976.0]],
            ],
            # Circuit no. 3, 5 shots
            [
                [[47855768.0, -52185604.0]],
                [[-64009220.0, -79507104.0]],
                [[51899032.0, -80737864.0]],
                [[118873272.0, -43621036.0]],
                [[24438894.0, -84970704.0]],
            ],
        ]

        self.create_experiment_data(iq_data, single_shot=True)

        iq_svd = SVD()
        iq_svd.train(
            np.asarray(
                [datum["memory"] for datum in self.iq_experiment.data()]))

        processed_data = iq_svd(np.array(iq_data))

        # Test the output of the axis
        self.assertEqual(len(iq_svd.parameters.main_axes), 1)
        self.assertTrue(
            np.allclose(iq_svd.parameters.main_axes[0],
                        [0.92727304, 0.37438577]))

        # Test the output data
        self.assertEqual(processed_data.shape, (3, 5, 1))
        test_values = np.array(processed_data[0].flatten(), dtype=float)
        expected = np.array(
            [-0.4982860, -0.4383349, -0.10852355, -0.38971727, -0.07045186],
            dtype=float)
        self.assertTrue(np.allclose(test_values, expected, atol=1e-06))

        # Test in a data processor, will catch, e.g., unumpy issues
        data_processor = DataProcessor("memory", [SVD()])
        data_processor.train(self.iq_experiment.data())
        processed_data = data_processor(self.iq_experiment.data())
        self.assertEqual(processed_data.shape, (3, 5, 1))
Example #7
0
    def test_json_trained(self):
        """Check if the trained node is serializable."""
        node = SVD()
        node.set_parameters(
            main_axes=np.array([[1.0, 2.0]]), scales=[1.0], i_means=[2.0], q_means=[3.0]
        )
        self.assertRoundTripSerializable(node, check_func=self.json_equiv)

        loaded_node = json.loads(json.dumps(node, cls=ExperimentEncoder), cls=ExperimentDecoder)
        self.assertTrue(loaded_node.is_trained)
Example #8
0
    def test_process_all_data(self):
        """Test that we can process all data at once."""

        processor = DataProcessor("memory", [AverageData(axis=1), SVD()])

        # Test training using the calibration points
        self.assertFalse(processor.is_trained)
        processor.train([self.data.data(idx) for idx in [0, 1]])
        self.assertTrue(processor.is_trained)

        all_expected = np.vstack((
            self._sig_es.reshape(1, 2),
            self._sig_gs.reshape(1, 2),
            self._sig_x90.reshape(1, 2),
            self._sig_x45.reshape(1, 2),
        ))

        # Test processing of all data
        processed = processor(self.data.data())
        np.testing.assert_array_almost_equal(
            unp.nominal_values(processed),
            all_expected,
        )

        # Test processing of each datum individually
        for idx, expected in enumerate(
            [self._sig_es, self._sig_gs, self._sig_x90, self._sig_x45]):
            processed = processor(self.data.data(idx))
            np.testing.assert_array_almost_equal(
                unp.nominal_values(processed),
                expected,
            )
    def test_averaging_and_svd(self):
        """Test averaging followed by a SVD."""

        processor = DataProcessor("memory", [AverageData(axis=1), SVD()])

        # Test training using the calibration points
        self.assertFalse(processor.is_trained)
        processor.train([self.data.data(idx) for idx in [0, 1]])
        self.assertTrue(processor.is_trained)

        # Test the excited state
        processed, error = processor(self.data.data(0))
        self.assertTrue(np.allclose(processed, self._sig_es))

        # Test the ground state
        processed, error = processor(self.data.data(1))
        self.assertTrue(np.allclose(processed, self._sig_gs))

        # Test the x90p rotation
        processed, error = processor(self.data.data(2))
        self.assertTrue(np.allclose(processed, self._sig_x90))
        self.assertTrue(np.allclose(error, np.array([0.25, 0.25])))

        # Test the x45p rotation
        processed, error = processor(self.data.data(3))
        expected_std = np.array([np.std([1, 1, 1, -1]) / np.sqrt(4.0) / 2] * 2)
        self.assertTrue(np.allclose(processed, self._sig_x45))
        self.assertTrue(np.allclose(error, expected_std))
Example #10
0
    def test_simple_data(self):
        """
        A simple setting where the IQ data of qubit 0 is oriented along (1,1) and
        the IQ data of qubit 1 is oriented along (1,-1).
        """
        iq_data = [[[0.0, 0.0], [0.0, 0.0]], [[1.0, 1.0], [-1.0, 1.0]],
                   [[-1.0, -1.0], [1.0, -1.0]]]

        self.create_experiment(iq_data)

        iq_svd = SVD()
        iq_svd.train(
            np.asarray(
                [datum["memory"] for datum in self.iq_experiment.data()]))

        # qubit 0 IQ data is oriented along (1,1)
        np.testing.assert_array_almost_equal(iq_svd.parameters.main_axes[0],
                                             np.array([-1, -1]) / np.sqrt(2))

        # qubit 1 IQ data is oriented along (1, -1)
        np.testing.assert_array_almost_equal(iq_svd.parameters.main_axes[1],
                                             np.array([-1, 1]) / np.sqrt(2))

        # This is n_circuit = 1, n_slot = 2, the input shape should be [1, 2, 2]
        # Then the output shape will be [1, 2] by reducing the last dimension
        processed_data = iq_svd(np.array([[[1, 1], [1, -1]]]))
        np.testing.assert_array_almost_equal(
            unp.nominal_values(processed_data),
            np.array([[-1, -1]]) / np.sqrt(2),
        )

        processed_data = iq_svd(np.array([[[2, 2], [2, -2]]]))
        np.testing.assert_array_almost_equal(
            unp.nominal_values(processed_data),
            2 * np.array([[-1, -1]]) / np.sqrt(2),
        )

        # Check that orthogonal data gives 0.
        processed_data = iq_svd(np.array([[[1, -1], [1, 1]]]))
        np.testing.assert_array_almost_equal(
            unp.nominal_values(processed_data),
            np.array([[0, 0]]),
        )
Example #11
0
    def test_svd_error(self):
        """Test the error formula of the SVD."""

        iq_svd = SVD()
        iq_svd._main_axes = np.array([[1.0, 0.0]])
        iq_svd._scales = [1.0]
        iq_svd._means = [[0.0, 0.0]]

        # Since the axis is along the real part the imaginary error is irrelevant.
        processed, error = iq_svd([[1.0, 0.2]], [[0.2, 0.1]])
        self.assertEqual(processed, np.array([1.0]))
        self.assertEqual(error, np.array([0.2]))

        # Since the axis is along the real part the imaginary error is irrelevant.
        processed, error = iq_svd([[1.0, 0.2]], [[0.2, 0.3]])
        self.assertEqual(processed, np.array([1.0]))
        self.assertEqual(error, np.array([0.2]))

        # Tilt the axis to an angle of 36.9... degrees
        iq_svd._main_axes = np.array([[0.8, 0.6]])
        processed, error = iq_svd([[1.0, 0.0]], [[0.2, 0.3]])
        cos_ = np.cos(np.arctan(0.6 / 0.8))
        sin_ = np.sin(np.arctan(0.6 / 0.8))
        self.assertEqual(processed, np.array([cos_]))
        expected_error = np.sqrt((0.2 * cos_)**2 + (0.3 * sin_)**2)
        self.assertEqual(error, np.array([expected_error]))
Example #12
0
    def test_svd_error(self):
        """Test the error formula of the SVD."""
        # This is n_circuit = 1, n_slot = 1, the input shape should be [1, 1, 2]
        # Then the output shape will be [1, 1] by reducing the last dimension

        iq_svd = SVD()
        iq_svd.set_parameters(
            main_axes=np.array([[1.0, 0.0]]), scales=[1.0], i_means=[0.0], q_means=[0.0]
        )

        # Since the axis is along the real part the imaginary error is irrelevant.
        processed_data = iq_svd(unp.uarray(nominal_values=[[[1.0, 0.2]]], std_devs=[[[0.2, 0.1]]]))
        np.testing.assert_array_almost_equal(unp.nominal_values(processed_data), np.array([[1.0]]))
        np.testing.assert_array_almost_equal(unp.std_devs(processed_data), np.array([[0.2]]))

        # Since the axis is along the real part the imaginary error is irrelevant.
        processed_data = iq_svd(unp.uarray(nominal_values=[[[1.0, 0.2]]], std_devs=[[[0.2, 0.3]]]))
        np.testing.assert_array_almost_equal(unp.nominal_values(processed_data), np.array([[1.0]]))
        np.testing.assert_array_almost_equal(unp.std_devs(processed_data), np.array([[0.2]]))

        # Tilt the axis to an angle of 36.9... degrees
        iq_svd.set_parameters(main_axes=np.array([[0.8, 0.6]]))

        processed_data = iq_svd(unp.uarray(nominal_values=[[[1.0, 0.0]]], std_devs=[[[0.2, 0.3]]]))
        cos_ = np.cos(np.arctan(0.6 / 0.8))
        sin_ = np.sin(np.arctan(0.6 / 0.8))
        np.testing.assert_array_almost_equal(
            unp.nominal_values(processed_data),
            np.array([[cos_]]),
        )
        np.testing.assert_array_almost_equal(
            unp.std_devs(processed_data),
            np.array([[np.sqrt((0.2 * cos_) ** 2 + (0.3 * sin_) ** 2)]]),
        )
    def test_normalize(self):
        """Test that by adding a normalization node we get a signal between 1 and 1."""

        processor = DataProcessor("memory", [SVD(), MinMaxNormalize()])

        self.assertFalse(processor.is_trained)
        processor.train([self.data.data(idx) for idx in [0, 1]])
        self.assertTrue(processor.is_trained)

        all_expected = np.array([[0.0, 1.0, 0.5, 0.75], [1.0, 0.0, 0.5, 0.25]])

        # Test processing of all data
        processed = processor(self.data.data())[0]
        self.assertTrue(np.allclose(processed, all_expected))
Example #14
0
    def test_normalize(self):
        """Test that by adding a normalization node we get a signal between 1 and 1."""

        processor = DataProcessor("memory", [SVD(), MinMaxNormalize()])

        self.assertFalse(processor.is_trained)
        processor.train([self.data.data(idx) for idx in [0, 1]])
        self.assertTrue(processor.is_trained)

        # Test processing of all data
        processed = processor(self.data.data())
        np.testing.assert_array_almost_equal(
            unp.nominal_values(processed),
            np.array([[0.0, 1.0], [1.0, 0.0], [0.5, 0.5], [0.75, 0.25]]),
        )
Example #15
0
    def test_averaging_and_svd(self):
        """Test averaging followed by a SVD."""

        processor = DataProcessor("memory", [AverageData(axis=1), SVD()])

        # Test training using the calibration points
        self.assertFalse(processor.is_trained)
        processor.train([self.data.data(idx) for idx in [0, 1]])
        self.assertTrue(processor.is_trained)

        # Test the excited state
        processed = processor(self.data.data(0))
        np.testing.assert_array_almost_equal(
            unp.nominal_values(processed),
            self._sig_es,
        )

        # Test the ground state
        processed = processor(self.data.data(1))
        np.testing.assert_array_almost_equal(
            unp.nominal_values(processed),
            self._sig_gs,
        )

        # Test the x90p rotation
        processed = processor(self.data.data(2))
        np.testing.assert_array_almost_equal(
            unp.nominal_values(processed),
            self._sig_x90,
        )
        np.testing.assert_array_almost_equal(
            unp.std_devs(processed),
            np.array([0.25, 0.25]),
        )

        # Test the x45p rotation
        processed = processor(self.data.data(3))
        np.testing.assert_array_almost_equal(
            unp.nominal_values(processed),
            self._sig_x45,
        )
        np.testing.assert_array_almost_equal(
            unp.std_devs(processed),
            np.array([np.std([1, 1, 1, -1]) / np.sqrt(4.0) / 2] * 2),
        )
Example #16
0
    def test_train_svd_processor(self):
        """Test that we can train a DataProcessor with an SVD."""

        processor = DataProcessor("memory", [SVD()])

        self.assertFalse(processor.is_trained)

        iq_data = [[[0.0, 0.0], [0.0, 0.0]], [[1.0, 1.0], [-1.0, 1.0]],
                   [[-1.0, -1.0], [1.0, -1.0]]]
        self.create_experiment(iq_data)

        processor.train(self.iq_experiment.data())

        self.assertTrue(processor.is_trained)

        # Check that we can use the SVD
        iq_data = [[[2, 2], [2, -2]]]
        self.create_experiment(iq_data)

        processed, _ = processor(self.iq_experiment.data(0))
        expected = np.array([-2, -2]) / np.sqrt(2)
        self.assertTrue(np.allclose(processed, expected))
Example #17
0
 def test_json(self):
     """Check if the node is serializable."""
     node = SVD()
     self.assertRoundTripSerializable(node, check_func=self.json_equiv)