Qx.Operations (Qx - Quantum Computing Simulator v0.6.0)
View SourceQuantum gate operations for quantum circuits.
This module provides functions for applying quantum gates to quantum circuits, including single-qubit gates (H, X, Y, Z), two-qubit gates (CNOT), and three-qubit gates (CCNOT/Toffoli).
Summary
Functions
Adds a barrier to the circuit for visualization purposes.
Applies gates conditionally based on a classical bit value.
Applies a controlled-controlled-X (CCNOT/Toffoli) gate.
Applies a controlled-phase (CP) gate.
Applies a Fredkin (controlled-SWAP) gate.
Applies a controlled-X (CNOT) gate.
Applies a controlled-Z (CZ) gate.
Applies a Hadamard gate to the specified qubit.
Applies an iSWAP gate, exchanging qubit states while applying an i phase factor to the swapped components.
Adds a measurement operation to the circuit.
Applies a phase gate with the specified phase.
Applies a rotation around the X-axis by the specified angle.
Applies a rotation around the Y-axis by the specified angle.
Applies a rotation around the Z-axis by the specified angle.
Applies an S gate (phase gate with π/2 phase).
Applies an S† (S-dagger) gate (-π/2 phase on |1⟩).
Applies a SWAP gate, exchanging the quantum states of two qubits.
Applies a T gate (phase gate with π/4 phase).
Inspects the circuit without breaking the pipeline.
Inspects measurement probabilities without breaking the pipeline.
Inspects the current quantum state without breaking the pipeline.
Applies the general single-qubit unitary gate U(θ,φ,λ) (IBM/OpenQASM 3 convention).
Applies a Pauli-X gate (bit flip) to the specified qubit.
Applies a Pauli-Y gate to the specified qubit.
Applies a Pauli-Z gate (phase flip) to the specified qubit.
Functions
Adds a barrier to the circuit for visualization purposes.
Barriers are used to group operations and improve circuit readability. They do not affect the quantum state.
Parameters
circuit- The quantum circuitqubits- List of qubit indices the barrier spans
Examples
iex> qc = Qx.QuantumCircuit.new(3, 0)
iex> qc = Qx.Operations.barrier(qc, [0, 1, 2])
iex> [{gate, qubits, _params}] = Qx.QuantumCircuit.get_instructions(qc)
iex> {gate, qubits}
{:barrier, [0, 1, 2]}
Applies gates conditionally based on a classical bit value.
The conditional block executes during simulation only if the specified classical bit equals the given value at runtime.
Parameters
circuit- The quantum circuitclassical_bit- Classical bit index to check (0-based)value- Value to compare (0 or 1)gate_fn- Function that applies gates: (circuit -> circuit)
Examples
iex> qc = Qx.QuantumCircuit.new(2, 2)
iex> qc = qc |> Qx.Operations.h(0) |> Qx.Operations.measure(0, 0)
iex> qc = Qx.Operations.c_if(qc, 0, 1, fn c -> Qx.Operations.x(c, 1) end)
iex> instructions = Qx.QuantumCircuit.get_instructions(qc)
iex> length(instructions)
2Constraints
- Classical bit must be valid for the circuit
- Value must be 0 or 1
- Gates in conditional block cannot contain measurements
- No nesting of conditional blocks
Applies a controlled-controlled-X (CCNOT/Toffoli) gate.
The CCNOT gate flips the target qubit if and only if both control qubits are |1⟩.
Parameters
circuit- The quantum circuitcontrol1- First control qubit indexcontrol2- Second control qubit indextarget- Target qubit index
Examples
iex> qc = Qx.QuantumCircuit.new(3, 0)
iex> qc = Qx.Operations.ccx(qc, 0, 1, 2)
iex> [{gate, qubits, _params}] = Qx.QuantumCircuit.get_instructions(qc)
iex> {gate, qubits}
{:ccx, [0, 1, 2]}
Applies a controlled-phase (CP) gate.
The CP gate applies a phase of e^(i*theta) to the |11⟩ basis state only. All other basis states are unchanged.
Parameters
circuit- The quantum circuitcontrol_qubit- Control qubit indextarget_qubit- Target qubit indextheta- Phase angle in radians
Examples
iex> qc = Qx.QuantumCircuit.new(2, 0)
iex> qc = Qx.Operations.cp(qc, 0, 1, :math.pi())
iex> [{gate, qubits, _params}] = Qx.QuantumCircuit.get_instructions(qc)
iex> {gate, qubits}
{:cp, [0, 1]}Raises
FunctionClauseError- If qubit indices are out of range or equalArgumentError- If theta is not a number
Applies a Fredkin (controlled-SWAP) gate.
Swaps the quantum states of target_a and target_b when the control qubit is |1⟩.
When the control qubit is |0⟩, the targets are left unchanged.
Parameters
circuit- The quantum circuitcontrol- Control qubit indextarget_a- First target qubit indextarget_b- Second target qubit index
Examples
iex> qc = Qx.QuantumCircuit.new(3, 0)
iex> qc = Qx.Operations.cswap(qc, 0, 1, 2)
iex> [{gate, qubits, _params}] = Qx.QuantumCircuit.get_instructions(qc)
iex> {gate, qubits}
{:cswap, [0, 1, 2]}Raises
ArgumentError- If any two qubit indices are equal or any index is out of range
Applies a controlled-X (CNOT) gate.
The CNOT gate flips the target qubit if and only if the control qubit is |1⟩.
Parameters
circuit- The quantum circuitcontrol_qubit- Control qubit indextarget_qubit- Target qubit index
Examples
iex> qc = Qx.QuantumCircuit.new(2, 0)
iex> qc = Qx.Operations.cx(qc, 0, 1)
iex> [{gate, qubits, _params}] = Qx.QuantumCircuit.get_instructions(qc)
iex> {gate, qubits}
{:cx, [0, 1]}
Applies a controlled-Z (CZ) gate.
The CZ gate applies a phase of -1 if and only if both qubits are |1⟩.
Parameters
circuit- The quantum circuitcontrol_qubit- Control qubit indextarget_qubit- Target qubit index
Examples
iex> qc = Qx.QuantumCircuit.new(2, 0)
iex> qc = Qx.Operations.cz(qc, 0, 1)
iex> [{gate, qubits, _params}] = Qx.QuantumCircuit.get_instructions(qc)
iex> {gate, qubits}
{:cz, [0, 1]}
Applies a Hadamard gate to the specified qubit.
The Hadamard gate creates superposition, transforming |0⟩ to (|0⟩ + |1⟩)/√2 and |1⟩ to (|0⟩ - |1⟩)/√2.
Parameters
circuit- The quantum circuitqubit- Target qubit index
Examples
iex> qc = Qx.QuantumCircuit.new(2, 0)
iex> qc = Qx.Operations.h(qc, 0)
iex> [{gate, qubits, _params}] = Qx.QuantumCircuit.get_instructions(qc)
iex> {gate, qubits}
{:h, [0]}
Applies an iSWAP gate, exchanging qubit states while applying an i phase factor to the swapped components.
Parameters
circuit- The quantum circuitqubit_a- Index of the first qubitqubit_b- Index of the second qubit
Examples
iex> qc = Qx.QuantumCircuit.new(2, 0)
iex> qc = Qx.Operations.iswap(qc, 0, 1)
iex> [{gate, qubits, _params}] = Qx.QuantumCircuit.get_instructions(qc)
iex> {gate, qubits}
{:iswap, [0, 1]}Raises
FunctionClauseError- If qubit indices are out of range or equal
Adds a measurement operation to the circuit.
Parameters
circuit- The quantum circuitqubit- Qubit index to measureclassical_bit- Classical bit index to store the result
Examples
iex> qc = Qx.QuantumCircuit.new(2, 2)
iex> qc = Qx.Operations.measure(qc, 0, 0)
iex> [{qubit, classical_bit}] = Qx.QuantumCircuit.get_measurements(qc)
iex> {qubit, classical_bit}
{0, 0}
Applies a phase gate with the specified phase.
Parameters
circuit- The quantum circuitqubit- Target qubit indexphi- Phase angle in radians
Examples
iex> qc = Qx.QuantumCircuit.new(1, 0)
iex> qc = Qx.Operations.phase(qc, 0, :math.pi/4)
iex> [{gate, qubits, params}] = Qx.QuantumCircuit.get_instructions(qc)
iex> {gate, qubits, length(params)}
{:phase, [0], 1}
Applies a rotation around the X-axis by the specified angle.
Parameters
circuit- The quantum circuitqubit- Target qubit indextheta- Rotation angle in radians
Examples
iex> qc = Qx.QuantumCircuit.new(1, 0)
iex> qc = Qx.Operations.rx(qc, 0, :math.pi/2)
iex> [{gate, qubits, params}] = Qx.QuantumCircuit.get_instructions(qc)
iex> {gate, qubits, length(params)}
{:rx, [0], 1}
Applies a rotation around the Y-axis by the specified angle.
Parameters
circuit- The quantum circuitqubit- Target qubit indextheta- Rotation angle in radians
Examples
iex> qc = Qx.QuantumCircuit.new(1, 0)
iex> qc = Qx.Operations.ry(qc, 0, :math.pi/2)
iex> [{gate, qubits, params}] = Qx.QuantumCircuit.get_instructions(qc)
iex> {gate, qubits, length(params)}
{:ry, [0], 1}
Applies a rotation around the Z-axis by the specified angle.
Parameters
circuit- The quantum circuitqubit- Target qubit indextheta- Rotation angle in radians
Examples
iex> qc = Qx.QuantumCircuit.new(1, 0) iex> qc = Qx.Operations.rz(qc, 0, :math.pi/2) iex> [{gate, qubits, params}] = Qx.QuantumCircuit.get_instructions(qc) iex> {gate, qubits, length(params)}
Applies an S gate (phase gate with π/2 phase).
Parameters
circuit- The quantum circuitqubit- Target qubit index
Examples
iex> qc = Qx.QuantumCircuit.new(1, 0)
iex> qc = Qx.Operations.s(qc, 0)
iex> [{gate, qubits, _params}] = Qx.QuantumCircuit.get_instructions(qc)
iex> {gate, qubits}
{:s, [0]}
Applies an S† (S-dagger) gate (-π/2 phase on |1⟩).
Parameters
circuit- The quantum circuitqubit- Target qubit index
Examples
iex> qc = Qx.QuantumCircuit.new(1, 0)
iex> qc = Qx.Operations.sdg(qc, 0)
iex> [{gate, qubits, _params}] = Qx.QuantumCircuit.get_instructions(qc)
iex> {gate, qubits}
{:sdg, [0]}
Applies a SWAP gate, exchanging the quantum states of two qubits.
Parameters
circuit- The quantum circuitqubit_a- Index of the first qubitqubit_b- Index of the second qubit
Examples
iex> qc = Qx.QuantumCircuit.new(2, 0)
iex> qc = Qx.Operations.swap(qc, 0, 1)
iex> [{gate, qubits, _params}] = Qx.QuantumCircuit.get_instructions(qc)
iex> {gate, qubits}
{:swap, [0, 1]}Raises
FunctionClauseError- If qubit indices are out of range or equal
Applies a T gate (phase gate with π/4 phase).
Parameters
circuit- The quantum circuitqubit- Target qubit index
Examples
iex> qc = Qx.QuantumCircuit.new(1, 0)
iex> qc = Qx.Operations.t(qc, 0)
iex> [{gate, qubits, _params}] = Qx.QuantumCircuit.get_instructions(qc)
iex> {gate, qubits}
{:t, [0]}
@spec tap_circuit(Qx.QuantumCircuit.t(), (Qx.QuantumCircuit.t() -> any())) :: Qx.QuantumCircuit.t()
Inspects the circuit without breaking the pipeline.
The provided function receives the circuit and can perform any side-effect (logging, printing, assertions), but the return value is ignored and the original circuit is returned.
Parameters
circuit- The quantum circuitfun- Function to execute:(circuit -> any())
Examples
iex> circuit = Qx.QuantumCircuit.new(2, 0)
...> |> Qx.Operations.h(0)
...> |> Qx.Operations.tap_circuit(&IO.inspect(&1.instructions, label: "After H"))
...> |> Qx.Operations.cx(0, 1)
After H: [{:h, [0], []}]
%Qx.QuantumCircuit{...}
# Create circuit and inspect depth/qubits
circuit = Qx.QuantumCircuit.new(3, 0)
|> Qx.Operations.h(0)
|> Qx.Operations.tap_circuit(fn circ ->
IO.puts("Depth: #{Qx.QuantumCircuit.depth(circ)}")
IO.puts("Qubits: #{circ.num_qubits}")
end)
|> Qx.Operations.x(1)
# Outputs:
# Depth: 1
# Qubits: 3See Also
tap_state/2- Inspect quantum statetap_probabilities/2- Inspect measurement probabilities
@spec tap_probabilities(Qx.QuantumCircuit.t(), (Nx.Tensor.t() -> any())) :: Qx.QuantumCircuit.t()
Inspects measurement probabilities without breaking the pipeline.
Convenience function that computes probabilities and passes them to your inspection function.
Parameters
circuit- The quantum circuitfun- Function to execute:(Nx.Tensor.t() -> any())
Examples
iex> circuit = Qx.QuantumCircuit.new(2, 2)
...> |> Qx.Operations.h(0)
...> |> Qx.Operations.cx(0, 1)
...> |> Qx.Operations.tap_probabilities(&IO.inspect/1)
...> |> Qx.Operations.measure(0, 0)
#Nx.Tensor<
f32[4]
[0.5, 0.0, 0.0, 0.5]
>
%Qx.QuantumCircuit{...}
# Create circuit and inspect probabilities
circuit = Qx.QuantumCircuit.new(1, 0)
|> Qx.Operations.h(0)
|> Qx.Operations.tap_probabilities(fn probs ->
prob_list = Nx.to_list(probs)
IO.puts("P(|0⟩) = #{Enum.at(prob_list, 0)}")
IO.puts("P(|1⟩) = #{Enum.at(prob_list, 1)}")
end)
# Outputs:
# P(|0⟩) = 0.5
# P(|1⟩) = 0.5See Also
tap_state/2- Inspect full quantum statetap_circuit/2- Inspect circuit metadata
@spec tap_state(Qx.QuantumCircuit.t(), (Nx.Tensor.t() -> any())) :: Qx.QuantumCircuit.t()
Inspects the current quantum state without breaking the pipeline.
Important: This executes all instructions so far to get the current state. Use sparingly in performance-critical code.
Parameters
circuit- The quantum circuitfun- Function to execute:(Nx.Tensor.t() -> any())
Examples
iex> circuit = Qx.QuantumCircuit.new(1, 0)
...> |> Qx.Operations.h(0)
...> |> Qx.Operations.tap_state(&IO.inspect(&1, label: "After H gate"))
...> |> Qx.Operations.z(0)
After H gate: #Nx.Tensor<...>
%Qx.QuantumCircuit{...}
iex> circuit = Qx.QuantumCircuit.new(2, 0)
...> |> Qx.Operations.h(0)
...> |> Qx.Operations.tap_state(fn state ->
...> probs = Qx.Math.probabilities(state)
...> IO.inspect(Nx.to_list(probs), label: "Probabilities")
...> end)
...> |> Qx.Operations.cx(0, 1)
Probabilities: [0.5, 0.5, 0.0, 0.0]
%Qx.QuantumCircuit{...}See Also
tap_circuit/2- Inspect circuit metadatatap_probabilities/2- Inspect measurement probabilities directly
Applies the general single-qubit unitary gate U(θ,φ,λ) (IBM/OpenQASM 3 convention).
U(θ,φ,λ) = [[cos(θ/2), -e^(iλ)·sin(θ/2) ],
[e^(iφ)·sin(θ/2), e^(i(φ+λ))·cos(θ/2) ]]Special cases:
- U(π, 0, π) = X gate
- U(π/2, 0, π) = H gate
Parameters
circuit- The quantum circuitqubit- Target qubit indextheta- Polar angle in radiansphi- Azimuthal angle in radianslambda- Additional phase angle in radians
Examples
iex> qc = Qx.QuantumCircuit.new(1, 0)
iex> qc = Qx.Operations.u(qc, 0, :math.pi(), 0, :math.pi())
iex> [{gate, qubits, params}] = Qx.QuantumCircuit.get_instructions(qc)
iex> {gate, qubits, length(params)}
{:u, [0], 3}Raises
ArgumentError- if theta, phi, or lambda is not a numberFunctionClauseError- if qubit index is out of range
Applies a Pauli-X gate (bit flip) to the specified qubit.
The X gate flips |0⟩ to |1⟩ and |1⟩ to |0⟩.
Parameters
circuit- The quantum circuitqubit- Target qubit index
Examples
iex> qc = Qx.QuantumCircuit.new(2, 0)
iex> qc = Qx.Operations.x(qc, 0)
iex> [{gate, qubits, _params}] = Qx.QuantumCircuit.get_instructions(qc)
iex> {gate, qubits}
{:x, [0]}
Applies a Pauli-Y gate to the specified qubit.
The Y gate applies both bit flip and phase flip transformations.
Parameters
circuit- The quantum circuitqubit- Target qubit index
Examples
iex> qc = Qx.QuantumCircuit.new(2, 0)
iex> qc = Qx.Operations.y(qc, 0)
iex> [{gate, qubits, _params}] = Qx.QuantumCircuit.get_instructions(qc)
iex> {gate, qubits}
{:y, [0]}
Applies a Pauli-Z gate (phase flip) to the specified qubit.
The Z gate leaves |0⟩ unchanged and applies a phase of -1 to |1⟩.
Parameters
circuit- The quantum circuitqubit- Target qubit index
Examples
iex> qc = Qx.QuantumCircuit.new(2, 0)
iex> qc = Qx.Operations.z(qc, 0)
iex> [{gate, qubits, _params}] = Qx.QuantumCircuit.get_instructions(qc)
iex> {gate, qubits}
{:z, [0]}