Qx.Qubit (Qx - Quantum Computing Simulator v0.5.0)
View SourceSimplified API for single-qubit quantum operations.
This module provides a beginner-friendly interface for working with individual
qubits. Under the hood, it uses Qx.Register with num_qubits=1, providing
a clean abstraction for single-qubit operations without exposing multi-qubit
complexity.
Calculation Mode
Calculation mode allows you to work with qubits directly, applying gates
in real-time and seeing results immediately. This is different from circuit
mode (using Qx.QuantumCircuit) where you build a circuit first and then
execute it.
In calculation mode:
- Gates are applied immediately to the quantum state
- You can inspect the state at any point using
state_vector/1ormeasure_probabilities/1 - Results are available instantly without needing to run a simulation
- Perfect for learning, exploration, and debugging
Example Workflows
# Basic gate application
q = Qx.Qubit.new()
|> Qx.Qubit.h()
|> Qx.Qubit.state_vector()
# Returns superposition state
# Check probabilities at each step
q = Qx.Qubit.new()
Qx.Qubit.measure_probabilities(q) # [1.0, 0.0] - definitely |0⟩
q = Qx.Qubit.x(q)
Qx.Qubit.measure_probabilities(q) # [0.0, 1.0] - definitely |1⟩
q = Qx.Qubit.h(q)
Qx.Qubit.measure_probabilities(q) # [0.5, 0.5] - equal superposition
# Create and manipulate custom states
q = Qx.Qubit.new(0.6, 0.8) # Custom amplitudes (auto-normalized)
|> Qx.Qubit.rz(:math.pi() / 4)
|> Qx.Qubit.rx(:math.pi() / 2)Available Gates
Single-Qubit Gates (no parameters):
h/1- Hadamard gate (creates superposition)x/1- Pauli-X gate (bit flip)y/1- Pauli-Y gate (bit and phase flip)z/1- Pauli-Z gate (phase flip)s/1- S gate (π/2 phase)t/1- T gate (π/4 phase)
Parameterized Gates:
rx/2- Rotation around X-axisry/2- Rotation around Y-axisrz/2- Rotation around Z-axisphase/2- Arbitrary phase gate
Pipeline Patterns
The Qx.Qubit module supports both transformation pipelines and terminal operations:
Transformation Pipelines (return qubits):
Gates and state manipulations that return qubits for chaining:
Qx.Qubit.new()
|> Qx.Qubit.h() # Hadamard gate
|> Qx.Qubit.x() # Pauli-X gate
|> Qx.Qubit.ry(angle) # RotationDebugging Within Pipelines:
Use tap_state/2 to inspect state without breaking the chain:
Qx.Qubit.new()
|> Qx.Qubit.h()
|> Qx.Qubit.tap_state(label: "After H") # Side effect: prints state
|> Qx.Qubit.x() # Returns qubit, pipeline continuesTerminal Operations (return data):
Functions that extract information and end the pipeline:
state_map = qubit |> Qx.Qubit.h() |> Qx.Qubit.show_state() # Returns map
prob_tensor = qubit |> Qx.Qubit.measure_probabilities() # Returns Nx.Tensor
bloch = qubit |> Qx.Qubit.draw_bloch() # Returns VegaLite struct (default) or SVG string
is_valid = qubit |> Qx.Qubit.valid?() # Returns booleanChoose the right pattern for your use case!
Architecture Note
This module is implemented as a thin wrapper around Qx.Register. All gate
operations delegate to the Register module, ensuring consistency and reducing
code duplication. This design provides:
- Single source of truth for gate implementations
- Better performance (Register is highly optimized)
- Easier maintenance
- Seamless transition when scaling to multi-qubit operations
See Also
Qx.Register- Multi-qubit calculation modeQx.QuantumCircuit- Circuit mode for building quantum circuitsQx.Draw.bloch_sphere/2- Visualize single qubit statesQx.Qubit.draw_bloch/2- Visualize qubit on Bloch sphere
Summary
Functions
Gets the amplitude for the |0⟩ state.
Gets the amplitude for the |1⟩ state.
Draws the qubit state on a Bloch sphere.
Creates a qubit from angle (simplified Bloch sphere).
Creates a qubit from a computational basis state.
Creates a qubit from Bloch sphere coordinates.
Applies a Hadamard gate to a qubit in calculation mode.
Measures a qubit and returns the probability of measuring |0⟩ and |1⟩.
Creates a qubit in the |-⟩ state.
Creates a qubit in the |0⟩ state.
Creates a qubit with custom amplitudes.
Creates a qubit in the |1⟩ state.
Applies an arbitrary phase gate.
Creates a qubit in the |+⟩ state (equal superposition).
Creates a random qubit state with uniformly distributed amplitudes.
Applies a rotation around the X-axis.
Applies a rotation around the Y-axis.
Applies a rotation around the Z-axis.
Applies an S gate (π/2 phase) to a qubit.
Returns a map containing formatted state information.
Returns the state vector of the qubit.
Applies a T gate (π/4 phase) to a qubit.
Inspects the qubit state and returns the original qubit (pipeline-friendly).
Checks if a given state vector represents a valid qubit.
Applies a Pauli-X gate (bit flip) to a qubit.
Applies a Pauli-Y gate to a qubit.
Applies a Pauli-Z gate (phase flip) to a qubit.
Types
@type t() :: Nx.Tensor.t()
Functions
Gets the amplitude for the |0⟩ state.
Examples
iex> qubit = Qx.Qubit.new(0.6, 0.8)
iex> alpha = Qx.Qubit.alpha(qubit)
iex> abs(Complex.abs(alpha) - 0.6) < 0.01
truePipeline Usage
⚠️ This is a terminal operation that returns a Complex number, not a qubit.
For pipeline-friendly state inspection, use tap_state/2.
Gets the amplitude for the |1⟩ state.
Examples
iex> qubit = Qx.Qubit.new(0.6, 0.8)
iex> beta = Qx.Qubit.beta(qubit)
iex> abs(Complex.abs(beta) - 0.8) < 0.01
truePipeline Usage
⚠️ This is a terminal operation that returns a Complex number, not a qubit.
For pipeline-friendly state inspection, use tap_state/2.
Draws the qubit state on a Bloch sphere.
This function visualizes the qubit's state on the Bloch sphere, showing the state vector, axes, and key basis states.
Parameters
qubit- The qubit state to visualizeoptions- Optional visualization parameters:format- Output format (:svg,:vega_lite) (default::vega_lite):title- Title of the plot (default: "Bloch Sphere"):size- Size of the visualization in pixels (default: 400)
Examples
iex> q = Qx.Qubit.new() |> Qx.Qubit.h()
iex> result = Qx.Qubit.draw_bloch(q)
iex> is_struct(result) or is_binary(result)
true
iex> q = Qx.Qubit.new() |> Qx.Qubit.h()
iex> svg = Qx.Qubit.draw_bloch(q, format: :svg)
iex> is_binary(svg)
truePipeline Usage
⚠️ This is a terminal operation that returns an SVG string or VegaLite struct, not a qubit.
For pipeline-friendly state inspection, use tap_state/2.
Creates a qubit from angle (simplified Bloch sphere).
This is a simplified version of from_bloch/2 where phi=0.
Useful for creating states along the X-Z plane of the Bloch sphere.
Parameters
theta- Polar angle in radians (0 to π)
Examples
# Create superposition |+⟩
iex> q = Qx.Qubit.from_angle(:math.pi() / 2)
iex> probs = Qx.Qubit.measure_probabilities(q) |> Nx.to_flat_list()
iex> abs(Enum.at(probs, 0) - 0.5) < 0.01
true
@spec from_basis(0 | 1) :: t()
Creates a qubit from a computational basis state.
Parameters
basis- 0 for |0⟩ or 1 for |1⟩
Examples
iex> q = Qx.Qubit.from_basis(0)
iex> Qx.Qubit.alpha(q) |> Complex.abs()
1.0
iex> q = Qx.Qubit.from_basis(1)
iex> Qx.Qubit.beta(q) |> Complex.abs()
1.0
Creates a qubit from Bloch sphere coordinates.
The Bloch sphere is a geometrical representation of a qubit's quantum state. Any pure qubit state can be written as: |ψ⟩ = cos(θ/2)|0⟩ + e^(iφ)sin(θ/2)|1⟩
Parameters
theta- Polar angle in radians (0 to π)phi- Azimuthal angle in radians (0 to 2π)
Examples
# Create |0⟩ state (north pole)
iex> q = Qx.Qubit.from_bloch(0, 0)
iex> Qx.Qubit.alpha(q) |> Complex.abs() |> Float.round(3)
1.0
# Create |1⟩ state (south pole)
iex> q = Qx.Qubit.from_bloch(:math.pi(), 0)
iex> Qx.Qubit.beta(q) |> Complex.abs() |> Float.round(3)
1.0
# Create |+⟩ state (equator, x-axis)
iex> q = Qx.Qubit.from_bloch(:math.pi() / 2, 0)
iex> probs = Qx.Qubit.measure_probabilities(q) |> Nx.to_flat_list()
iex> abs(Enum.at(probs, 0) - 0.5) < 0.01
true
Applies a Hadamard gate to a qubit in calculation mode.
The Hadamard gate creates superposition by transforming:
- |0⟩ → (|0⟩ + |1⟩)/√2
- |1⟩ → (|0⟩ - |1⟩)/√2
Examples
iex> q = Qx.Qubit.new() |> Qx.Qubit.h()
iex> probs = Qx.Qubit.measure_probabilities(q) |> Nx.to_flat_list()
iex> abs(Enum.at(probs, 0) - 0.5) < 0.01
true
Measures a qubit and returns the probability of measuring |0⟩ and |1⟩.
Examples
iex> qubit = Qx.Qubit.plus()
iex> probs = Qx.Qubit.measure_probabilities(qubit)
iex> Nx.shape(probs)
{2}Pipeline Usage
⚠️ This is a terminal operation that returns an Nx.Tensor, not a qubit.
For pipeline-friendly state inspection, use tap_state/2.
Creates a qubit in the |-⟩ state.
The |-⟩ state is (|0⟩ - |1⟩)/√2.
Examples
iex> q = Qx.Qubit.minus()
iex> probs = Qx.Qubit.measure_probabilities(q) |> Nx.to_flat_list()
iex> abs(Enum.at(probs, 0) - 0.5) < 0.01
true
Creates a qubit in the |0⟩ state.
The |0⟩ state is represented as the state vector [1, 0].
Examples
iex> Qx.Qubit.new()
#Nx.Tensor<
c64[2]
[1.0+0.0i, 0.0+0.0i]
>
Creates a qubit with custom amplitudes.
The qubit state is automatically normalized to ensure |α|² + |β|² = 1.
Parameters
alpha- Amplitude for |0⟩ state (real number or Complex)beta- Amplitude for |1⟩ state (real number or Complex)
Examples
iex> q = Qx.Qubit.new(0.6, 0.8)
iex> Qx.Qubit.valid?(q)
true
iex> q = Qx.Qubit.new(1, 1) # Auto-normalized to (|0⟩ + |1⟩)/√2
iex> probs = Qx.Qubit.measure_probabilities(q) |> Nx.to_flat_list()
iex> abs(Enum.at(probs, 0) - 0.5) < 0.01
true
Creates a qubit in the |1⟩ state.
Examples
iex> Qx.Qubit.one()
#Nx.Tensor<
c64[2]
[0.0+0.0i, 1.0+0.0i]
>
Applies an arbitrary phase gate.
Parameters
qubit- The qubit statephi- Phase angle in radians
Examples
iex> q = Qx.Qubit.new() |> Qx.Qubit.phase(:math.pi() / 4)
iex> Qx.Qubit.valid?(q)
true
Creates a qubit in the |+⟩ state (equal superposition).
The |+⟩ state is (|0⟩ + |1⟩)/√2.
Examples
iex> q = Qx.Qubit.plus()
iex> probs = Qx.Qubit.measure_probabilities(q) |> Nx.to_flat_list()
iex> abs(Enum.at(probs, 0) - 0.5) < 0.01
true
Creates a random qubit state with uniformly distributed amplitudes.
The state is automatically normalized to ensure it represents a valid qubit.
Examples
iex> random_qubit = Qx.Qubit.random()
iex> Qx.Qubit.valid?(random_qubit)
true
Applies a rotation around the X-axis.
Parameters
qubit- The qubit statetheta- Rotation angle in radians
Examples
iex> q = Qx.Qubit.new() |> Qx.Qubit.rx(:math.pi())
iex> probs = Qx.Qubit.measure_probabilities(q) |> Nx.to_flat_list()
iex> abs(Enum.at(probs, 1) - 1.0) < 0.01
true
Applies a rotation around the Y-axis.
Examples
iex> q = Qx.Qubit.new() |> Qx.Qubit.ry(:math.pi() / 2)
iex> probs = Qx.Qubit.measure_probabilities(q) |> Nx.to_flat_list()
iex> abs(Enum.at(probs, 0) - 0.5) < 0.01
true
Applies a rotation around the Z-axis.
Examples
iex> q = Qx.Qubit.new() |> Qx.Qubit.h() |> Qx.Qubit.rz(:math.pi() / 4)
iex> Qx.Qubit.valid?(q)
true
Applies an S gate (π/2 phase) to a qubit.
Examples
iex> q = Qx.Qubit.new() |> Qx.Qubit.s()
iex> Qx.Qubit.valid?(q)
true
Returns a map containing formatted state information.
This function returns a map with human-readable representations of the qubit state, including Dirac notation, complex amplitudes, and measurement probabilities.
Returns
A map with keys:
:state- Dirac notation string (e.g., "0.707|0⟩ + 0.707|1⟩"):amplitudes- List of tuples with basis states and complex amplitudes:probabilities- List of tuples with basis states and measurement probabilities
Pipeline Usage
⚠️ Note: This function returns display data (a map) and ends the pipeline.
To inspect state while continuing a pipeline, use tap_state/2:
qubit
|> h()
|> tap_state(label: "After H gate") # Shows state, returns qubit
|> x() # Pipeline continues
|> tap_state(label: "After X gate")To get the display map at the end of a pipeline:
state_info =
qubit
|> h()
|> x()
|> show_state() # Terminal operation, returns the map
IO.puts(state_info.state)Examples
iex> q = Qx.Qubit.new() |> Qx.Qubit.h()
iex> info = Qx.Qubit.show_state(q)
iex> is_map(info)
true
iex> q = Qx.Qubit.plus()
iex> info = Qx.Qubit.show_state(q)
iex> info.state =~ "|0⟩"
trueSee also: tap_state/2 for pipeline-friendly state inspection.
Returns the state vector of the qubit.
Examples
iex> q = Qx.Qubit.new()
iex> Qx.Qubit.state_vector(q)
#Nx.Tensor<
c64[2]
[1.0+0.0i, 0.0+0.0i]
>
Applies a T gate (π/4 phase) to a qubit.
Examples
iex> q = Qx.Qubit.new() |> Qx.Qubit.t()
iex> Qx.Qubit.valid?(q)
true
Inspects the qubit state and returns the original qubit (pipeline-friendly).
This function is designed for debugging within pipelines. It displays the state as a side effect but returns the qubit unchanged, allowing the pipeline to continue.
Options
:label- Custom label for the output (default: "Qubit State"):verbose- Show detailed probabilities (default: false)
vs. show_state/1
tap_state/2- Shows state, returns qubit (continues pipeline)show_state/1- Returns display map (ends pipeline)
Examples
Basic debugging in a pipeline:
result =
Qx.Qubit.new()
|> Qx.Qubit.h()
|> Qx.Qubit.tap_state(label: "After Hadamard")
|> Qx.Qubit.x()
|> Qx.Qubit.tap_state(label: "After X gate")
|> Qx.Qubit.y()Verbose mode to see detailed probabilities:
qubit
|> Qx.Qubit.rx(:math.pi() / 4)
|> Qx.Qubit.tap_state(label: "After rotation", verbose: true)Multiple inspection points throughout a pipeline:
qubit
|> Qx.Qubit.tap_state(label: "Initial state")
|> Qx.Qubit.h()
|> Qx.Qubit.tap_state(label: "Superposition")
|> Qx.Qubit.rz(:math.pi() / 2)
|> Qx.Qubit.tap_state(label: "After phase rotation")Doctest example:
iex> q = Qx.Qubit.new()
...> |> Qx.Qubit.h()
...> |> Qx.Qubit.tap_state(label: "After Hadamard")
...> |> Qx.Qubit.x()
iex> Qx.Qubit.valid?(q)
trueSee also: show_state/1 for getting the state as a map (terminal operation).
@spec valid?(Nx.Tensor.t()) :: boolean()
Checks if a given state vector represents a valid qubit.
A valid qubit must:
- Have exactly 2 complex components (shape {2})
- Be normalized (|α|² + |β|² = 1)
Examples
iex> valid_qubit = Qx.Qubit.new(0.6, 0.8)
iex> Qx.Qubit.valid?(valid_qubit)
true
iex> invalid_qubit = Nx.tensor([Complex.new(1.0, 0.0), Complex.new(1.0, 0.0)], type: :c64)
iex> Qx.Qubit.valid?(invalid_qubit)
falsePipeline Usage
⚠️ This is a terminal operation that returns a boolean, not a qubit.
For pipeline-friendly state inspection, use tap_state/2.
Applies a Pauli-X gate (bit flip) to a qubit.
Transforms |0⟩ ↔ |1⟩.
Examples
iex> q = Qx.Qubit.new() |> Qx.Qubit.x()
iex> probs = Qx.Qubit.measure_probabilities(q) |> Nx.to_flat_list()
iex> Enum.at(probs, 1)
1.0
Applies a Pauli-Y gate to a qubit.
Examples
iex> q = Qx.Qubit.new() |> Qx.Qubit.y()
iex> Qx.Qubit.valid?(q)
true
Applies a Pauli-Z gate (phase flip) to a qubit.
Examples
iex> q = Qx.Qubit.new() |> Qx.Qubit.z()
iex> Qx.Qubit.valid?(q)
true