Repository: Qiskit/qiskit

Issue:
SuzukiTrotter class should not accept odd orders
### Environment

- **Qiskit Terra version**: 
- **Python version**: 
- **Operating system**: 
It applies to all environments.

### What is happening?

The SuzukiTrotter class in `qiskit.synthesis.evolution` currently accepts any integer as input for the order. However the formula is not defined for odd orders (see definition below) and even though the code works on such input, the results do not make sense when the order is odd. 
![image](https://user-images.githubusercontent.com/5624856/142388673-acc5c6ce-1073-4103-9227-86d4fc79a63e.png)


### How can we reproduce the issue?

```python
from qiskit.opflow import X, Y
from qiskit.circuit.library import PauliEvolutionGate
from qiskit.synthesis import SuzukiTrotter
op = X + Y
time = 0.1
reps = 1
evo_gate = PauliEvolutionGate(op, time, synthesis=SuzukiTrotter(order=1, reps=reps))
```

### What should happen?

It should raise an error message and do not accept odd integers as input for the order.

### Any suggestions?

_No response_


Discussion:
An order of 1 would still make sense I think as that's just the Lie-Trotter formula 🙂 Do you have an example of why the results are weird for other odd higher orders?
At the moment an order `1` would only give the right answer if `time=1`, because the coefficients in `pauli_list` are never multiplied by time.
```python
@staticmethod
    def _recurse(order, time, pauli_list):
        if order < 1:
            raise ValueError(
                "The given order of the Trotterization was "
                + str(order)
                + " but it should be an integer number at least "
                "1."
            )

        if order == 1:
            return pauli_list

        elif order == 2:
            halves = [(op, coeff * time / 2) for op, coeff in pauli_list[:-1]]
            full = [(pauli_list[-1][0], time * pauli_list[-1][1])]
            return halves + full + list(reversed(halves))

        else:
            reduction = 1 / (4 - 4 ** (1 / (order - 1)))
            outer = 2 * SuzukiTrotter._recurse(
                order - 2, time=reduction * time, pauli_list=pauli_list
            )
            inner = SuzukiTrotter._recurse(
                order - 2, time=(1 - 4 * reduction) * time, pauli_list=pauli_list
            )
            return outer + inner + outer
```
These formulas are symmetric, which means that they do not have odd order errors. I could add an example where it does not converge as you increase the number of Trotter steps but intuitively the formulas are defined so that you cancel these odd error terms by combining symmetrically to 2n-order product formulas. And that allows you to jump to the 2n+2 order.

Resolving patch:
diff --git a/qiskit/synthesis/evolution/suzuki_trotter.py b/qiskit/synthesis/evolution/suzuki_trotter.py
--- a/qiskit/synthesis/evolution/suzuki_trotter.py
+++ b/qiskit/synthesis/evolution/suzuki_trotter.py
@@ -13,7 +13,10 @@
 """The Suzuki-Trotter product formula."""
 
 from typing import Callable, Optional, Union
+
+import warnings
 import numpy as np
+
 from qiskit.circuit.quantumcircuit import QuantumCircuit
 from qiskit.quantum_info.operators import SparsePauliOp, Pauli
 
@@ -61,12 +64,24 @@ def __init__(
             reps: The number of time steps.
             insert_barriers: Whether to insert barriers between the atomic evolutions.
             cx_structure: How to arrange the CX gates for the Pauli evolutions, can be "chain",
-                where next neighbor connections are used, or "fountain", where all qubits are connected
-                to one.
+                where next neighbor connections are used, or "fountain", where all qubits are
+                connected to one.
             atomic_evolution: A function to construct the circuit for the evolution of single
                 Pauli string. Per default, a single Pauli evolution is decomopsed in a CX chain
                 and a single qubit Z rotation.
         """
+        if order % 2 == 1:
+            warnings.warn(
+                "SuzukiTrotter for odd orders is deprecated as of 0.20.0, and will be "
+                "removed no earlier than 3 months after that release date. Suzuki "
+                "product formulae are symmetric and therefore only defined for even"
+                "orders.",
+                DeprecationWarning,
+                stacklevel=2,
+            )
+            # TODO replace deprecation warning by the following error and add unit test for odd
+            # raise ValueError("Suzuki product formulae are symmetric and therefore only defined "
+            #                  "for even orders.")
         super().__init__(order, reps, insert_barriers, cx_structure, atomic_evolution)
 
     def synthesize(self, evolution):


Test patch:
diff --git a/test/python/circuit/library/test_evolution_gate.py b/test/python/circuit/library/test_evolution_gate.py
--- a/test/python/circuit/library/test_evolution_gate.py
+++ b/test/python/circuit/library/test_evolution_gate.py
@@ -76,7 +76,7 @@ def test_suzuki_trotter(self):
         op = (X ^ 3) + (Y ^ 3) + (Z ^ 3)
         time = 0.123
         reps = 4
-        for order in [2, 4, 5]:
+        for order in [2, 4, 6]:
             if order == 2:
                 expected_cx = reps * 5 * 4
             elif order % 2 == 0: