Circuit-Side Simulation Examples

This example focuses on GraphQOMB’s circuit-level simulation APIs, including MBQC-native circuits, macro-gate circuits, and phase gadgets.

import math

import numpy as np

from graphqomb.circuit import Circuit, MBQCCircuit
from graphqomb.gates import CNOT, CZ, H, Rz, X
from graphqomb.simulator import CircuitSimulator, SimulatorBackend

Simple MBQC Circuit Example

Create a simple MBQC circuit with basic J gates and CZ gates

circuit = MBQCCircuit(num_qubits=2)

# Add some basic operations
circuit.j(qubit=0, angle=math.pi / 4)
circuit.j(qubit=1, angle=math.pi / 2)
circuit.cz(qubit1=0, qubit2=1)
circuit.j(qubit=0, angle=-math.pi / 4)

print(f"Circuit has {circuit.num_qubits} qubits")
instructions = circuit.instructions()
print(f"Circuit has {len(instructions)} instructions:")
for i, instr in enumerate(instructions):
    print(f"  {i}: {instr}")
Circuit has 2 qubits
Circuit has 4 instructions:
  0: J(qubit=0, angle=0.7853981633974483)
  1: J(qubit=1, angle=1.5707963267948966)
  2: CZ(qubits=(0, 1))
  3: J(qubit=0, angle=-0.7853981633974483)

Simulate the MBQC circuit

simulator = CircuitSimulator(mbqc_circuit=circuit, backend=SimulatorBackend.StateVector)
simulator.simulate()

# Get final state
final_state = simulator.state
print(f"Final state shape: {final_state.state().shape}")
print(f"Final state norm: {final_state.norm():.6f}")

# Print final state vector
state_vec = final_state.state()
print("Final state vector:")
flat_state = state_vec.ravel()
TOLERANCE = 1e-10
for i, amp in enumerate(flat_state):
    if abs(amp) > TOLERANCE:
        print(f"  |{i:02b}⟩: {amp:.6f}")
Final state shape: (2, 2)
Final state norm: 1.000000
Final state vector:
  |00⟩: 0.250000+0.250000j
  |01⟩: 0.603553-0.103553j
  |10⟩: 0.103553+0.603553j
  |11⟩: 0.250000-0.250000j

Macro Gate Circuit Example

Create a circuit with high-level macro gates

macro_circuit = Circuit(num_qubits=3)

# Add macro gates
macro_circuit.apply_macro_gate(H(qubit=0))  # Hadamard on qubit 0
macro_circuit.apply_macro_gate(X(qubit=1))  # Pauli-X on qubit 1
macro_circuit.apply_macro_gate(CNOT(qubits=(0, 1)))  # CNOT gate
macro_circuit.apply_macro_gate(Rz(qubit=2, angle=math.pi / 3))  # Rz rotation
macro_circuit.apply_macro_gate(CZ(qubits=(1, 2)))  # CZ gate

print(f"Circuit has {macro_circuit.num_qubits} qubits")
macro_instructions = macro_circuit.instructions()
print(f"Circuit has {len(macro_instructions)} macro instructions:")
for i, instr in enumerate(macro_instructions):
    print(f"  {i}: {instr}")
Circuit has 3 qubits
Circuit has 5 macro instructions:
  0: H(qubit=0)
  1: X(qubit=1)
  2: CNOT(qubits=(0, 1))
  3: Rz(qubit=2, angle=1.0471975511965976)
  4: CZ(qubits=(1, 2))

Convert to unit gates for simulation

unit_instructions = macro_circuit.unit_instructions()
print(f"Expanded to {len(unit_instructions)} unit instructions:")
for i, instr in enumerate(unit_instructions):
    print(f"  {i}: {instr}")
Expanded to 9 unit instructions:
  0: J(qubit=0, angle=0)
  1: J(qubit=1, angle=0)
  2: J(qubit=1, angle=3.141592653589793)
  3: J(qubit=1, angle=0)
  4: CZ(qubits=(0, 1))
  5: J(qubit=1, angle=0)
  6: J(qubit=2, angle=1.0471975511965976)
  7: J(qubit=2, angle=0)
  8: CZ(qubits=(1, 2))

Simulate the macro circuit

simulator = CircuitSimulator(mbqc_circuit=macro_circuit, backend=SimulatorBackend.StateVector)
simulator.simulate()

# Get final state
final_state = simulator.state
print(f"Final state shape: {final_state.state().shape}")
print(f"Final state norm: {final_state.norm():.6f}")

# Print final state vector
state_vec = final_state.state()
print("Final state vector:")
flat_state = state_vec.ravel()
for i, amp in enumerate(flat_state):
    if abs(amp) > TOLERANCE:
        print(f"  |{i:03b}⟩: {amp:.6f}")
Final state shape: (2, 2, 2)
Final state norm: 1.000000
Final state vector:
  |000⟩: 0.433013-0.250000j
  |001⟩: 0.433013+0.250000j
  |010⟩: 0.433013-0.250000j
  |011⟩: -0.433013-0.250000j

Phase Gadget Circuit Example

Create a circuit with phase gadgets

circuit = MBQCCircuit(num_qubits=3)

# Prepare initial state
circuit.j(qubit=0, angle=math.pi / 2)
circuit.j(qubit=1, angle=math.pi / 4)

# Add phase gadget
circuit.phase_gadget(qubits=[0, 1, 2], angle=math.pi / 6)

# Final rotations
circuit.j(qubit=2, angle=-math.pi / 3)

print(f"Circuit has {circuit.num_qubits} qubits")
instructions = circuit.instructions()
print(f"Circuit has {len(instructions)} instructions:")
for i, instr in enumerate(instructions):
    print(f"  {i}: {instr}")
Circuit has 3 qubits
Circuit has 4 instructions:
  0: J(qubit=0, angle=1.5707963267948966)
  1: J(qubit=1, angle=0.7853981633974483)
  2: PhaseGadget(qubits=[0, 1, 2], angle=0.5235987755982988)
  3: J(qubit=2, angle=-1.0471975511965976)

Simulate the phase gadget circuit

simulator = CircuitSimulator(mbqc_circuit=circuit, backend=SimulatorBackend.StateVector)
simulator.simulate()

# Get final state
final_state = simulator.state
print(f"Final state shape: {final_state.state().shape}")
print(f"Final state norm: {final_state.norm():.6f}")

# Calculate some expectation values
pauli_z = np.array([[1, 0], [0, -1]], dtype=complex)
expectation_z0 = final_state.expectation(pauli_z, 0)
expectation_z1 = final_state.expectation(pauli_z, 1)
expectation_z2 = final_state.expectation(pauli_z, 2)

print(f"⟨Z₀⟩ = {expectation_z0:.6f}")
print(f"⟨Z₁⟩ = {expectation_z1:.6f}")
print(f"⟨Z₂⟩ = {expectation_z2:.6f}")
Final state shape: (2, 2, 2)
Final state norm: 1.000000
⟨Z₀⟩ = 0.000000
⟨Z₁⟩ = 0.707107
⟨Z₂⟩ = 0.433013

Total running time of the script: (0 minutes 0.007 seconds)

Gallery generated by Sphinx-Gallery