Repository: Qiskit/qiskit-terra (python)

Issue:
Grover's Migration from Aqua to Qiskit Terra
<!-- ⚠️ If you do not respect this template, your issue will be closed -->
<!-- ⚠️ Make sure to browse the opened and closed issues -->

### Informations

- **Qiskit version**: 0.26.0
- **Python version**: 3.8
- **Operating system**: MacOS

### What is the current behavior?

Grover's algorithm does not behave as expected, at least does not take previously known as "Logical Expression" (now PhaseOracle) alphabetically. It runs fine in Aqua but not in Qiskit circuit library.

### Steps to reproduce the problem

```python
from qiskit import *
from qiskit.tools.visualization import plot_histogram
from qiskit.circuit.library import PhaseOracle
from qiskit.algorithms import Grover, AmplificationProblem

oracle = PhaseOracle('((A & C) | (B & D)) & ~(C & D)')
problem = AmplificationProblem(oracle=oracle, is_good_state=oracle.evaluate_bitstring)
backend = Aer.get_backend('qasm_simulator')
grover = Grover(quantum_instance=backend)
result = grover.amplify(problem)
print(result.circuit_results[0])
```

### What is the expected behavior?

It shouldn't give 1100 as a suggestion, since we declare C&D as not expression in PhaseOracle. 

However it gives:

{'1101': 255, '0011': 260, '1100': 260, '0111': 249}

In Aqua it gives (this is the expected behaviour):

{'0101': 261, '0111': 236, '1011': 262, '1010': 265}

### Suggested solutions

There should be something wrong in PhaseOracle implementation, please consider LogicalExpression library when you try to solve this to make it alphabetically ordered correctly.


Pull request:
PhaseOracle and BooleanExpression allow setting the expression variable order
<!--
⚠️ If you do not respect this template, your pull request will be closed.
⚠️ Your pull request title should be short detailed and understandable for all.
⚠️ Also, please add a release note file using reno if the change needs to be
  documented in the release notes.
⚠️ If your pull request fixes an open issue, please link to the issue.

- [ ] I have added the tests to cover my changes.
- [ ] I have updated the documentation accordingly.
- [ ] I have read the CONTRIBUTING document.
-->

### Summary
This PR add the ability for users to define the variable order when defining a
`PhaseOracle`.  This closes #6499. It depends on #6588.

```python
from qiskit import *
from qiskit.tools.visualization import plot_histogram
from qiskit.circuit.library import PhaseOracle
from qiskit.algorithms import Grover, AmplificationProblem

oracle = PhaseOracle('((A & C) | (B & D)) & ~(C & D)', var_order=['A', 'B', 'C', 'D'])
problem = AmplificationProblem(oracle=oracle, is_good_state=oracle.evaluate_bitstring)
backend = Aer.get_backend('qasm_simulator')
grover = Grover(quantum_instance=backend)
result = grover.amplify(problem)
print(result.circuit_results[0])
```

The result is `{'0101': 237, '1010': 271, '1011': 276, '0111': 240}`

### Details and comments
The default behaviour is to order variables by appearance in the expression.

Which prints the result: `{'0011': 266, '1101': 264, '1100': 241, '0111': 253}`



Patch:
diff --git a/qiskit/circuit/classicalfunction/boolean_expression.py b/qiskit/circuit/classicalfunction/boolean_expression.py
index 8ac4c8356..7a66f2a20 100644
--- a/qiskit/circuit/classicalfunction/boolean_expression.py
+++ b/qiskit/circuit/classicalfunction/boolean_expression.py
@@ -25,15 +25,19 @@ from .classical_element import ClassicalElement
 class BooleanExpression(ClassicalElement):
     """The Boolean Expression gate."""
 
-    def __init__(self, expression: str, name: str = None) -> None:
+    def __init__(self, expression: str, name: str = None, var_order: list = None) -> None:
         """
         Args:
             expression (str): The logical expression string.
-            name (str): Optional. Instruction gate name. Otherwise part of
-                        the expression is going to be used.
+            name (str): Optional. Instruction gate name. Otherwise part of the expression is
+               going to be used.
+            var_order(list): A list with the order in which variables will be created.
+               (default: by appearance)
         """
 
