Quick Start Guide

Framework

Building on Julia, JuMP, and mixed-integer programming (MIP) solvers, QuantumCircuitOpt (QCOpt) is an open-source toolkit for optimal quantum circuit design. QCOpt provides an abstraction layer with two primary goals:

  1. Capture a target quantum computation, the available hardware-native gates, and circuit-design requirements in a JuMP optimization model.
  2. Extract, analyze, and validate the optimizer solution as an exact, globally phase-equivalent, or approximate circuit decomposition.

The optimization model searches over discrete gate choices and circuit depths, allowing QCOpt to certify global optimality for objectives such as circuit depth, CNOT count, and T-gate count.

QuantumCircuitOpt workflow QuantumCircuitOpt workflow

Presentations

  • May 2024: The CPAIOR 2024 Master Class slide deck discusses how emerging quantum computing technology can impact Constraint Programming (CP), Artificial Intelligence (AI), and Operations Research (OR), and vice versa.

  • November 2022: Presentation link from the Third Quantum Computing Software Workshop, held in conjunction with the International Conference on Supercomputing (SC22). This presentation introduces the role of nonlinear programming formulations in optimal quantum circuit design. Additional technical details are available in the associated paper.

  • July 2022: The JuliaCon 2022 presentation introduces the package and demonstrates its principal features. The conference program is available here.

Watch the JuliaCon 2022 presentation
  • November 2021: Presentation from the Second Quantum Computing Software Workshop, held in conjunction with the International Conference on Supercomputing (SC21). It presents the technical foundations of QuantumCircuitOpt, which are also described in the associated paper.
Watch the SC21 presentation

Getting started

Install QCOpt, JuMP, and a compatible MIP solver. Gurobi is recommended for computationally difficult instances. IBM CPLEX and the open-source HiGHS solver are also supported.

User inputs

Circuit specifications are passed as a Dict{String,Any} named params in the examples.

Mandatory circuit specificationsDescription
num_qubitsNumber of circuit qubits (2 to 10).
maximum_depthMaximum decomposition depth (at least 2).
elementary_gatesNonempty vector of supported one-, two-, or multi-qubit gate labels.
target_gateTarget unitary matrix to decompose.

If elementary_gates contains gates with continuous angle parameters, supply the corresponding discretizations:

Mandatory angle discretizationsDescription
RX_discretization, RY_discretization, RZ_discretizationAngles in radians for RXGate, RYGate, or RZGate.
Phase_discretizationAngles in radians for PhaseGate.
R_θ_discretization, R_ϕ_discretizationPolar and azimuthal angle grids in radians for RGate.
U3_θ_discretization, U3_ϕ_discretization, U3_λ_discretizationEuler-angle grids in radians for U3Gate.
CRX_discretization, CRY_discretization, CRZ_discretizationAngles in radians for controlled rotation gates.
CU3_θ_discretization, CU3_ϕ_discretization, CU3_λ_discretizationEuler-angle grids in radians for CU3Gate.
GR_θ_discretization, GR_ϕ_discretizationPolar and azimuthal angle grids in radians for GRGate.

U1Gate and U2Gate are available as matrix constructors. For discretized elementary-gate inputs, use the equivalent PhaseGate or U3Gate parameterizations.

Optional circuit specificationsDescription
objectiveminimize_depth, minimize_cnot, or minimize_T (default: minimize_depth). Include Identity when minimizing depth.
decomposition_typeexact_optimal, exact_feasible, optimal_global_phase, or approximate (default: exact_optimal).
initial_gateInitial condition at depth zero. Only Identity is currently supported (default: Identity).
set_cnot_lower_boundLower bound on the number of CNot/CX gates.
set_cnot_upper_boundUpper bound on the number of CNot/CX gates. Set both bounds to the same value to fix the count.
input_circuitWarm-start circuit as Vector{Tuple{Int64,String}}. Depths must be consecutive from 1, and every gate must occur in elementary_gates (default: empty).

Optimization model inputs

Model settings are passed through the optional options::Dict{Symbol,Any} keyword argument to build_QCModel or run_QCModel. Defaults are defined in get_default_options.

