Qx.Patterns (Qx - Quantum Computing Simulator v0.11.0)

View Source

Utility module: reached from Qx.* in normal use — the _all, cx_chain, and state-prep helpers front Qx.h_all/1, Qx.cx_chain/2, Qx.bell_state/1, etc.

Composite circuit-building patterns: thin wrappers that emit multiple instructions in one call.

Where Qx.Operations emits exactly one instruction per call (one gate, one qubit), this module bundles the recurring "apply X to every qubit" / "measure every qubit" / "CNOT chain" motifs that appear in tutorials and algorithm circuits (Grover diffuser, Bernstein-Vazirani oracle, GHZ preparation, etc.).

All helpers are additive over Qx.Operations and Qx.QuantumCircuit; they introduce no new exception types. Out-of-range qubit indices or insufficient classical bits surface the existing typed errors (Qx.QubitIndexError, Qx.ClassicalBitError) from the underlying primitives.

Each _all helper has two arities:

  • /1 — apply to every qubit in the circuit (whole-circuit form).
  • /2 — apply to a sub-list or range of qubits (sub-register form), e.g. Qx.Patterns.h_all(qc, 0..2) or Qx.Patterns.h_all(qc, [0, 2, 4]).

See also:

  • Qx.Operations — one-instruction-per-call gate API.
  • Qx.StateInit — sibling module for composite state-vector recipes (Bell state, GHZ state, W state). Qx.Patterns is the circuit-instruction analogue.
  • Qx.bell_state/1 and Qx.ghz_state/1 — the documented entry points for the Bell- and GHZ-preparation circuits. bell_state_circuit/1 and ghz_state_circuit/1 here are their delegated-to implementations and carry @doc false; call them through the Qx facade.

Examples

# Equal superposition over all qubits (replaces a private `apply_h_all`
# helper used in tutorials).
iex> qc = Qx.create_circuit(3) |> Qx.Patterns.h_all()
iex> length(Qx.QuantumCircuit.get_instructions(qc))
3

# Equal superposition over a sub-register.
iex> qc = Qx.create_circuit(5) |> Qx.Patterns.h_all(0..2)
iex> length(Qx.QuantumCircuit.get_instructions(qc))
3

# Measure every qubit into its same-index classical bit.
iex> qc = Qx.create_circuit(2, 2) |> Qx.Patterns.measure_all()
iex> Qx.QuantumCircuit.get_instructions(qc)
[{:measure, [0, 0], []}, {:measure, [1, 1], []}]

# GHZ-style linear CNOT chain.
iex> qc = Qx.create_circuit(4) |> Qx.Patterns.cx_chain([0, 1, 2, 3])
iex> length(Qx.QuantumCircuit.get_instructions(qc))
3

Summary

Types

Selector for which of the four Bell states a recipe builds.

A list or range of non-negative qubit indices.

Functions

Adds a single barrier instruction spanning every qubit in circuit.

Adds a single barrier instruction spanning the given list or range of qubits.

Appends the gates that entangle qubits q0 and q1 into one of the four Bell states onto an existing circuit.

Applies a linear cascade of CNOTs along qubits.

Appends the GHZ-preparation gates over qubits onto an existing circuit.

Applies a Hadamard gate to every qubit in circuit.

Applies a Hadamard gate to every qubit in the given list or range.

Measures every qubit into its same-index classical bit.

Measures every qubit in the given list or range into its same-index classical bit (qubit i → classical bit i).

Builds an n-qubit equal-superposition circuit: H applied to every qubit, on a |0…0⟩ input the result is the uniform superposition. Default is 1 qubit.

Applies a Pauli-X gate to every qubit in circuit.

Applies a Pauli-X gate to every qubit in the given list or range.

Applies a Pauli-Y gate to every qubit in circuit.

Applies a Pauli-Y gate to every qubit in the given list or range.

Applies a Pauli-Z gate to every qubit in circuit.

Applies a Pauli-Z gate to every qubit in the given list or range.

Types

bell_state_type()

@type bell_state_type() :: :phi_plus | :phi_minus | :psi_plus | :psi_minus

Selector for which of the four Bell states a recipe builds.

qubits()

@type qubits() :: [non_neg_integer()] | Range.t()

A list or range of non-negative qubit indices.

Used as the second argument to the /2 form of h_all, x_all, y_all, z_all, measure_all, and barrier_all to select a sub-register, and as the qubit selector for ghz/2.

Functions

barrier_all(circuit)

@spec barrier_all(Qx.QuantumCircuit.t()) :: Qx.QuantumCircuit.t()

