# This code is part of Qiskit.
# (C) Copyright IBM 2023.
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
"""Double commutator function."""
from __future__ import annotations
from typing import TypeVar
from qiskit.quantum_info.operators.linear_op import LinearOp
OperatorTypeT = TypeVar("OperatorTypeT", bound=LinearOp)
a: OperatorTypeT, b: OperatorTypeT, c: OperatorTypeT, *, commutator: bool = True
) -> OperatorTypeT:
r"""Compute symmetric double commutator of a, b and c.
See also Equation (13.6.18) in .
If `commutator` is `True`, it returns
[[A, B], C]/2 + [A, [B, C]]/2
= (2ABC + 2CBA - BAC - CAB - ACB - BCA)/2.
If `commutator` is `False`, it returns
\lbrace[A, B], C\rbrace/2 + \lbrace A, [B, C]\rbrace/2
= (2ABC - 2CBA - BAC + CAB - ACB + BCA)/2.
a: Operator a.
b: Operator b.
c: Operator c.
commutator: If ``True`` compute the double commutator,
if ``False`` the double anti-commutator.
The double commutator
: R. McWeeny.
Methods of Molecular Quantum Mechanics.
2nd Edition, Academic Press, 1992.
sign_num = -1 if commutator else 1
ab = a @ b
ba = b @ a
ac = a @ c
ca = c @ a
abc = ab @ c
cba = c @ ba
bac = ba @ c
cab = c @ ab
acb = ac @ b
bca = b @ ca
res = abc - sign_num * cba + 0.5 * (-bac + sign_num * cab - acb + sign_num * bca)