Repository: Qiskit/qiskit

Issue:
Barrier instruction ignores number of qubits when passed qubit operands as set
### Environment

- **Qiskit Terra version**: 0.45
- **Python version**: 3.9.*
- **Operating system**: Linux



### What is happening?

When a circuit is created with integer qubit operands and a barrier is applied with those operands as a set the barrier instruction is created for a single qubit operand.

### How can we reproduce the issue?

```python
from qiskit import QuantumCircuit
qc = QuantumCircuit(2)
qc.barrier({0, 1})
print(qc.data)
```
gives
```
>>> [CircuitInstruction(operation=Instruction(name='barrier', num_qubits=1, num_clbits=0, params=[]), qubits=(Qubit(QuantumRegister(2, 'q'), 0), Qubit(QuantumRegister(2, 'q'), 1)), clbits=())]
```

### What should happen?

I would expect (and the behaviour was this way in 0.44)

```
>>> [CircuitInstruction(operation=Instruction(name='barrier', num_qubits=2, num_clbits=0, params=[]), qubits=(Qubit(QuantumRegister(2, 'q'), 0), Qubit(QuantumRegister(2, 'q'), 1)), clbits=())]
```

Passing a list gives the expected behaviour
```python
qc.barrier([0, 1])
```
### Any suggestions?

_No response_


Discussion:
Not denying that this probably should work, but are you sure this was working in previous versions of Qiskit?  I can't see any way it could have, given that the definition of `QuantumCircuit.barrier` hasn't changed for years, and that's where the bug is.

*edit*: fwiw, the bug as presented is still present at least as far back as Terra 0.20.0, about two years ago.
It's showing up in the code failing after upgrading to qiskit 0.45. It's possibly caused by a secondary interaction but casting to a list before calling resolves the failure that is working prior to the release (and I manually triggered it by upgrading my local qiskit version).
What you're presenting is definitely a problem, but I don't think it can be the differential cause of what you're seeing, because this behaviour was in Qiskit 0.44 (and many versions before) as well - the reproducer in your top comment has the exact same behaviour with Qiskit 0.44 as with 0.45.

We did have #11113, which if you're seeing new behaviour with `Barrier` is likely related, but the particular behaviour in the reproducer at the top wasn't changed by that, which is why I'm mentioning it - fixing this bug might not be the root cause of what you're seeing.
Its worth mentioning that the bug came up during the traversal of a circuit with compose. Something like
```python
    for inst, qargs, cargs in qc.data:
            new_circ.compose(inst, qargs, cargs, inplace=True)
```
So its possible the behaviour of compose or the broadcasting above has changed and is interacting poorly with this issue.
Ah, right right - so the circuit is _initially_ constructed with `QuantumCircuit.barrier({0, 1})`, and then when later it's iterated through with `compose` like this (which actually looks like it means `append`, but that's not important right now), the `compose` call throws an error?

If so, that's entirely possible, and it's actually _good_ behaviour; we're finally detecting this years-old bug in `QuantumCircuit.barrier`.  Before #11113, the `compose` would silently duplicate the bugged-out circuit (`qc` in your latest code block), but now it's detecting it and complaining.

The other good news from that is that fixing this bug as reported should solve your problem, despite this particular code not having changed in 0.45. All circuits generated using the code you've mentioned before now were buggy (including `qc` and `new_circ`) and it's been silently ignored.  Fortunately, I don't think it will have had any effect on anything - the `Instruction.num_qubits` field is never really inspected other than during the append.
Great, thank you Jake 😄. For others that encounter this bug in the meantime, I was able to resolve it by first casting to a list, eg.,
```python
list_qubits = list(set_qubits)
qc.barrier(list_qubits)
```
@hunterkemeny: would you be able to take a look at this?

Resolving patch:
diff --git a/qiskit/circuit/quantumcircuit.py b/qiskit/circuit/quantumcircuit.py
--- a/qiskit/circuit/quantumcircuit.py
+++ b/qiskit/circuit/quantumcircuit.py
@@ -2852,23 +2852,12 @@ def barrier(self, *qargs: QubitSpecifier, label=None) -> InstructionSet:
         """
         from .barrier import Barrier
 
-        qubits: list[QubitSpecifier] = []
-
-        if not qargs:  # None
-            qubits.extend(self.qubits)
-
-        for qarg in qargs:
-            if isinstance(qarg, QuantumRegister):
-                qubits.extend([qarg[j] for j in range(qarg.size)])
-            elif isinstance(qarg, list):
-                qubits.extend(qarg)
-            elif isinstance(qarg, range):
-                qubits.extend(list(qarg))
-            elif isinstance(qarg, slice):
-                qubits.extend(self.qubits[qarg])
-            else:
-                qubits.append(qarg)
-
+        qubits = (
+            # This uses a `dict` not a `set` to guarantee a deterministic order to the arguments.
+            list({q: None for qarg in qargs for q in self.qbit_argument_conversion(qarg)})
+            if qargs
+            else self.qubits.copy()
+        )
         return self.append(Barrier(len(qubits), label=label), qubits, [])
 
     def delay(


Test patch:
diff --git a/test/python/circuit/test_circuit_operations.py b/test/python/circuit/test_circuit_operations.py
--- a/test/python/circuit/test_circuit_operations.py
+++ b/test/python/circuit/test_circuit_operations.py
@@ -420,6 +420,27 @@ def test_clear_circuit(self):
         self.assertEqual(len(qc.data), 0)
         self.assertEqual(len(qc._parameter_table), 0)
 
+    def test_barrier(self):
+        """Test multiple argument forms of barrier."""
+        qr1, qr2 = QuantumRegister(3, "qr1"), QuantumRegister(4, "qr2")
+        qc = QuantumCircuit(qr1, qr2)
+        qc.barrier()  # All qubits.
+        qc.barrier(0, 1)
+        qc.barrier([4, 2])
+        qc.barrier(qr1)
+        qc.barrier(slice(3, 5))
+        qc.barrier({1, 4, 2}, range(5, 7))
+
+        expected = QuantumCircuit(qr1, qr2)
+        expected.append(Barrier(expected.num_qubits), expected.qubits.copy(), [])
+        expected.append(Barrier(2), [expected.qubits[0], expected.qubits[1]], [])
+        expected.append(Barrier(2), [expected.qubits[2], expected.qubits[4]], [])
+        expected.append(Barrier(3), expected.qubits[0:3], [])
+        expected.append(Barrier(2), [expected.qubits[3], expected.qubits[4]], [])
+        expected.append(Barrier(5), [expected.qubits[x] for x in [1, 2, 4, 5, 6]], [])
+
+        self.assertEqual(qc, expected)
+
     def test_measure_active(self):
         """Test measure_active
         Applies measurements only to non-idle qubits. Creates a ClassicalRegister of size equal to