Adds a single barrier instruction spanning every qubit in circuit.

Equivalent to Qx.Operations.barrier(circuit, Enum.to_list(0..(n - 1))).

Examples

iex> qc = Qx.create_circuit(3) |> Qx.Patterns.barrier_all()
iex> Qx.QuantumCircuit.get_instructions(qc)
[{:barrier, [0, 1, 2], []}]

barrier_all(circuit, qubits)

@spec barrier_all(Qx.QuantumCircuit.t(), qubits()) :: Qx.QuantumCircuit.t()

Adds a single barrier instruction spanning the given list or range of qubits.

An empty list or empty range is a no-op (returns circuit unchanged).

Examples

iex> qc = Qx.create_circuit(4) |> Qx.Patterns.barrier_all([0, 2])
iex> Qx.QuantumCircuit.get_instructions(qc)
[{:barrier, [0, 2], []}]

bell_pair(circuit, q0, q1, which \\ :phi_plus)

Appends the gates that entangle qubits q0 and q1 into one of the four Bell states onto an existing circuit.

Unlike Qx.bell_state/1 (which creates a fresh 2-qubit circuit), this builder appends onto circuit at the caller-chosen qubits, so it composes inside a larger pipeline. The gate sequence per which (with q0 the control and q1 the target of the final CX):

whichGates appended
:phi_plush(q0), cx(q0, q1) (default)
:phi_minusx(q0), h(q0), cx(q0, q1)
:psi_plusx(q1), h(q0), cx(q0, q1)
:psi_minusx(q0), x(q1), h(q0), cx(q0, q1)

Parameters

  • circuit - The Qx.QuantumCircuit to append onto.
  • q0 - Control qubit of the entangling CX (and the Hadamard target).
  • q1 - Target qubit of the entangling CX.
  • which - Which Bell state to prepare (default :phi_plus).

Returns

The updated Qx.QuantumCircuit, so calls chain in a pipeline.

Examples

iex> qc = Qx.QuantumCircuit.new(3) |> Qx.Patterns.bell_pair(1, 2)
iex> Qx.QuantumCircuit.get_instructions(qc)
[{:h, [1], []}, {:cx, [1, 2], []}]

Raises

cx_chain(circuit, qubits)

Applies a linear cascade of CNOTs along qubits.

For qubits = [q0, q1, q2, ..., qk], emits CNOTs cx(q0, q1), cx(q1, q2), …, cx(q_{k-1}, q_k) — i.e. each qubit controls the next. This is the shape used to build GHZ states (e.g. H(0) → cx(0,1) → cx(1,2)).

Lists of length 0 or 1 are deliberate no-ops and return circuit unchanged.

Examples

iex> qc = Qx.create_circuit(4) |> Qx.Patterns.cx_chain([0, 1, 2, 3])
iex> Qx.QuantumCircuit.get_instructions(qc)
[{:cx, [0, 1], []}, {:cx, [1, 2], []}, {:cx, [2, 3], []}]

iex> qc = Qx.create_circuit(2) |> Qx.Patterns.cx_chain([])
iex> Qx.QuantumCircuit.get_instructions(qc)
[]

iex> qc = Qx.create_circuit(2) |> Qx.Patterns.cx_chain([0])
iex> Qx.QuantumCircuit.get_instructions(qc)
[]

ghz(circuit, qubits)

Appends the GHZ-preparation gates over qubits onto an existing circuit.

Applies a Hadamard to the first qubit in qubits, then a linear CNOT chain (cx_chain/2) along the rest — the |GHZ⟩ = (|0…0⟩ + |1…1⟩)/√2 recipe. Where Qx.ghz_state/1 creates a fresh n-qubit circuit over 0..n-1, this builder appends onto circuit at the caller-chosen qubits.

qubits may be a list or a range and must name at least two qubits — a GHZ state needs two qubits to entangle.

Parameters

  • circuit - The Qx.QuantumCircuit to append onto.
  • qubits - A list or range of at least two qubit indices; the first is the Hadamard/root qubit, and the chain follows the given order.

Returns

The updated Qx.QuantumCircuit, so calls chain in a pipeline.

Examples

iex> qc = Qx.QuantumCircuit.new(4) |> Qx.Patterns.ghz(1..3)
iex> Qx.QuantumCircuit.get_instructions(qc)
[{:h, [1], []}, {:cx, [1, 2], []}, {:cx, [2, 3], []}]

Raises

h_all(circuit)

Applies a Hadamard gate to every qubit in circuit.