-        self._tweedledum_bool_expression = BoolFunction.from_expression(expression)
+        self._tweedledum_bool_expression = BoolFunction.from_expression(
+            expression, var_order=var_order
+        )
 
         short_expr_for_name = (expression[:10] + "...") if len(expression) > 13 else expression
         num_qubits = (
diff --git a/qiskit/circuit/library/phase_oracle.py b/qiskit/circuit/library/phase_oracle.py
index 699eddacb..f00a8d562 100644
--- a/qiskit/circuit/library/phase_oracle.py
+++ b/qiskit/circuit/library/phase_oracle.py
@@ -52,6 +52,7 @@ class PhaseOracle(QuantumCircuit):
         self,
         expression: Union[str, ClassicalElement],
         synthesizer: Optional[Callable[[BooleanExpression], QuantumCircuit]] = None,
+        var_order: list = None,
     ) -> None:
         """Creates a PhaseOracle object
 
@@ -59,12 +60,14 @@ class PhaseOracle(QuantumCircuit):
             expression: A Python-like boolean expression.
             synthesizer: Optional. A function to convert a BooleanExpression into a QuantumCircuit
                If None is provided, Tweedledum's `pkrm_synth` with `phase_esop` will be used.
+            var_order(list): A list with the order in which variables will be created.
+               (default: by appearance)
         """
         from qiskit.circuit.classicalfunction.boolean_expression import BooleanExpression
         from qiskit.circuit.classicalfunction.classical_element import ClassicalElement
 
         if not isinstance(expression, ClassicalElement):
-            expression = BooleanExpression(expression)
+            expression = BooleanExpression(expression, var_order=var_order)
 
         self.boolean_expression = expression
 
diff --git a/releasenotes/notes/expression-var-order-d87e9b04fb5d545c.yaml b/releasenotes/notes/expression-var-order-d87e9b04fb5d545c.yaml
new file mode 100644
index 000000000..24f5b47da
--- /dev/null
+++ b/releasenotes/notes/expression-var-order-d87e9b04fb5d545c.yaml
@@ -0,0 +1,18 @@
+---
+features:
+  - |
+    Add the parameter `var_order` when defining a `PhaseOracle`. This allows for defining the order in which the variables in the logical expression are being considered.
+
+    .. code-block::python
+
+        from qiskit import *
+        from qiskit.tools.visualization import plot_histogram
+        from qiskit.circuit.library import PhaseOracle
+        from qiskit.algorithms import Grover, AmplificationProblem
+
+        oracle = PhaseOracle('((A & C) | (B & D)) & ~(C & D)', var_order=['A', 'B', 'C', 'D'])
+        problem = AmplificationProblem(oracle=oracle, is_good_state=oracle.evaluate_bitstring)
+        backend = Aer.get_backend('qasm_simulator')
+        grover = Grover(quantum_instance=backend)
+        result = grover.amplify(problem)
+        print(result.circuit_results[0])


Test patch:
diff --git a/test/python/circuit/library/test_phase_oracle.py b/test/python/circuit/library/test_phase_oracle.py
index 825a8c00a..e15d6df8e 100644
--- a/test/python/circuit/library/test_phase_oracle.py
+++ b/test/python/circuit/library/test_phase_oracle.py
@@ -69,6 +69,32 @@ class TestPhaseOracle(QiskitTestCase):
         self.assertListEqual(expected_valid, result_valid)
         self.assertListEqual(expected_invalid, result_invalid)
 
+    @data(
+        ("((A & C) | (B & D)) & ~(C & D)", None, [3, 7, 12, 13]),
+        ("((A & C) | (B & D)) & ~(C & D)", ["A", "B", "C", "D"], [5, 7, 10, 11]),
+    )
+    @unpack
+    def test_variable_order(self, expression, var_order, good_states):
+        """Circuit generation"""
+        oracle = PhaseOracle(expression, var_order=var_order)
+        num_qubits = oracle.num_qubits
+        circuit = QuantumCircuit(num_qubits)
+        circuit.h(range(num_qubits))
+        circuit.compose(oracle, inplace=True)
+        statevector = Statevector.from_instruction(circuit)
+
+        valid_state = -1 / sqrt(2**num_qubits)
+        invalid_state = 1 / sqrt(2**num_qubits)
+
+        states = list(range(2**num_qubits))
+        expected_valid = [state in good_states for state in states]
+        result_valid = [isclose(statevector.data[state], valid_state) for state in states]
+
+        expected_invalid = [state not in good_states for state in states]
+        result_invalid = [isclose(statevector.data[state], invalid_state) for state in states]
+        self.assertListEqual(expected_valid, result_valid)
+        self.assertListEqual(expected_invalid, result_invalid)
+
 
 if __name__ == "__main__":
     unittest.main()