Optional model inputsDescription
model_typecompact_formulation or balas_formulation (default: compact_formulation).
all_valid_constraintsDisable (-1), configure individually (0), or enable (1) all valid inequalities (default: 0).
commute_gate_constraintsEliminate symmetric orderings of commuting gates (default: true).
involutory_gate_constraintsEliminate consecutive involutory gate pairs (default: true).
redundant_gate_pair_constraintsEliminate gate pairs equivalent to another elementary gate (default: true).
identity_gate_symmetry_constraintsEliminate identity-gate symmetry (default: true).
idempotent_gate_constraintsEliminate repeated idempotent gates (default: false).
convex_hull_gate_constraintsAdd convex-hull constraints for complex gate entries (default: false).
fix_unitary_variablesFix unitary variable entries whose values can be inferred (default: false).
unitary_constraintsAdd unitary-property constraints (default: false).
unitary_complex_conjugateConjugate-transpose constraints: disabled (0), linear (1), or linear and quadratic (2) (default: 1).
visualize_solutionPrint the decomposition after optimization (default: true).
relax_integralityRelax integer variables to continuous variables (default: false).
optimizer_logEnable optimizer console output (default: true).
objective_slack_penaltyApproximation slack penalty (default: 1e3).
time_limitOptimizer time limit in seconds (default: 10_800).

Sample circuit synthesis

This example minimizes the depth of a controlled-Z decomposition using CNOT and discretized U3 gates:

import QuantumCircuitOpt as QCOpt
using Gurobi
using JuMP

params = Dict{String,Any}(
    "num_qubits" => 2,
    "maximum_depth" => 4,
    "elementary_gates" => ["U3_1", "U3_2", "CNot_1_2", "Identity"],
    "target_gate" => ComplexF64[
        1 0 0 0
        0 1 0 0
        0 0 1 0
        0 0 0 -1
    ],
    "objective" => "minimize_depth",
    "decomposition_type" => "exact_optimal",
    "U3_θ_discretization" => -π:(π / 2):π,
    "U3_ϕ_discretization" => -π:(π / 2):π,
    "U3_λ_discretization" => -π:(π / 2):π,
)

model_options = Dict{Symbol,Any}(
    :model_type => "compact_formulation",
    :visualize_solution => true,
    :optimizer_log => false,
)

optimizer = optimizer_with_attributes(Gurobi.Optimizer, "Presolve" => 1)
results = QCOpt.run_QCModel(params, optimizer; options = model_options)

Change target_gate and elementary_gates to synthesize another circuit. See the examples directory for more decompositions.

Warning

Globally optimal quantum circuit synthesis is a combinatorial optimization problem whose computational cost can grow rapidly with num_qubits, maximum_depth, and the number of elementary gates. This difficulty is intrinsic to the circuit-synthesis problem; see this reference.

Tip

Commercial MIP optimizers such as Gurobi may be faster on difficult instances. Gurobi provides free academic licenses.

Extracting results

run_QCModel returns a Dict{String,Any}. Common result fields include:

  • optimizer
  • termination_status and primal_status
  • objective and objective_lb
  • solve_time
  • solution, which maps model variable names to their values

For example:

results["solve_time"]
results["objective"]

Visualizing results

run_QCModel prints a feasible decomposition by default. To render a saved result explicitly:

data = QCOpt.get_data(params)
QCOpt.visualize_solution(results, data)

The example produces the following output with Gurobi Optimizer 13.0.0:

=============================================================================
QuantumCircuitOpt version: 0.6.3

Quantum Circuit Data
  Number of qubits      : 2
  Maximum circuit depth : 4
  Decomposition type    : exact_optimal
  MIP optimizer         : Gurobi
  Number of input gates : 72 (presolved)
  Input gates : Qubits
      CNot : {1,2}
        U3 : 1,2
    U3_ϕ : [-180.0, -90.0, 0.0, 90.0, 180.0]
    U3_θ : [-180.0, -90.0, 0.0, 90.0, 180.0]
    U3_λ : [-180.0, -90.0, 0.0, 90.0, 180.0]

Optimal Circuit
  depth 1 : I ⊗ U3(90.0,0.0,180.0)
  depth 2 : CNot_{1,2}
  depth 3 : I ⊗ U3(90.0,0.0,180.0)

  Optimal number of gates : 3
  Optimal circuit depth   : 3
  Optimizer run time      : 1.7 sec.
=============================================================================