Equivalent to Enum.reduce(0..(n - 1), circuit, &Qx.h(&2, &1)) where n is circuit.num_qubits, but expresses the intent directly.

Examples

iex> qc = Qx.create_circuit(3) |> Qx.Patterns.h_all()
iex> Qx.QuantumCircuit.get_instructions(qc)
[{:h, [0], []}, {:h, [1], []}, {:h, [2], []}]

h_all(circuit, qubits)

Applies a Hadamard gate to every qubit in the given list or range.

Examples

iex> qc = Qx.create_circuit(5) |> Qx.Patterns.h_all([0, 2, 4])
iex> Qx.QuantumCircuit.get_instructions(qc)
[{:h, [0], []}, {:h, [2], []}, {:h, [4], []}]

iex> qc = Qx.create_circuit(5) |> Qx.Patterns.h_all(1..3)
iex> Qx.QuantumCircuit.get_instructions(qc)
[{:h, [1], []}, {:h, [2], []}, {:h, [3], []}]

measure_all(circuit)

@spec measure_all(Qx.QuantumCircuit.t()) :: Qx.QuantumCircuit.t()

Measures every qubit into its same-index classical bit.

Emits n measurement instructions where n = circuit.num_qubits, each mapping qubit i to classical bit i.

Raises Qx.ClassicalBitError if circuit.num_classical_bits < num_qubits — the circuit shape is the caller's decision (made at create_circuit/2), and no auto-grow happens.

Examples

iex> qc = Qx.create_circuit(3, 3) |> Qx.Patterns.measure_all()
iex> Qx.QuantumCircuit.get_instructions(qc)
[{:measure, [0, 0], []}, {:measure, [1, 1], []}, {:measure, [2, 2], []}]

measure_all(circuit, qubits)

@spec measure_all(Qx.QuantumCircuit.t(), qubits()) :: Qx.QuantumCircuit.t()

Measures every qubit in the given list or range into its same-index classical bit (qubit i → classical bit i).

Examples

iex> qc = Qx.create_circuit(3, 3) |> Qx.Patterns.measure_all([0, 2])
iex> Qx.QuantumCircuit.get_instructions(qc)
[{:measure, [0, 0], []}, {:measure, [2, 2], []}]

superposition_circuit(num_qubits \\ 1)

@spec superposition_circuit(pos_integer()) :: Qx.QuantumCircuit.t()

Builds an n-qubit equal-superposition circuit: H applied to every qubit, on a |0…0⟩ input the result is the uniform superposition. Default is 1 qubit.

Examples

iex> qc = Qx.Patterns.superposition_circuit()
iex> qc.num_qubits
1

iex> qc = Qx.Patterns.superposition_circuit(3)
iex> length(Qx.QuantumCircuit.get_instructions(qc))
3

x_all(circuit)

Applies a Pauli-X gate to every qubit in circuit.

Examples

iex> qc = Qx.create_circuit(2) |> Qx.Patterns.x_all()
iex> Qx.QuantumCircuit.get_instructions(qc)
[{:x, [0], []}, {:x, [1], []}]

x_all(circuit, qubits)

Applies a Pauli-X gate to every qubit in the given list or range.

Examples

iex> qc = Qx.create_circuit(4) |> Qx.Patterns.x_all([0, 3])
iex> Qx.QuantumCircuit.get_instructions(qc)
[{:x, [0], []}, {:x, [3], []}]

y_all(circuit)

Applies a Pauli-Y gate to every qubit in circuit.

Examples

iex> qc = Qx.create_circuit(2) |> Qx.Patterns.y_all()
iex> Qx.QuantumCircuit.get_instructions(qc)
[{:y, [0], []}, {:y, [1], []}]

y_all(circuit, qubits)

Applies a Pauli-Y gate to every qubit in the given list or range.

Examples

iex> qc = Qx.create_circuit(3) |> Qx.Patterns.y_all(0..1)
iex> Qx.QuantumCircuit.get_instructions(qc)
[{:y, [0], []}, {:y, [1], []}]

z_all(circuit)

Applies a Pauli-Z gate to every qubit in circuit.

Examples

iex> qc = Qx.create_circuit(2) |> Qx.Patterns.z_all()
iex> Qx.QuantumCircuit.get_instructions(qc)
[{:z, [0], []}, {:z, [1], []}]

z_all(circuit, qubits)

Applies a Pauli-Z gate to every qubit in the given list or range.

Examples

iex> qc = Qx.create_circuit(3) |> Qx.Patterns.z_all([2])
iex> Qx.QuantumCircuit.get_instructions(qc)
[{:z, [2], []}]