Repository: quantumlib/OpenFermion
Pull request #519 (2019-05-20 23:03:52)

Implement Jordan-Wigner Transform for MajoranaOperator


Patch:
diff --git a/src/openfermion/transforms/_jordan_wigner.py b/src/openfermion/transforms/_jordan_wigner.py
index ceb208d..9592f6b 100644
--- a/src/openfermion/transforms/_jordan_wigner.py
+++ b/src/openfermion/transforms/_jordan_wigner.py
@@ -16,7 +16,8 @@ import itertools
 import numpy
 
 from openfermion.ops import (DiagonalCoulombHamiltonian, FermionOperator,
-                             InteractionOperator, QubitOperator)
+                             InteractionOperator, MajoranaOperator,
+                             QubitOperator)
 from openfermion.utils import count_qubits
 
 
@@ -40,22 +41,25 @@ def jordan_wigner(operator):
         TypeError: Operator must be a FermionOperator,
             DiagonalCoulombHamiltonian, or InteractionOperator.
     """
-    if isinstance(operator, InteractionOperator):
-        return jordan_wigner_interaction_op(operator)
+    if isinstance(operator, FermionOperator):
+        return jordan_wigner_fermion_operator(operator)
+    if isinstance(operator, MajoranaOperator):
+        return jordan_wigner_majorana_operator(operator)
     if isinstance(operator, DiagonalCoulombHamiltonian):
         return jordan_wigner_diagonal_coulomb_hamiltonian(operator)
+    if isinstance(operator, InteractionOperator):
+        return jordan_wigner_interaction_op(operator)
+    raise TypeError("Operator must be a FermionOperator, "
+                    "MajoranaOperator, "
+                    "DiagonalCoulombHamiltonian, or "
+                    "InteractionOperator.")
 
-    if not isinstance(operator, FermionOperator):
-        raise TypeError("Operator must be a FermionOperator, "
-                        "DiagonalCoulombHamiltonian, or "
-                        "InteractionOperator.")
 
+def jordan_wigner_fermion_operator(operator):
     transformed_operator = QubitOperator()
     for term in operator.terms:
-
         # Initialize identity matrix.
         transformed_term = QubitOperator((), operator.terms[term])
-
         # Loop through operators, transform and multiply.
         for ladder_operator in term:
             z_factors = tuple((index, 'Z') for
@@ -70,7 +74,19 @@ def jordan_wigner(operator):
                     z_factors + ((ladder_operator[0], 'Y'),), 0.5j)
             transformed_term *= pauli_x_component + pauli_y_component
         transformed_operator += transformed_term
+    return transformed_operator
+
 
+def jordan_wigner_majorana_operator(operator):
+    transformed_operator = QubitOperator()
+    for term, coeff in operator.terms.items():
+        transformed_term = QubitOperator((), coeff)
+        for majorana_index in term:
+            q, b = divmod(majorana_index, 2)
+            z_string = tuple((i, 'Z') for i in range(q))
+            bit_flip_op = 'Y' if b else 'X'
+            transformed_term *= QubitOperator(z_string + ((q, bit_flip_op),))
+        transformed_operator += transformed_term
     return transformed_operator
 
 


Test patch:
diff --git a/src/openfermion/transforms/_jordan_wigner_test.py b/src/openfermion/transforms/_jordan_wigner_test.py
index 079c132..977c58e 100644
--- a/src/openfermion/transforms/_jordan_wigner_test.py
+++ b/src/openfermion/transforms/_jordan_wigner_test.py
@@ -21,6 +21,7 @@ from openfermion.config import DATA_DIRECTORY
 from openfermion.hamiltonians import MolecularData, fermi_hubbard
 from openfermion.ops import (FermionOperator,
                              InteractionOperator,
+                             MajoranaOperator,
                              QubitOperator)
 from openfermion.transforms import (get_diagonal_coulomb_hamiltonian,
                                     get_fermion_operator,
@@ -404,3 +405,10 @@ class JordanWignerDiagonalCoulombHamiltonianTest(unittest.TestCase):
         self.assertTrue(
                 jordan_wigner(ferm_op) ==
                 jordan_wigner(get_diagonal_coulomb_hamiltonian(ferm_op)))
+
+
+def test_jordan_wigner_majorana_op_consistent():
+    op = (MajoranaOperator((1, 3, 4), 0.5)
+          + MajoranaOperator((3, 7, 8, 9, 10, 12), 1.8)
+          + MajoranaOperator((0, 4)))
+    assert jordan_wigner(op) == jordan_wigner(get_fermion_operator(op))