Пример #1
0
 def test_init_multiple_digits(self):
     """Test __init__ for sparse label with multiple digits"""
     actual = SpinOp([("X_10^20", 1 + 2j), ("X_12^34", 56)],
                     Fraction(5, 2),
                     register_length=13)
     desired = [("X_10^20", 1 + 2j), ("X_12^34", 56)]
     self.assertListEqual(actual.to_list(), desired)
Пример #2
0
 def test_init_raising_lowering_ops(self):
     """Test __init__ for +_i -_i pattern"""
     with self.subTest("one reg"):
         actual = SpinOp("+_0 -_0", spin=1, register_length=1)
         expected = SpinOp([("X_0^2", 1), ("Y_0^2", 1), ("Z_0", 1)],
                           spin=1,
                           register_length=1)
         self.assertSpinEqual(actual, expected)
     with self.subTest("two reg"):
         actual = SpinOp("+_1 -_1 +_0 -_0", spin=3 / 2, register_length=2)
         expected = SpinOp(
             [
                 ("X_0^2 X_1^2", 1),
                 ("X_0^2 Y_1^2", 1),
                 ("X_0^2 Z_1", 1),
                 ("Y_0^2 X_1^2", 1),
                 ("Y_0^2 Y_1^2", 1),
                 ("Y_0^2 Z_1", 1),
                 ("Z_0 X_1^2", 1),
                 ("Z_0 Y_1^2", 1),
                 ("Z_0 Z_1", 1),
             ],
             spin=3 / 2,
             register_length=2,
         )
         self.assertSpinEqual(actual, expected)
Пример #3
0
 def test_init_label(self, label, pre_processing):
     """Test __init__"""
     spin = SpinOp(pre_processing(label), register_length=len(label) // 3)
     expected_label = " ".join(l for l in label.split() if l[0] != "I")
     if not expected_label:
         expected_label = f"I_{len(label) // 3 - 1}"
     self.assertListEqual(spin.to_list(), [(expected_label, 1)])
     self.assertSpinEqual(eval(repr(spin)), spin)  # pylint: disable=eval-used
Пример #4
0
 def test_init_dense_label(self, label):
     """Test __init__ for dense label"""
     if len(label) == 1:
         actual = SpinOp([(f"{label}", 1 + 1j)])
         desired = SpinOp([(f"{label}_0", 1 + 1j)])
     elif len(label) == 2:
         actual = SpinOp([(f"{label}", 1)])
         desired = SpinOp([(f"{label[0]}_1 {label[1]}_0", 1)])
     self.assertSpinEqual(actual, desired)
Пример #5
0
    def test_add(self):
        """Test __add__"""
        with self.subTest("sum of heisenberg"):
            actual = self.heisenberg + self.heisenberg
            desired = SpinOp(
                (self.heisenberg_spin_array, 2 * self.heisenberg_coeffs),
                spin=1)
            self.assertSpinEqual(actual, desired)

        with self.subTest("raising operator"):
            plus = SpinOp("+", 3 / 2)
            x = SpinOp("X", 3 / 2)
            y = SpinOp("Y", 3 / 2)
            self.assertSpinEqual(x + 1j * y, plus)
Пример #6
0
 def test_flatten_ladder_ops(self):
     """Test _flatten_ladder_ops"""
     actual = SpinOp._flatten_ladder_ops([("+-", 2j)])
     self.assertSetEqual(
         frozenset(actual),
         frozenset([("XX", 2j), ("XY", 2), ("YX", -2), ("YY", 2j)]),
     )
Пример #7
0
    def test_adjoint(self):
        """Test adjoint method and dagger property"""
        with self.subTest("heisenberg adjoint"):
            actual = self.heisenberg.adjoint()
            desired = SpinOp((self.heisenberg_spin_array,
                              self.heisenberg_coeffs.conjugate().T),
                             spin=1)
            self.assertSpinEqual(actual, desired)

        with self.subTest("imag heisenberg adjoint"):
            actual = ~((3 + 2j) * self.heisenberg)
            desired = SpinOp(
                (self.heisenberg_spin_array,
                 ((3 + 2j) * self.heisenberg_coeffs).conjugate().T),
                spin=1,
            )
            self.assertSpinEqual(actual, desired)
Пример #8
0
    def test_reduce(self):
        """Test reduce"""
        with self.subTest("trivial reduce"):
            actual = (self.heisenberg - self.heisenberg).reduce()
            self.assertListEqual(actual.to_list(), [("I_1 I_0", 0)])

        with self.subTest("nontrivial reduce"):
            test_op = SpinOp(
                (
                    np.array([[[0, 1], [0, 1]], [[0, 0], [0, 0]],
                              [[1, 0], [1, 0]]]),
                    np.array([1.5, 2.5]),
                ),
                spin=3 / 2,
            )
            actual = test_op.reduce()
            self.assertListEqual(actual.to_list(), [("Z_1 X_0", 4)])

        with self.subTest("nontrivial reduce 2"):
            test_op = SpinOp(
                (
                    np.array([
                        [[0, 1], [0, 1], [1, 1]],
                        [[0, 0], [0, 0], [0, 0]],
                        [[1, 0], [1, 0], [0, 0]],
                    ]),
                    np.array([1.5, 2.5, 2]),
                ),
                spin=3 / 2,
            )
            actual = test_op.reduce()
            self.assertListEqual(actual.to_list(), [("Z_1 X_0", 4),
                                                    ("X_1 X_0", 2)])
Пример #9
0
 def test_init_heisenberg(self):
     """Test __init__ for Heisenberg model."""
     actual = SpinOp(
         [
             ("XX", -1),
             ("YY", -1),
             ("ZZ", -1),
             ("ZI", -0.3),
             ("IZ", -0.3),
         ],
         spin=1,
     )
     self.assertSpinEqual(actual, self.heisenberg)
Пример #10
0
 def setUp(self):
     super().setUp()
     self.heisenberg_spin_array = np.array([
         [[1, 1], [0, 0], [0, 0], [0, 0], [0, 0]],
         [[0, 0], [1, 1], [0, 0], [0, 0], [0, 0]],
         [[0, 0], [0, 0], [1, 1], [1, 0], [0, 1]],
     ], )
     self.heisenberg_coeffs = np.array([-1, -1, -1, -0.3, -0.3])
     self.heisenberg = SpinOp(
         (self.heisenberg_spin_array, self.heisenberg_coeffs),
         spin=1,
     )
     self.zero_op = SpinOp(
         (np.array([[[0, 0]], [[0, 0]], [[0, 0]]]), np.array([0])),
         spin=1,
     )
     self.spin_1_matrix = {
         "I": np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]),
         "X": np.array([[0, 1, 0], [1, 0, 1], [0, 1, 0]]) / np.sqrt(2),
         "Y":
         np.array([[0, -1j, 0], [1j, 0, -1j], [0, 1j, 0]]) / np.sqrt(2),
         "Z": np.array([[1, 0, 0], [0, 0, 0], [0, 0, -1]]),
     }
