Repository: quantumlib/OpenFermion
Pull request #527 (2019-07-10 21:20:55)

Upgrade tapering qubit function
We update the tapering qubits using stabilizer function to deal with cases where the stabilizers have larger weight than the Hamiltonian.

In principle, this will be useful to study subgroups of Pauli strings belonging to a larger Hamiltonian.

Additionally, I added myself in the author list after an email from @babbush to @msteudtner. I followed the alphabetic order.

Best,
Xavi and Mark


Patch:
diff --git a/NOTICE b/NOTICE
index d5728be..77f08f7 100644
--- a/NOTICE
+++ b/NOTICE
@@ -7,6 +7,7 @@ Kevin J. Sung (University of Michigan)
 Ian Kivlichan (Harvard)
 
 Dave Bacon (Google)
+Xavier Bonet-Monroig (Leiden University)
 Yudong Cao (Harvard)
 Chengyu Dai (University of Michigan)
 E. Schuyler Fried (Harvard)
diff --git a/README.rst b/README.rst
index b27c9cf..30c57cd 100644
--- a/README.rst
+++ b/README.rst
@@ -132,6 +132,7 @@ Authors
 `Kevin Sung <https://github.com/kevinsung>`__ (University of Michigan),
 `Ian Kivlichan <http://aspuru.chem.harvard.edu/ian-kivlichan/>`__ (Harvard),
 `Dave Bacon <https://github.com/dabacon>`__ (Google),
+`Xavier Bonet-Monroig <https://github.com/xabomon>`__  (Leiden University),
 `Yudong Cao <https://github.com/yudongcao>`__ (Harvard),
 `Chengyu Dai <https://github.com/jdaaph>`__ (University of Michigan),
 `E. Schuyler Fried <https://github.com/schuylerfried>`__ (Harvard),
@@ -171,7 +172,7 @@ How to cite
 ===========
 When using OpenFermion for research projects, please cite:
 
-    Jarrod R. McClean, Kevin J. Sung, Ian D. Kivlichan, Yudong Cao,
+    Jarrod R. McClean, Kevin J. Sung, Ian D. Kivlichan, Xavier Bonet-Monroig, Yudong Cao,
     Chengyu Dai, E. Schuyler Fried, Craig Gidney, Brendan Gimby,
     Pranav Gokhale, Thomas Häner, Tarini Hardikar, Vojtĕch Havlíček,
     Oscar Higgott, Cupjin Huang, Josh Izaac, Zhang Jiang, William Kirby, Xinle Liu,
diff --git a/src/openfermion/utils/_qubit_tapering_from_stabilizer.py b/src/openfermion/utils/_qubit_tapering_from_stabilizer.py
index 261c58e..d48a6a9 100644
--- a/src/openfermion/utils/_qubit_tapering_from_stabilizer.py
+++ b/src/openfermion/utils/_qubit_tapering_from_stabilizer.py
@@ -451,7 +451,16 @@ def taper_off_qubits(operator, stabilizers, manual_input=False,
                                   the remaining qubits have been moved up to
                                   those indices.
     """
-    n_qbits = count_qubits(operator)
+    if isinstance(stabilizers, (list, tuple, numpy.ndarray)):
+        n_qbits_stabs = 0
+        for ent in stabilizers:
+            if count_qubits(ent) > n_qbits_stabs:
+                n_qbits_stabs = count_qubits(ent)
+    else:
+        n_qbits_stabs = count_qubits(stabilizers)
+
+    n_qbits = max(count_qubits(operator), n_qbits_stabs)
+
     (ham_to_update,
      qbts_to_rm) = reduce_number_of_terms(operator,
                                           stabilizers,


Test patch:
diff --git a/src/openfermion/utils/_qubit_tapering_from_stabilizer_test.py b/src/openfermion/utils/_qubit_tapering_from_stabilizer_test.py
index 90c0da4..00600e4 100644
--- a/src/openfermion/utils/_qubit_tapering_from_stabilizer_test.py
+++ b/src/openfermion/utils/_qubit_tapering_from_stabilizer_test.py
@@ -19,7 +19,7 @@ import numpy
 from openfermion.hamiltonians import MolecularData
 from openfermion.ops import QubitOperator
 from openfermion.transforms import jordan_wigner, get_fermion_operator
-from openfermion.utils import eigenspectrum
+from openfermion.utils import eigenspectrum, count_qubits
 
 from openfermion.utils import reduce_number_of_terms, taper_off_qubits
 from openfermion.utils._qubit_tapering_from_stabilizer import (
@@ -331,7 +331,20 @@ class TaperingTest(unittest.TestCase):
                                        manual_input=True,
                                        fixed_positions=[0, 3],
                                        output_tapered_positions=True)
+
         tapered_spectrum = eigenspectrum(tapered_hamiltonian)
 
         self.assertAlmostEqual(spectrum[0], tapered_spectrum[0])
         self.assertEqual(positions, [0, 3])
+
+    def test_tappering_stabilizer_more_qubits(self):
+        """Test for stabilizer with more qubits than operator."""
+        hamiltonian = QubitOperator('Y0 Y1', 1.0)
+        stab = QubitOperator('X0 X1 X2', -1.0)
+
+        num_qubits = max(count_qubits(hamiltonian),
+                         count_qubits(stab))
+        tap_ham = taper_off_qubits(hamiltonian, stab)
+        num_qubits_tap = count_qubits(tap_ham)
+
+        self.assertFalse(num_qubits == num_qubits_tap)