Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: do not use normal_order as part of commutator methods #1299

Merged
merged 2 commits into from
Dec 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions qiskit_nature/second_q/operators/commutators.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@ def commutator(op_a: SparseLabelOp, op_b: SparseLabelOp) -> SparseLabelOp:
op_b: Operator B.

Returns:
The computed commutator.
The computed commutator. If available for your kind of operator, you may want to
``normal_order()`` it.
"""
return (op_a @ op_b - op_b @ op_a).normal_order().simplify(atol=0)
return (op_a @ op_b - op_b @ op_a).simplify(atol=0)


def anti_commutator(op_a: SparseLabelOp, op_b: SparseLabelOp) -> SparseLabelOp:
Expand All @@ -59,9 +60,10 @@ def anti_commutator(op_a: SparseLabelOp, op_b: SparseLabelOp) -> SparseLabelOp:
op_b: Operator B.

Returns:
The computed anti-commutator.
The computed anti--commutator. If available for your kind of operator, you may want to
``normal_order()`` it.
"""
return (op_a @ op_b + op_b @ op_a).normal_order().simplify(atol=0)
return (op_a @ op_b + op_b @ op_a).simplify(atol=0)


def double_commutator(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
fixes:
- |
The commutator methods were faultily trying to call ``normal_order()`` on
their operands, which are not guaranteed to have this method. Now, they no
longer call this method and instead it is up to the user to normal-order the
result as needed.
6 changes: 3 additions & 3 deletions test/second_q/operators/test_bosonic_op.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,15 +246,15 @@ def test_commutator(self):
with self.subTest("commutator same index"):
bos_op = commutator(BosonicOp({"-_0": 1}), BosonicOp({"+_0": 1}))
targ = BosonicOp({"": 1})
self.assertEqual(bos_op, targ)
self.assertEqual(bos_op.normal_order(), targ)
with self.subTest("commutator same index reversed"):
bos_op = commutator(BosonicOp({"+_0": 1}), BosonicOp({"-_0": 1}))
targ = BosonicOp({"": -1})
self.assertEqual(bos_op, targ)
self.assertEqual(bos_op.normal_order(), targ)
with self.subTest("commutator same different indices"):
bos_op = commutator(BosonicOp({"+_0": 1}), BosonicOp({"-_1": 1}))
targ = BosonicOp({}) # 0
self.assertEqual(bos_op, targ)
self.assertEqual(bos_op.normal_order(), targ)

def test_compose(self):
"""Test operator composition
Expand Down
2 changes: 1 addition & 1 deletion test/second_q/operators/test_commutators.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class TestCommutators(QiskitNatureTestCase):
@unpack
@data(
(op1, op2, {}),
(op4, op5, {"+_0 -_0": (2 + 0j), "": (-1 + 0j)}),
(op4, op5, {"+_0 -_0": (1 + 0j), "-_0 +_0": (-1 + 0j)}),
)
def test_commutator(self, op_a: FermionicOp, op_b: FermionicOp, expected: dict):
"""Test commutator method"""
Expand Down
12 changes: 6 additions & 6 deletions test/second_q/properties/test_s_operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,39 +74,39 @@ def test_commutator_xyz(self) -> None:
s_x = s_x_operator(4)
s_y = s_y_operator(4)
s_z = s_z_operator(4)
self.assertEqual(commutator(s_x, s_y), 1j * s_z)
self.assertEqual(commutator(s_x, s_y).normal_order(), 1j * s_z)

def test_commutator_yzx(self) -> None:
"""Tests that :math:`[S^y, S^z] = 1j * S^x`."""
s_x = s_x_operator(4)
s_y = s_y_operator(4)
s_z = s_z_operator(4)
self.assertEqual(commutator(s_y, s_z), 1j * s_x)
self.assertEqual(commutator(s_y, s_z).normal_order(), 1j * s_x)

def test_commutator_zxy(self) -> None:
"""Tests that :math:`[S^z, S^x] = 1j * S^y`."""
s_x = s_x_operator(4)
s_y = s_y_operator(4)
s_z = s_z_operator(4)
self.assertEqual(commutator(s_z, s_x), 1j * s_y)
self.assertEqual(commutator(s_z, s_x).normal_order(), 1j * s_y)

def test_commutator_s2x(self) -> None:
"""Tests that :math:`[S^2, S^x] = 0`."""
s_x = s_x_operator(4)
s_2 = AngularMomentum(4).second_q_ops()["AngularMomentum"]
self.assertEqual(commutator(s_2, s_x), FermionicOp.zero())
self.assertEqual(commutator(s_2, s_x).normal_order(), FermionicOp.zero())

def test_commutator_s2y(self) -> None:
"""Tests that :math:`[S^2, S^y] = 0`."""
s_y = s_y_operator(4)
s_2 = AngularMomentum(4).second_q_ops()["AngularMomentum"]
self.assertEqual(commutator(s_2, s_y), FermionicOp.zero())
self.assertEqual(commutator(s_2, s_y).normal_order(), FermionicOp.zero())

def test_commutator_s2z(self) -> None:
"""Tests that :math:`[S^2, S^z] = 0`."""
s_z = s_z_operator(4)
s_2 = AngularMomentum(4).second_q_ops()["AngularMomentum"]
self.assertEqual(commutator(s_2, s_z), FermionicOp.zero())
self.assertEqual(commutator(s_2, s_z).normal_order(), FermionicOp.zero())


class TestSOperatorsWithOverlap(QiskitNatureTestCase):
Expand Down