Пример #11
0
class TestLinearMapper(QiskitNatureTestCase):
    """ Test Linear Mapper """

    spin_op1 = SpinOp([('Y_0^2', -0.432 + 1.32j)], 0.5, 1)
    ref_qubit_op1 = (-0.054 + 0.165j) * (I ^ I) + (0.054 - 0.165j) * (Z ^ Z)

    spin_op2 = SpinOp([('X_0 Z_0 I_1', -1.139 + 0.083j)], 0.5, 2)
    ref_qubit_op2 = (0.010375 + 0.142375j) * (I ^ I ^ Y ^ X) + \
                    (-0.010375 - 0.142375j) * (I ^ I ^ X ^ Y)

    spin_op3 = SpinOp([('X_0 Y_0^2 Z_0 X_1 Y_1 Y_2 Z_2', -0.18 + 1.204j)], 0.5,
                      3)
    ref_qubit_op3 = (0.000587890625 + 8.7890625e-05j) * (Y ^ Y ^ I ^ Z ^ Y ^ X) + \
                    (0.000587890625 + 8.7890625e-05j) * (X ^ X ^ I ^ Z ^ Y ^ X) + \
                    (-0.000587890625 - 8.7890625e-05j) * (Y ^ Y ^ Z ^ I ^ Y ^ X) + \
                    (-0.000587890625 - 8.7890625e-05j) * (X ^ X ^ Z ^ I ^ Y ^ X) + \
                    (-0.000587890625 - 8.7890625e-05j) * (Y ^ Y ^ I ^ Z ^ X ^ Y) + \
                    (-0.000587890625 - 8.7890625e-05j) * (X ^ X ^ I ^ Z ^ X ^ Y) + \
                    (0.000587890625 + 8.7890625e-05j) * (Y ^ Y ^ Z ^ I ^ X ^ Y) + \
                    (0.000587890625 + 8.7890625e-05j) * (X ^ X ^ Z ^ I ^ X ^ Y)

    spin_op4 = SpinOp([('I_0 Z_1', -0.875 - 0.075j)], 1.5, 2)
    ref_qubit_op4 = (-0.65625 - 0.05625j) * (Z ^ I ^ I ^ I ^ I ^ I ^ I ^ I) + \
                    (-0.21875 - 0.01875j) * (I ^ Z ^ I ^ I ^ I ^ I ^ I ^ I) + \
                    (0.21875 + 0.01875j) * (I ^ I ^ Z ^ I ^ I ^ I ^ I ^ I) + \
                    (0.65625 + 0.05625j) * (I ^ I ^ I ^ Z ^ I ^ I ^ I ^ I)

    spin_op5 = SpinOp([('X_0 I_1 I_2 I_3 I_4 I_5 I_6 I_7', 4 + 0j)], 0.5, 8) + \
        SpinOp([('I_0^2 I_2 I_3 I_4 I_5 I_6 I_7 I_8', 8 + 0j)], 0.5, 8)
    ref_qubit_op5 = (8.0 + 0j) * (I ^ I ^ I ^ I ^ I ^ I ^ I ^ I ^ I ^ I ^ I ^ I ^ I ^ I ^ I ^ I) + \
                    (1.0 + 0j) * (I ^ I ^ I ^ I ^ I ^ I ^ I ^ I ^ I ^ I ^ I ^ I ^ I ^ I ^ X ^ X) + \
                    (1.0 + 0j) * (I ^ I ^ I ^ I ^ I ^ I ^ I ^ I ^ I ^ I ^ I ^ I ^ I ^ I ^ Y ^ Y)

    @data(
        (spin_op1, ref_qubit_op1),
        (spin_op2, ref_qubit_op2),
        (spin_op3, ref_qubit_op3),
        (spin_op4, ref_qubit_op4),
        (spin_op5, ref_qubit_op5),
    )
    @unpack
    def test_mapping(self, spin_op, ref_qubit_op):
        """ Test mapping to qubit operator """
        mapper = LinearMapper()
        qubit_op = mapper.map(spin_op)
        self.assertEqual(qubit_op, ref_qubit_op)
