# Get PennyLane wire ordering and state-vector conventions right

Resolve PennyLane wire/statevector ordering confusion: the wire-0-is-MSB convention, BasisState index mapping, marginal vs joint qml.probs, Qiskit little-endian conversion, controlled-gate wire order, and non-integer wire labels.

Exact reference: {"kind":"skill_version","skill_id":"skl_J5EfOHqGhbEUnr-fpq8f-w","version_id":"skv_DNz0xTZVS2mIlaxwKY4JKA"}

Applicability: [{"constraint":">=0.30","technology":"PennyLane","version_scheme":"semver"}]

# Get PennyLane wire ordering and state-vector conventions right

Use this when a prepared state, `qml.state()` output, or `qml.probs()` result
does not match the bitstring you expected, or when PennyLane numbers disagree
with Qiskit (or another framework) on the same circuit. Nearly all of these are
convention mismatches, not bugs — check the convention before rewriting the
circuit.

## 1. The convention: wire 0 is the most significant bit

PennyLane uses |q0, q1, ..., qN-1> with q0 as the most significant bit
(documented in the device API). Consequences:

- `qml.BasisState([1, 0], wires=[0, 1])` puts the amplitude-1 entry at index 2
  of the state vector (binary `10`, wire 0 read first) — not index 1.
- `qml.probs(wires=[0, 1, 2, 3])` returns a 16-element vector where index `i`
  holds the probability of the bitstring equal to the binary representation of
  `i` (wire 0 = MSB).
- `qml.probs(wires=0)` returns the *marginal* distribution of wire 0 alone
  (other wires traced out).

Verify with a known state before trusting a large circuit:

```python
import pennylane as qml

dev = qml.device("default.qubit", wires=2)

def prep():
    qml.BasisState([1, 0], wires=[0, 1])
    return qml.state()

prep_qnode = qml.QNode(prep, dev)
print(prep_qnode())  # expect [0, 0, 1, 0]: amplitude at index 2 = binary 10
```

If this prints what you expect, the convention is understood; the bug is
elsewhere in your circuit.

## 2. Classify the mismatch

- **Comparing against Qiskit**: Qiskit numbers qubits little-endian (qubit 0 =
  least significant bit) — the opposite convention. Convert a Qiskit
  statevector to PennyLane ordering with:
  ```python
  pl_state = qiskit_state.reshape([2] * n_qubits).T.flatten()
  ```
  (PennyLane team answer on the forum.) If you convert the wrong direction,
  everything looks bit-reversed.
- **Controlled gates**: in `qml.CNOT(wires=[0, 1])` the FIRST wire is the
  control (wire 0) and the second is the target (wire 1). Swapping the list
  order changes which qubit controls the gate — check every multi-qubit gate's
  wire list.
- **Marginal vs joint probabilities**: `qml.probs(wires=[0])` is the marginal
  for wire 0; `qml.probs(wires=[0, 1])` is the joint distribution. A Bell pair
  measures `[0.5, 0.5]` marginally but `[0.5, 0, 0, 0.5]` jointly — mixing these
  up is a classic "wrong answer".
- **Drawing order**: `qml.draw` lists wires in device wire order; pass
  `wire_order=[...]` to pin it. A "Wires in circuit are inconsistent with
  those in wire_order" error means your `wire_order` list does not match the
  circuit's wires — fix the list, not the circuit.

## 3. Wire labels are not necessarily integers

Wires can be any unique labels: `qml.device("default.qubit", wires=["a", "b"])`
is valid, and ops take `wires="a"`. The device wire count must cover every wire
the circuit uses. Composite ops that build internal wire lists (e.g.
`qml.QSVT`) can produce wire orders that surprise device checks — print
`op.wires` and compare against the circuit's wires when a wire-consistency
error appears.

## 4. Checklist

1. Write down the expected index/bitstring for a 2-qubit basis state first;
   run the verify snippet in step 1.
2. If comparing frameworks, confirm each framework's endianness and convert
   once, explicitly, in the right direction.
3. Check control/target order in every multi-qubit gate's wire list.
4. Check marginal vs joint in every `qml.probs` call.
5. Pin `wire_order` in `qml.draw` when sharing or comparing circuit diagrams.


## Supporting basis and limitations

Built from the PennyLane device docs ('PennyLane uses the convention |q0,q1,...,qN-1> where q0 is the most significant bit'), a PennyLane-team forum answer giving the Qiskit conversion (statevector.reshape([2]*n).T.flatten()), and forum threads on qml.probs index ordering and wire_order drawing errors.

## Change and rationale

New skill: get PennyLane wire ordering and state-vector conventions right.

'My state doesn't match' is a recurring PennyLane forum theme with a single root cause family: PennyLane's wire-0-is-MSB convention vs Qiskit little-endian, marginal vs joint probs, and control/target wire order. Users rewrite circuits when they should convert conventions. This skill adds a classify-first decision procedure with a 2-qubit verification snippet.
