Task: Fix non-determinism VF2Layout with only 1q gates (Qiskit/qiskit#14730)

org: Qiskit
repo: qiskit
pr_number: 14730
issue_title: Fix non-determinism VF2Layout with only 1q gates
issue_body: <!--\r\n⚠️ If you do not respect this template, your pull request will be closed.\r\n⚠️ Your pull request title should be short detailed and understandable for all.\r\n⚠️ Also, please add a release note file using reno if the change needs to be\r\n  documented in the release notes.\r\n⚠️ If your pull request fixes an open issue, please link to the issue.\r\n\r\n- [ ] I have added the tests to cover my changes.\r\n- [ ] I have updated the documentation accordingly.\r\n- [ ] I have read the CONTRIBUTING document.\r\n-->\r\n\r\n### Summary\r\n\r\nThis commit fixes an issue in the VF2Layout transpiler pass that would cause a non-deterministic output if the circuit had any qubit that only had single qubit operations. The dedicated internal function to deal with this special case sorts the qubits in the circuit by number of operations and the physical qubits on the target by error rate, to map the qubits with the lowest error rate. However this sorting wasn't fully stable as it was done on a hash set which doesn't have a stable iteration order. This commit fixes this by also sorting based on the qubit index so in the case of a tie the sort is stable.\r\n\r\n### Details and comments\r\n\r\nFixes #14729
resolved_issues: number: 14729
title: Transpile with seed_transpiler doesn't yield the same circuit
body: ### Environment\n\n- **Qiskit version**: 2.1.1\n- **Python version**: 3.12.9\n- **Operating system**: MacOS\n\n### What is happening?\n\nTranspiling with a pass manager created with `seed_transpiler` doesn't yield the same circuit after 2.1.\n\n### How can we reproduce the issue?\n\n```python\nimport numpy as np\nfrom qiskit.circuit import ParameterVector, QuantumCircuit\nfrom qiskit.providers.fake_provider import GenericBackendV2\nfrom qiskit.transpiler import generate_preset_pass_manager\n\nparams = ParameterVector("θ", length=3)\n\ncirc = QuantumCircuit(3)\nfor i, par in enumerate(params):\n    circ.rx(par, i)\ncirc.measure_all()\n\nbackend = GenericBackendV2(10, noise_info=True, seed=123)\nisa_circs = []\nfor _ in range(10):\n    pm = generate_preset_pass_manager(optimization_level=2, target=backend.target, seed_transpiler=123)\n    isa_circs.append(pm.run(circ))  \n\nassert all(x == isa_circs[0] for x in isa_circs)\n```\n\nThis code works okey with 2.0.\n\nWith 2.1.* the pass manger layout is inconsistent.\n\n```\nglobal phase: π/2\n         ┌─────────┐┌────┐┌──────────────┐┌────┐┌──────────┐ ░    ┌─┐   \nq_1 -> 0 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[1]) ├┤ √X ├┤ Rz(5π/2) ├─░────┤M├───\n         ├─────────┤├────┤├──────────────┤├────┤├──────────┤ ░    └╥┘┌─┐\nq_2 -> 3 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[2]) ├┤ √X ├┤ Rz(5π/2) ├─░─────╫─┤M├\n         ├─────────┤├────┤├──────────────┤├────┤├──────────┤ ░ ┌─┐ ║ └╥┘\nq_0 -> 8 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[0]) ├┤ √X ├┤ Rz(5π/2) ├─░─┤M├─╫──╫─\n         └─────────┘└────┘└──────────────┘└────┘└──────────┘ ░ └╥┘ ║  ║ \n meas: 3/═══════════════════════════════════════════════════════╩══╩══╩═\n                                                                0  1  2 \nglobal phase: π/2\n         ┌─────────┐┌────┐┌──────────────┐┌────┐┌──────────┐ ░       ┌─┐\nq_2 -> 0 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[2]) ├┤ √X ├┤ Rz(5π/2) ├─░───────┤M├\n         ├─────────┤├────┤├──────────────┤├────┤├──────────┤ ░    ┌─┐└╥┘\nq_1 -> 3 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[1]) ├┤ √X ├┤ Rz(5π/2) ├─░────┤M├─╫─\n         ├─────────┤├────┤├──────────────┤├────┤├──────────┤ ░ ┌─┐└╥┘ ║ \nq_0 -> 8 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[0]) ├┤ √X ├┤ Rz(5π/2) ├─░─┤M├─╫──╫─\n         └─────────┘└────┘└──────────────┘└────┘└──────────┘ ░ └╥┘ ║  ║ \n meas: 3/═══════════════════════════════════════════════════════╩══╩══╩═\n                                                                0  1  2 \nglobal phase: π/2\n         ┌─────────┐┌────┐┌──────────────┐┌────┐┌──────────┐ ░    ┌─┐   \nq_1 -> 0 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[1]) ├┤ √X ├┤ Rz(5π/2) ├─░────┤M├───\n         ├─────────┤├────┤├──────────────┤├────┤├──────────┤ ░    └╥┘┌─┐\nq_2 -> 3 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[2]) ├┤ √X ├┤ Rz(5π/2) ├─░─────╫─┤M├\n         ├─────────┤├────┤├──────────────┤├────┤├──────────┤ ░ ┌─┐ ║ └╥┘\nq_0 -> 8 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[0]) ├┤ √X ├┤ Rz(5π/2) ├─░─┤M├─╫──╫─\n         └─────────┘└────┘└──────────────┘└────┘└──────────┘ ░ └╥┘ ║  ║ \n meas: 3/═══════════════════════════════════════════════════════╩══╩══╩═\n                                                                0  1  2 \nglobal phase: π/2\n         ┌─────────┐┌────┐┌──────────────┐┌────┐┌──────────┐ ░    ┌─┐   \nq_1 -> 0 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[1]) ├┤ √X ├┤ Rz(5π/2) ├─░────┤M├───\n         ├─────────┤├────┤├──────────────┤├────┤├──────────┤ ░    └╥┘┌─┐\nq_2 -> 3 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[2]) ├┤ √X ├┤ Rz(5π/2) ├─░─────╫─┤M├\n         ├─────────┤├────┤├──────────────┤├────┤├──────────┤ ░ ┌─┐ ║ └╥┘\nq_0 -> 8 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[0]) ├┤ √X ├┤ Rz(5π/2) ├─░─┤M├─╫──╫─\n         └─────────┘└────┘└──────────────┘└────┘└──────────┘ ░ └╥┘ ║  ║ \n meas: 3/═══════════════════════════════════════════════════════╩══╩══╩═\n                                                                0  1  2 \nglobal phase: π/2\n         ┌─────────┐┌────┐┌──────────────┐┌────┐┌──────────┐ ░       ┌─┐\nq_2 -> 0 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[2]) ├┤ √X ├┤ Rz(5π/2) ├─░───────┤M├\n         ├─────────┤├────┤├──────────────┤├────┤├──────────┤ ░ ┌─┐   └╥┘\nq_0 -> 3 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[0]) ├┤ √X ├┤ Rz(5π/2) ├─░─┤M├────╫─\n         ├─────────┤├────┤├──────────────┤├────┤├──────────┤ ░ └╥┘┌─┐ ║ \nq_1 -> 8 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[1]) ├┤ √X ├┤ Rz(5π/2) ├─░──╫─┤M├─╫─\n         └─────────┘└────┘└──────────────┘└────┘└──────────┘ ░  ║ └╥┘ ║ \n meas: 3/═══════════════════════════════════════════════════════╩══╩══╩═\n                                                                0  1  2 \nglobal phase: π/2\n         ┌─────────┐┌────┐┌──────────────┐┌────┐┌──────────┐ ░    ┌─┐   \nq_1 -> 0 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[1]) ├┤ √X ├┤ Rz(5π/2) ├─░────┤M├───\n         ├─────────┤├────┤├──────────────┤├────┤├──────────┤ ░    └╥┘┌─┐\nq_2 -> 3 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[2]) ├┤ √X ├┤ Rz(5π/2) ├─░─────╫─┤M├\n         ├─────────┤├────┤├──────────────┤├────┤├──────────┤ ░ ┌─┐ ║ └╥┘\nq_0 -> 8 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[0]) ├┤ √X ├┤ Rz(5π/2) ├─░─┤M├─╫──╫─\n         └─────────┘└────┘└──────────────┘└────┘└──────────┘ ░ └╥┘ ║  ║ \n meas: 3/═══════════════════════════════════════════════════════╩══╩══╩═\n                                                                0  1  2 \nglobal phase: π/2\n         ┌─────────┐┌────┐┌──────────────┐┌────┐┌──────────┐ ░    ┌─┐   \nq_1 -> 0 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[1]) ├┤ √X ├┤ Rz(5π/2) ├─░────┤M├───\n         ├─────────┤├────┤├──────────────┤├────┤├──────────┤ ░    └╥┘┌─┐\nq_2 -> 3 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[2]) ├┤ √X ├┤ Rz(5π/2) ├─░─────╫─┤M├\n         ├─────────┤├────┤├──────────────┤├────┤├──────────┤ ░ ┌─┐ ║ └╥┘\nq_0 -> 8 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[0]) ├┤ √X ├┤ Rz(5π/2) ├─░─┤M├─╫──╫─\n         └─────────┘└────┘└──────────────┘└────┘└──────────┘ ░ └╥┘ ║  ║ \n meas: 3/═══════════════════════════════════════════════════════╩══╩══╩═\n                                                                0  1  2 \nglobal phase: π/2\n         ┌─────────┐┌────┐┌──────────────┐┌────┐┌──────────┐ ░       ┌─┐\nq_2 -> 0 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[2]) ├┤ √X ├┤ Rz(5π/2) ├─░───────┤M├\n         ├─────────┤├────┤├──────────────┤├────┤├──────────┤ ░ ┌─┐   └╥┘\nq_0 -> 3 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[0]) ├┤ √X ├┤ Rz(5π/2) ├─░─┤M├────╫─\n         ├─────────┤├────┤├──────────────┤├────┤├──────────┤ ░ └╥┘┌─┐ ║ \nq_1 -> 8 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[1]) ├┤ √X ├┤ Rz(5π/2) ├─░──╫─┤M├─╫─\n         └─────────┘└────┘└──────────────┘└────┘└──────────┘ ░  ║ └╥┘ ║ \n meas: 3/═══════════════════════════════════════════════════════╩══╩══╩═\n                                                                0  1  2 \nglobal phase: π/2\n         ┌─────────┐┌────┐┌──────────────┐┌────┐┌──────────┐ ░ ┌─┐      \nq_0 -> 0 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[0]) ├┤ √X ├┤ Rz(5π/2) ├─░─┤M├──────\n         ├─────────┤├────┤├──────────────┤├────┤├──────────┤ ░ └╥┘┌─┐   \nq_1 -> 3 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[1]) ├┤ √X ├┤ Rz(5π/2) ├─░──╫─┤M├───\n         ├─────────┤├────┤├──────────────┤├────┤├──────────┤ ░  ║ └╥┘┌─┐\nq_2 -> 8 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[2]) ├┤ √X ├┤ Rz(5π/2) ├─░──╫──╫─┤M├\n         └─────────┘└────┘└──────────────┘└────┘└──────────┘ ░  ║  ║ └╥┘\n meas: 3/═══════════════════════════════════════════════════════╩══╩══╩═\n                                                                0  1  2 \nglobal phase: π/2\n         ┌─────────┐┌────┐┌──────────────┐┌────┐┌──────────┐ ░ ┌─┐      \nq_0 -> 0 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[0]) ├┤ √X ├┤ Rz(5π/2) ├─░─┤M├──────\n         ├─────────┤├────┤├──────────────┤├────┤├──────────┤ ░ └╥┘┌─┐   \nq_1 -> 3 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[1]) ├┤ √X ├┤ Rz(5π/2) ├─░──╫─┤M├───\n         ├─────────┤├────┤├──────────────┤├────┤├──────────┤ ░  ║ └╥┘┌─┐\nq_2 -> 8 ┤ Rz(π/2) ├┤ √X ├┤ Rz(π + θ[2]) ├┤ √X ├┤ Rz(5π/2) ├─░──╫──╫─┤M├\n         └─────────┘└────┘└──────────────┘└────┘└──────────┘ ░  ║  ║ └╥┘\n meas: 3/═══════════════════════════════════════════════════════╩══╩══╩═\n                                                                0  1  2 \n\n```\n\n### What should happen?\n\nTranspile with a fixed seed should always generate the same layout. This is problematic at least for unittest of my codebase. Not sure if applications can be also affected by this.\n\n### Any suggestions?\n\nI don't have bandwidth to investigate.\n\n(edit) \nAfter carefully looking into transpiled circuits, I realized that the circuit is always consistent at the level of physical qubit set. Since each wire in my circuit is logically equivalent, the behavior of transpiler is still reasonable. Maybe this is undocumented policy update?

Reference solution:
fix_patch: diff --git a/crates/transpiler/src/passes/vf2/vf2_layout.rs b/crates/transpiler/src/passes/vf2/vf2_layout.rs\nindex c53419768e2c..c7241848dbaf 100644\n--- a/crates/transpiler/src/passes/vf2/vf2_layout.rs\n+++ b/crates/transpiler/src/passes/vf2/vf2_layout.rs\n@@ -347,10 +347,14 @@ fn map_free_qubits(\n             .get(&[PhysicalQubit::new(*qubit_b), PhysicalQubit::new(*qubit_b)])\n             .unwrap_or(&0.);\n         // Reverse comparison so lower error rates are at the end of the vec.\n-        score_b.partial_cmp(&score_a).unwrap()\n+        match score_b.partial_cmp(&score_a).unwrap() {\n+            Ordering::Equal => qubit_b.cmp(qubit_a),\n+            Ordering::Less => Ordering::Less,\n+            Ordering::Greater => Ordering::Greater,\n+        }\n     });\n     let mut free_indices: Vec<NodeIndex> = free_nodes.keys().copied().collect();\n-    free_indices.par_sort_by_key(|index| free_nodes[index].values().sum::<usize>());\n+    free_indices.par_sort_by_key(|index| (free_nodes[index].values().sum::<usize>(), *index));\n     for im_index in free_indices {\n         let selected_qubit = free_qubits.pop()?;\n         partial_layout.insert(\ndiff --git a/releasenotes/notes/fix-1q-non-determinism-vf2-75490119547bf656.yaml b/releasenotes/notes/fix-1q-non-determinism-vf2-75490119547bf656.yaml\nnew file mode 100644\nindex 000000000000..336b6a5c8f9c\n--- /dev/null\n+++ b/releasenotes/notes/fix-1q-non-determinism-vf2-75490119547bf656.yaml\n@@ -0,0 +1,8 @@\n+---\n+fixes:\n+  - |\n+    Fixed an issue in the :class:`.VF2Layout` transpiler pass where even with\n+    a fixed seed set the output from the pass was potentially non-deterministic;\n+    specifically if the input circuit had any active qubits that only contained\n+    single qubit operations.\n+    Fixed `#14729 <https://github.com/Qiskit/qiskit/issues/14729>`__\n