Пример #12
0
 def test_mul(self):
     """Test __mul__, and __rmul__"""
     actual = self.heisenberg * 2
     desired = SpinOp(
         (self.heisenberg_spin_array, 2 * self.heisenberg_coeffs), spin=1)
     self.assertSpinEqual(actual, desired)
Пример #13
0
    def test_init_pm_label(self):
        """Test __init__ with plus and minus label"""
        with self.subTest("plus"):
            plus = SpinOp([("+_0", 2)], register_length=1)
            desired = SpinOp([("X_0", 2), ("Y_0", 2j)], register_length=1)
            self.assertSpinEqual(plus, desired)

        with self.subTest("dense plus"):
            plus = SpinOp([("+", 2)])
            desired = SpinOp([("X_0", 2), ("Y_0", 2j)], register_length=1)
            self.assertSpinEqual(plus, desired)

        with self.subTest("minus"):
            minus = SpinOp([("-_0", 2)], register_length=1)
            desired = SpinOp([("X_0", 2), ("Y_0", -2j)], register_length=1)
            self.assertSpinEqual(minus, desired)

        with self.subTest("minus"):
            minus = SpinOp([("-", 2)])
            desired = SpinOp([("X_0", 2), ("Y_0", -2j)], register_length=1)
            self.assertSpinEqual(minus, desired)

        with self.subTest("plus tensor minus"):
            plus_tensor_minus = SpinOp([("+_0 -_1", 3)], register_length=2)
            desired = SpinOp(
                [("X_0 X_1", 3), ("Y_0 X_1", 3j), ("X_0 Y_1", -3j),
                 ("Y_0 Y_1", 3)],
                register_length=2,
            )
            self.assertSpinEqual(plus_tensor_minus, desired)

        with self.subTest("dense plus tensor minus"):
            plus_tensor_minus = SpinOp([("+-", 3)])
            desired = SpinOp(
                [("X_0 X_1", 3), ("Y_0 X_1", 3j), ("X_0 Y_1", -3j),
                 ("Y_0 Y_1", 3)],
                register_length=2,
            )
            self.assertSpinEqual(plus_tensor_minus, desired)
Пример #14
0
 def assertSpinEqual(first: SpinOp, second: SpinOp):
     """Fail if two SpinOps have different matrix representations."""
     np.testing.assert_array_almost_equal(first.to_matrix(),
                                          second.to_matrix())
Пример #15
0
 def test_init_len2_label(self, label):
     """Test __init__"""
     spin = SpinOp(f"{label[1]}_1 {label[0]}_0")
     self.assertListEqual(spin.to_list(),
                          [(f"{label[1]}_1 {label[0]}_0", 1)])
Пример #16
0
class TestSpinOp(QiskitNatureTestCase):
    """SpinOp tests."""
    def setUp(self):
        super().setUp()
        self.heisenberg_spin_array = np.array([
            [[1, 1], [0, 0], [0, 0], [0, 0], [0, 0]],
            [[0, 0], [1, 1], [0, 0], [0, 0], [0, 0]],
            [[0, 0], [0, 0], [1, 1], [1, 0], [0, 1]],
        ], )
        self.heisenberg_coeffs = np.array([-1, -1, -1, -0.3, -0.3])
        self.heisenberg = SpinOp(
            (self.heisenberg_spin_array, self.heisenberg_coeffs),
            spin=1,
        )
        self.zero_op = SpinOp(
            (np.array([[[0, 0]], [[0, 0]], [[0, 0]]]), np.array([0])),
            spin=1,
        )
        self.spin_1_matrix = {
            "I": np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]),
            "X": np.array([[0, 1, 0], [1, 0, 1], [0, 1, 0]]) / np.sqrt(2),
            "Y":
            np.array([[0, -1j, 0], [1j, 0, -1j], [0, 1j, 0]]) / np.sqrt(2),
            "Z": np.array([[1, 0, 0], [0, 0, 0], [0, 0, -1]]),
        }

    @staticmethod
    def assertSpinEqual(first: SpinOp, second: SpinOp):
        """Fail if two SpinOps have different matrix representations."""
        np.testing.assert_array_almost_equal(first.to_matrix(),
                                             second.to_matrix())

    @data(*product(
        (*sparse_labels(1), *sparse_labels(2), *sparse_labels(3)),
        (str2str, str2tuple, str2list),
    ))
    @unpack
    def test_init_label(self, label, pre_processing):
        """Test __init__"""
        spin = SpinOp(pre_processing(label), register_length=len(label) // 3)
        expected_label = " ".join(l for l in label.split() if l[0] != "I")
        if not expected_label:
            expected_label = f"I_{len(label) // 3 - 1}"
        self.assertListEqual(spin.to_list(), [(expected_label, 1)])
        self.assertSpinEqual(eval(repr(spin)), spin)  # pylint: disable=eval-used

    @data(*product(
        (
            *zip(dense_labels(1), sparse_labels(1)),
            *zip(dense_labels(2), sparse_labels(2)),
            *zip(dense_labels(3), sparse_labels(3)),
        ),
        (str2str, str2tuple, str2list),
    ))
    @unpack
    def test_init_dense_label(self, labels, pre_processing):
        """Test __init__ for dense label"""
        dense_label, sparse_label = labels
        actual = SpinOp(pre_processing(dense_label))
        desired = SpinOp([(sparse_label, 1)], register_length=len(dense_label))
        self.assertSpinEqual(actual, desired)

    def test_init_pm_label(self):
        """Test __init__ with plus and minus label"""
        with self.subTest("plus"):
            plus = SpinOp([("+_0", 2)], register_length=1)
            desired = SpinOp([("X_0", 2), ("Y_0", 2j)], register_length=1)
            self.assertSpinEqual(plus, desired)

        with self.subTest("dense plus"):
            plus = SpinOp([("+", 2)])
            desired = SpinOp([("X_0", 2), ("Y_0", 2j)], register_length=1)
            self.assertSpinEqual(plus, desired)

        with self.subTest("minus"):
            minus = SpinOp([("-_0", 2)], register_length=1)
            desired = SpinOp([("X_0", 2), ("Y_0", -2j)], register_length=1)
            self.assertSpinEqual(minus, desired)

        with self.subTest("minus"):
            minus = SpinOp([("-", 2)])
            desired = SpinOp([("X_0", 2), ("Y_0", -2j)], register_length=1)
            self.assertSpinEqual(minus, desired)

        with self.subTest("plus tensor minus"):
            plus_tensor_minus = SpinOp([("+_0 -_1", 3)], register_length=2)
            desired = SpinOp(
                [("X_0 X_1", 3), ("Y_0 X_1", 3j), ("X_0 Y_1", -3j),
                 ("Y_0 Y_1", 3)],
                register_length=2,
            )
            self.assertSpinEqual(plus_tensor_minus, desired)

        with self.subTest("dense plus tensor minus"):
            plus_tensor_minus = SpinOp([("+-", 3)])
            desired = SpinOp(
                [("X_0 X_1", 3), ("Y_0 X_1", 3j), ("X_0 Y_1", -3j),
                 ("Y_0 Y_1", 3)],
                register_length=2,
            )
            self.assertSpinEqual(plus_tensor_minus, desired)

    def test_init_heisenberg(self):
        """Test __init__ for Heisenberg model."""
        actual = SpinOp(
            [
                ("XX", -1),
                ("YY", -1),
                ("ZZ", -1),
                ("ZI", -0.3),
                ("IZ", -0.3),
            ],
            spin=1,
        )
        self.assertSpinEqual(actual, self.heisenberg)

    def test_init_multiple_digits(self):
        """Test __init__ for sparse label with multiple digits"""
        actual = SpinOp([("X_10^20", 1 + 2j), ("X_12^34", 56)],
                        Fraction(5, 2),
                        register_length=13)
        desired = [("X_10^20", 1 + 2j), ("X_12^34", 56)]
        self.assertListEqual(actual.to_list(), desired)

    @data("IJX", "Z_0 X_0", "Z_0 +_0", "+_0 X_0")
    def test_init_invalid_label(self, label):
        """Test __init__ for invalid label"""
        with self.assertRaises(ValueError):
            SpinOp(label)

    def test_init_raising_lowering_ops(self):
        """Test __init__ for +_i -_i pattern"""
        with self.subTest("one reg"):
            actual = SpinOp("+_0 -_0", spin=1, register_length=1)
            expected = SpinOp([("X_0^2", 1), ("Y_0^2", 1), ("Z_0", 1)],
                              spin=1,
                              register_length=1)
            self.assertSpinEqual(actual, expected)
        with self.subTest("two reg"):
            actual = SpinOp("+_1 -_1 +_0 -_0", spin=3 / 2, register_length=2)
            expected = SpinOp(
                [
                    ("X_0^2 X_1^2", 1),
                    ("X_0^2 Y_1^2", 1),
                    ("X_0^2 Z_1", 1),
                    ("Y_0^2 X_1^2", 1),
                    ("Y_0^2 Y_1^2", 1),
                    ("Y_0^2 Z_1", 1),
                    ("Z_0 X_1^2", 1),
                    ("Z_0 Y_1^2", 1),
                    ("Z_0 Z_1", 1),
                ],
                spin=3 / 2,
                register_length=2,
            )
            self.assertSpinEqual(actual, expected)

    def test_neg(self):
        """Test __neg__"""
        actual = -self.heisenberg
        desired = SpinOp((self.heisenberg_spin_array, -self.heisenberg_coeffs),
                         spin=1)
        self.assertSpinEqual(actual, desired)

    def test_mul(self):
        """Test __mul__, and __rmul__"""
        actual = self.heisenberg * 2
        desired = SpinOp(
            (self.heisenberg_spin_array, 2 * self.heisenberg_coeffs), spin=1)
        self.assertSpinEqual(actual, desired)

    def test_div(self):
        """Test __truediv__"""
        actual = self.heisenberg / 3
        desired = SpinOp(
            (self.heisenberg_spin_array, self.heisenberg_coeffs / 3), spin=1)
        self.assertSpinEqual(actual, desired)

    def test_add(self):
        """Test __add__"""
        with self.subTest("sum of heisenberg"):
            actual = self.heisenberg + self.heisenberg
            desired = SpinOp(
                (self.heisenberg_spin_array, 2 * self.heisenberg_coeffs),
                spin=1)
            self.assertSpinEqual(actual, desired)

        with self.subTest("raising operator"):
            plus = SpinOp("+", 3 / 2)
            x = SpinOp("X", 3 / 2)
            y = SpinOp("Y", 3 / 2)
            self.assertSpinEqual(x + 1j * y, plus)

    def test_sub(self):
        """Test __sub__"""
        actual = self.heisenberg - self.heisenberg
        self.assertSpinEqual(actual, self.zero_op)

    def test_adjoint(self):
        """Test adjoint method and dagger property"""
        with self.subTest("heisenberg adjoint"):
            actual = self.heisenberg.adjoint()
            desired = SpinOp((self.heisenberg_spin_array,
                              self.heisenberg_coeffs.conjugate().T),
                             spin=1)
            self.assertSpinEqual(actual, desired)

        with self.subTest("imag heisenberg adjoint"):
            actual = ~((3 + 2j) * self.heisenberg)
            desired = SpinOp(
                (self.heisenberg_spin_array,
                 ((3 + 2j) * self.heisenberg_coeffs).conjugate().T),
                spin=1,
            )
            self.assertSpinEqual(actual, desired)

        # TODO: implement adjoint for same register operators.
        # with self.sub Test("adjoint same register op"):
        #     actual = SpinOp("X_0 Y_0 Z_0").dagger

        #     print(actual.to_matrix())
        #     print(SpinOp("X_0 Y_0 Z_0").to_matrix().T.conjugate())

    def test_reduce(self):
        """Test reduce"""
        with self.subTest("trivial reduce"):
            actual = (self.heisenberg - self.heisenberg).reduce()
            self.assertListEqual(actual.to_list(), [("I_1", 0)])

        with self.subTest("nontrivial reduce"):
            test_op = SpinOp(
                (
                    np.array([[[0, 1], [0, 1]], [[0, 0], [0, 0]],
                              [[1, 0], [1, 0]]]),
                    np.array([1.5, 2.5]),
                ),
                spin=3 / 2,
            )
            actual = test_op.reduce()
            self.assertListEqual(actual.to_list(), [("Z_0 X_1", 4)])

        with self.subTest("nontrivial reduce 2"):
            test_op = SpinOp(
                (
                    np.array([
                        [[0, 1], [0, 1], [1, 1]],
                        [[0, 0], [0, 0], [0, 0]],
                        [[1, 0], [1, 0], [0, 0]],
                    ]),
                    np.array([1.5, 2.5, 2]),
                ),
                spin=3 / 2,
            )
            actual = test_op.reduce()
            self.assertListEqual(actual.to_list(), [("Z_0 X_1", 4),
                                                    ("X_0 X_1", 2)])

        with self.subTest("nontrivial reduce 3"):
            test_op = SpinOp([("+_0 -_0", 1)], register_length=4)
            actual = test_op.reduce()
            self.assertListEqual(actual.to_list(), [("Z_0", 1), ("Y_0^2", 1),
                                                    ("X_0^2", 1)])

    @data(*dense_labels(1))
    def test_to_matrix_single_qutrit(self, label):
        """Test to_matrix for single qutrit op"""
        actual = SpinOp(label, 1).to_matrix()
        np.testing.assert_array_almost_equal(actual, self.spin_1_matrix[label])

    @data(*product(dense_labels(1), dense_labels(1)))
    @unpack
    def test_to_matrix_sum_single_qutrit(self, label1, label2):
        """Test to_matrix for sum qutrit op"""
        actual = (SpinOp(label1, 1) + SpinOp(label2, 1)).to_matrix()
        np.testing.assert_array_almost_equal(
            actual, self.spin_1_matrix[label1] + self.spin_1_matrix[label2])

    @data(*dense_labels(2))
    def test_to_matrix_two_qutrit(self, label):
        """Test to_matrix for two qutrit op"""
        actual = SpinOp(label, 1).to_matrix()
        desired = np.kron(self.spin_1_matrix[label[0]],
                          self.spin_1_matrix[label[1]])
        np.testing.assert_array_almost_equal(actual, desired)

    @data(*dense_labels(1), *dense_labels(2), *dense_labels(3))
    def test_consistency_with_pauli(self, label):
        """Test consistency with pauli"""
        actual = SpinOp(label).to_matrix()
        desired = Pauli(label).to_matrix() / (2**(len(label) -
                                                  label.count("I")))
        np.testing.assert_array_almost_equal(actual, desired)

    def test_flatten_ladder_ops(self):
        """Test _flatten_ladder_ops"""
        actual = SpinOp._flatten_ladder_ops([("+-", 2j)])
        self.assertSetEqual(
            frozenset(actual),
            frozenset([("XX", 2j), ("XY", 2), ("YX", -2), ("YY", 2j)]),
        )
Пример #17
0
 def test_to_matrix_two_qutrit(self, label):
     """Test to_matrix for two qutrit op"""
     actual = SpinOp(label, 1).to_matrix()
     desired = np.kron(self.spin_1_matrix[label[0]],
                       self.spin_1_matrix[label[1]])
     np.testing.assert_array_almost_equal(actual, desired)
Пример #18
0
 def test_consistency_with_pauli(self, label):
     """Test consistency with pauli"""
     actual = SpinOp(label).to_matrix()
     desired = Pauli(label).to_matrix() / (2**(len(label) -
                                               label.count("I")))
     np.testing.assert_array_almost_equal(actual, desired)
Пример #19
0
 def test_to_matrix_single_qutrit(self, label):
     """Test to_matrix for single qutrit op"""
     actual = SpinOp(label, 1).to_matrix()
     np.testing.assert_array_almost_equal(actual, self.spin_1_matrix[label])
Пример #20
0
 def test_to_matrix_sum_single_qutrit(self, label1, label2):
     """Test to_matrix for sum qutrit op"""
     actual = (SpinOp(label1, 1) + SpinOp(label2, 1)).to_matrix()
     np.testing.assert_array_almost_equal(
         actual, self.spin_1_matrix[label1] + self.spin_1_matrix[label2])
Пример #21
0
 def test_init_invalid_label(self, label):
     """Test __init__ for invalid label"""
     with self.assertRaises(ValueError):
         SpinOp(label)
Пример #22
0
 def test_init_dense_label(self, labels, pre_processing):
     """Test __init__ for dense label"""
     dense_label, sparse_label = labels
     actual = SpinOp(pre_processing(dense_label))
     desired = SpinOp([(sparse_label, 1)], register_length=len(dense_label))
     self.assertSpinEqual(actual, desired)
Пример #23
0
 def test_div(self):
     """Test __truediv__"""
     actual = self.heisenberg / 3
     desired = SpinOp(
         (self.heisenberg_spin_array, self.heisenberg_coeffs / 3), spin=1)
     self.assertSpinEqual(actual, desired)
Пример #24
0
class TestSpinOp(QiskitNatureTestCase):
    """SpinOp tests."""
    def setUp(self):
        super().setUp()
        self.heisenberg_spin_array = np.array([
            [[1, 1], [0, 0], [0, 0], [0, 0], [0, 0]],
            [[0, 0], [1, 1], [0, 0], [0, 0], [0, 0]],
            [[0, 0], [0, 0], [1, 1], [1, 0], [0, 1]],
        ], )
        self.heisenberg_coeffs = np.array([-1, -1, -1, -0.3, -0.3])
        self.heisenberg = SpinOp(
            (self.heisenberg_spin_array, self.heisenberg_coeffs),
            spin=1,
        )
        self.zero_op = SpinOp(
            (np.array([[[0, 0]], [[0, 0]], [[0, 0]]]), np.array([0])),
            spin=1,
        )
        self.spin_1_matrix = {
            "I": np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]),
            "X": np.array([[0, 1, 0], [1, 0, 1], [0, 1, 0]]) / np.sqrt(2),
            "Y":
            np.array([[0, -1j, 0], [1j, 0, -1j], [0, 1j, 0]]) / np.sqrt(2),
            "Z": np.array([[1, 0, 0], [0, 0, 0], [0, 0, -1]]),
        }

    @staticmethod
    def assertSpinEqual(first: SpinOp, second: SpinOp):
        """Fail if two SpinOps have different matrix representations."""
        np.testing.assert_array_almost_equal(first.to_matrix(),
                                             second.to_matrix())

    @data(*spin_labels(1))
    def test_init_label(self, label):
        """Test __init__"""
        spin = SpinOp(f"{label}_0")
        self.assertListEqual(spin.to_list(), [(f"{label}_0", 1)])

    @data(*spin_labels(2))
    def test_init_len2_label(self, label):
        """Test __init__"""
        spin = SpinOp(f"{label[1]}_1 {label[0]}_0")
        self.assertListEqual(spin.to_list(),
                             [(f"{label[1]}_1 {label[0]}_0", 1)])

    def test_init_pm_label(self):
        """Test __init__ with plus and minus label"""
        with self.subTest("plus"):
            plus = SpinOp([("+_0", 2)])
            desired = SpinOp([("X_0", 2), ("Y_0", 2j)])
            self.assertSpinEqual(plus, desired)

        with self.subTest("dense plus"):
            plus = SpinOp([("+", 2)])
            desired = SpinOp([("X_0", 2), ("Y_0", 2j)])
            self.assertSpinEqual(plus, desired)

        with self.subTest("minus"):
            minus = SpinOp([("-_0", 2)])
            desired = SpinOp([("X_0", 2), ("Y_0", -2j)])
            self.assertSpinEqual(minus, desired)

        with self.subTest("minus"):
            minus = SpinOp([("-", 2)])
            desired = SpinOp([("X_0", 2), ("Y_0", -2j)])
            self.assertSpinEqual(minus, desired)

        with self.subTest("plus tensor minus"):
            plus_tensor_minus = SpinOp([("+_1 -_0", 3)])
            desired = SpinOp([("X_1 X_0", 3), ("X_1 Y_0", -3j),
                              ("Y_1 X_0", 3j), ("Y_1 Y_0", 3)])
            self.assertSpinEqual(plus_tensor_minus, desired)

        with self.subTest("dense plus tensor minus"):
            plus_tensor_minus = SpinOp([("+-", 3)])
            desired = SpinOp([("X_1 X_0", 3), ("X_1 Y_0", -3j),
                              ("Y_1 X_0", 3j), ("Y_1 Y_0", 3)])
            self.assertSpinEqual(plus_tensor_minus, desired)

    def test_init_heisenberg(self):
        """Test __init__ for Heisenberg model."""
        actual = SpinOp(
            [
                ("XX", -1),
                ("YY", -1),
                ("ZZ", -1),
                ("ZI", -0.3),
                ("IZ", -0.3),
            ],
            spin=1,
        )
        self.assertSpinEqual(actual, self.heisenberg)

    @data(*spin_labels(1), *spin_labels(2))
    def test_init_dense_label(self, label):
        """Test __init__ for dense label"""
        if len(label) == 1:
            actual = SpinOp([(f"{label}", 1 + 1j)])
            desired = SpinOp([(f"{label}_0", 1 + 1j)])
        elif len(label) == 2:
            actual = SpinOp([(f"{label}", 1)])
            desired = SpinOp([(f"{label[0]}_1 {label[1]}_0", 1)])
        self.assertSpinEqual(actual, desired)

    @data("IJX", "Z_0 X_0", "Z_0 +_0", "+_0 X_0")
    def test_init_invalid_label(self, label):
        """Test __init__ for invalid label"""
        with self.assertRaises(ValueError):
            SpinOp(label)

    def test_neg(self):
        """Test __neg__"""
        actual = -self.heisenberg
        desired = SpinOp((self.heisenberg_spin_array, -self.heisenberg_coeffs),
                         spin=1)
        self.assertSpinEqual(actual, desired)

    def test_mul(self):
        """Test __mul__, and __rmul__"""
        actual = self.heisenberg * 2
        desired = SpinOp(
            (self.heisenberg_spin_array, 2 * self.heisenberg_coeffs), spin=1)
        self.assertSpinEqual(actual, desired)

    def test_div(self):
        """Test __truediv__"""
        actual = self.heisenberg / 3
        desired = SpinOp(
            (self.heisenberg_spin_array, self.heisenberg_coeffs / 3), spin=1)
        self.assertSpinEqual(actual, desired)

    def test_add(self):
        """Test __add__"""
        with self.subTest("sum of heisenberg"):
            actual = self.heisenberg + self.heisenberg
            desired = SpinOp(
                (self.heisenberg_spin_array, 2 * self.heisenberg_coeffs),
                spin=1)
            self.assertSpinEqual(actual, desired)

        with self.subTest("raising operator"):
            plus = SpinOp("+", 3 / 2)
            x = SpinOp("X", 3 / 2)
            y = SpinOp("Y", 3 / 2)
            self.assertSpinEqual(x + 1j * y, plus)

    def test_sub(self):
        """Test __sub__"""
        actual = self.heisenberg - self.heisenberg
        self.assertSpinEqual(actual, self.zero_op)

    def test_adjoint(self):
        """Test adjoint method and dagger property"""
        with self.subTest("heisenberg adjoint"):
            actual = self.heisenberg.adjoint()
            desired = SpinOp((self.heisenberg_spin_array,
                              self.heisenberg_coeffs.conjugate().T),
                             spin=1)
            self.assertSpinEqual(actual, desired)

        with self.subTest("imag heisenberg adjoint"):
            actual = ~((3 + 2j) * self.heisenberg)
            desired = SpinOp(
                (self.heisenberg_spin_array,
                 ((3 + 2j) * self.heisenberg_coeffs).conjugate().T),
                spin=1,
            )
            self.assertSpinEqual(actual, desired)

        # TODO: implement adjoint for same register operators.
        # with self.sub Test("adjoint same register op"):
        #     actual = SpinOp("X_0 Y_0 Z_0").dagger

        #     print(actual.to_matrix())
        #     print(SpinOp("X_0 Y_0 Z_0").to_matrix().T.conjugate())

    def test_reduce(self):
        """Test reduce"""
        with self.subTest("trivial reduce"):
            actual = (self.heisenberg - self.heisenberg).reduce()
            self.assertListEqual(actual.to_list(), [("I_1 I_0", 0)])

        with self.subTest("nontrivial reduce"):
            test_op = SpinOp(
                (
                    np.array([[[0, 1], [0, 1]], [[0, 0], [0, 0]],
                              [[1, 0], [1, 0]]]),
                    np.array([1.5, 2.5]),
                ),
                spin=3 / 2,
            )
            actual = test_op.reduce()
            self.assertListEqual(actual.to_list(), [("Z_1 X_0", 4)])

        with self.subTest("nontrivial reduce 2"):
            test_op = SpinOp(
                (
                    np.array([
                        [[0, 1], [0, 1], [1, 1]],
                        [[0, 0], [0, 0], [0, 0]],
                        [[1, 0], [1, 0], [0, 0]],
                    ]),
                    np.array([1.5, 2.5, 2]),
                ),
                spin=3 / 2,
            )
            actual = test_op.reduce()
            self.assertListEqual(actual.to_list(), [("Z_1 X_0", 4),
                                                    ("X_1 X_0", 2)])

    @data(*spin_labels(1))
    def test_to_matrix_single_qutrit(self, label):
        """Test to_matrix for single qutrit op"""
        actual = SpinOp(label, 1).to_matrix()
        np.testing.assert_array_almost_equal(actual, self.spin_1_matrix[label])

    @data(*product(spin_labels(1), spin_labels(1)))
    @unpack
    def test_to_matrix_sum_single_qutrit(self, label1, label2):
        """Test to_matrix for sum qutrit op"""
        actual = (SpinOp(label1, 1) + SpinOp(label2, 1)).to_matrix()
        np.testing.assert_array_almost_equal(
            actual, self.spin_1_matrix[label1] + self.spin_1_matrix[label2])

    @data(*spin_labels(2))
    def test_to_matrix_two_qutrit(self, label):
        """Test to_matrix for two qutrit op"""
        actual = SpinOp(label, 1).to_matrix()
        desired = np.kron(self.spin_1_matrix[label[0]],
                          self.spin_1_matrix[label[1]])
        np.testing.assert_array_almost_equal(actual, desired)

    @data(*spin_labels(1), *spin_labels(2), *spin_labels(3))
    def test_consistency_with_pauli(self, label):
        """Test consistency with pauli"""
        actual = SpinOp(label).to_matrix()
        desired = Pauli(label).to_matrix() / (2**(len(label) -
                                                  label.count("I")))
        np.testing.assert_array_almost_equal(actual, desired)

    def test_flatten_ladder_ops(self):
        """Test _flatten_ladder_ops"""
        actual = SpinOp._flatten_ladder_ops([("+-", 2j)])
        self.assertSetEqual(
            frozenset(actual),
            frozenset([("XX", 2j), ("XY", 2), ("YX", -2), ("YY", 2j)]),
        )
Пример #25
0
 def test_neg(self):
     """Test __neg__"""
     actual = -self.heisenberg
     desired = SpinOp((self.heisenberg_spin_array, -self.heisenberg_coeffs),
                      spin=1)
     self.assertSpinEqual(actual, desired)