Amir Azzam1, Luke Mortimer1, Vyron Vasileiadis1, Natàlia Padilla Sirera1
1 Qilimanjaro Quantum Tech
Carrer de Veneçuela, 74, Sant Martí, 08019, Barcelona, Spain
Title
Body link
Contents
1. Introduction to QiliSDK
An overview of the QiliSDK architecture. The top layer contains the primitive components: cost functions, optimizers, analog and digital abstractions, and readout methods. The middle layer combines these primitives into complex workflows such as variational algorithms and functionals. The bottom layer handles execution, supporting real quantum hardware (QPU), classical simulation (GPU and CPU), and noise models.
- Primitive Modules used to construct quantum workflows:
- Analog: containing Hamiltonian and Schedule classes to define analog quantum workflows.
- Digital: offers Gate, Circuit, and pre-built Ansatz classes to define digital quantum workflows.
- Core: consisting of QTensor the fundamental quantum-tensor type, together with a parameter/variable system used to build an optimization Model. Generic optimization models are automatically linearized into QUBO form and can be exported as a Hamiltonian.
- Readout: methods to extract information from the quantum system after execution, including measurement samples, expectation values, or full-state tomography.
- Functionals: a unified abstraction for quantum workflows (sampling a circuit, evolving a Hamiltonian, running a variational program). Any functional can be dispatched to a compatible backend for execution through a common interface backend.execute(functional).
- Backends: run Functionals on a CPU, GPU, or QPU.
- CPU: the built-in QiliSim simulator supports digital, analog, and hybrid workflows. In addition, the QuTiP backend allows QiliSDK Functionals to be executed directly using the QuTiP library.
- GPU: a wrapper built on top of NVIDIA’s CUDA-Q library, enables the execution of both digital and analog QiliSDK workflows directly on a GPU.
- QPU: the SpeQtrum backend executes QiliSDK Functionals on Qilimanjaro’s QPUs.
pip install qilisdk. Optional extras provide support for GPU acceleration (cuda12/cuda13), QuTiP, OpenQASM, QIR, and other integrations.
QiliSDK is available on PyPI, documented at qilimanjaro-tech.github.io/qilisdk, and citable via Zenodo (DOI 10.5281/zenodo.20411054).
What’s new in 0.2.0. This release introduces QiliSim, a high-performance quantum simulator written in C++; a comprehensive noise-modeling framework covering digital, analog, and parameter noise; quantum reservoir computing primitives; migration of the core QTensor type to C++; interoperability with OpenQASM 2/3 and QIR; Trotterization of analog evolution; a composable circuit transpilation pipeline; and an expanded tutorial set with translations into Spanish and Catalan. The following sections cover each of these additions in more detail.
2. QiliSim: Qilimanjaro’s New Simulation Backend
QiliSim is Qilimanjaro’s native quantum simulator, implemented in C++ and accessible from Python. It is the default backend for simulating quantum circuits, Hamiltonian time evolution, and analog-digital quantum reservoirs. For small to medium problem sizes, QiliSim can achieve performance comparable to, and in some cases better than, GPU-based backends on standard CPU hardware.
The example below illustrates how to execute a digital quantum workload with QiliSim. A simple two-qubit Bell-state circuit is constructed, wrapped in a DigitalPropagation Functional, and executed on the QiliSim backend. A sampling readout is then applied to collect 500 measurement shots from the final quantum state that can be used for further analysis.
from qilisdk.digital import Circuit, H, CNOT
from qilisdk.backends import QiliSim
from qilisdk.functionals import DigitalPropagation
from qilisdk.readout import Readout
# Build a simple circuit
circuit = Circuit(2)
circuit.add(H(0))
circuit.add(CNOT(0, 1))
# Create DigitalPropagation functional
functional = DigitalPropagation(circuit)
# Execute with the QiliSim backend
backend = QiliSim()
result = backend.execute(functional, Readout().with_sampling(nshots=500))
print(result.get_samples())
Configurable simulation methods
QiliSim provides a set of simulation strategies through structured configuration objects (ExecutionConfig, DigitalMethod, AnalogMethod, MonteCarloConfig).- Digital (circuit) simulation uses state-vector propagation. By default, a matrix-free implementation is enabled (DigitalMethod.statevector(matrix_free=True)), which avoids materializing large gate matrices.
- Analog (time-evolution) simulation supports several integrators:
- AnalogMethod.integrator(): optimized fixed-step integrator (about 4× faster in 0.2.0), matrix-free by default.
- AnalogMethod.adaptive_integrator(): adaptive Dormand–Prince RK45 scheme with automatic step selection.
- AnalogMethod.arnoldi(): Arnoldi/Krylov-subspace exponentiation for stiff or large systems.
- AnalogMethod.direct(): direct matrix exponentiation, suitable for small systems.
- Monte-Carlo trajectory simulation can also be layered on top of any of the above (MonteCarloConfig(trajectories=…)).
from qilisdk.backends import QiliSim, ExecutionConfig, AnalogMethod, MonteCarloConfig
backend = QiliSim(
execution_config=ExecutionConfig(
analog_method=AnalogMethod.adaptive_integrator(tol=1e-3),
monte_carlo=MonteCarloConfig(trajectories=200),
)
)
3. Noise Models
Note: Noise Models are currently supported only on QiliSim and CUDA backends. The QuTiP backend doesn’t support them yet.
- The quantum state (channel noise): predefined channels BitFlip, PhaseFlip, Depolarizing, AmplitudeDamping, Dephasing, and the general PauliChannel.
- The control parameters (parameter noise): GaussianPerturbation, OffsetPerturbation, and the base ParameterPerturbation, capturing imperfect calibration.
- The measurement outcomes (readout noise): represented through ReadoutAssignment.
An overview of the QiliSDK architecture. The top layer contains the primitive components: cost functions, optimizers, analog and digital abstractions, and readout methods. The middle layer combines these primitives into complex workflows such as variational algorithms and functionals. The bottom layer handles execution, supporting real quantum hardware (QPU), classical simulation (GPU and CPU), and noise models.
In the example below, a BitFlip channel with a 2% error probability is applied to qubits 0 and 1 using the QiliSim backend. Because noise models are backend agnostic, the same definition can be reused unchanged on the CUDA backend to execute the simulation on a GPU. The documentation also provides a mathematical description of each sup<ported noise type.
from qilisdk.noise import NoiseModel, BitFlip
from qilisdk.backends import QiliSim
noise = NoiseModel()
noise.add(BitFlip(probability=0.02), qubits=[0, 1])
backend = QiliSim(noise_model=noise) # identical API on the CUDA backend
4. Quantum Reservoir Computing
QiliSDK 0.2.0 introduces support for Quantum Reservoir Computing (QRC), a quantum machine-learning paradigm in which a fixed quantum system (the “reservoir”) projects inputs into a high-dimensional feature space. Only a simple linear classical readout layer is trained, while the quantum dynamics are observed, not trained. This approach leverages the natural dynamics of the quantum system, making it well suited to near-term analog quantum hardware.
The API introduces three primitives:
- Quantum Reservoir: top-level component that orchestrates a sequence of reservoir layers.
- Reservoir Layer: single layer template with three sequential stages: input_encoding → evolution_dynamics → output_encoding. The evolution is driven by an analog Schedule, while optional single-qubit encoding circuits can be used to inject input data and post-process data. Selected qubits can also be reset between consecutive layers.
- Reservoir Input: non-trainable parameter used to inject layer-wise data into the reservoir. Inputs can be incorporated anywhere in a layer: as parameters of gates in the input or output encoding circuits, or as coefficients on the local fields and couplings of the analog evolution Hamiltonian.
The quantum reservoir layer workflow. Each layer consists of optional digital pre- and post-processing steps surrounding an analog evolution, any of which can serve as data input points. The state is then measured and qubit-reset, producing an output that is passed to the next reservoir layer.
Backends execute reservoir workflows natively, injecting inputs at each layer through the encoding stages and collecting the observables measured after every layer as a feature vector for downstream learning.
The example below defines a two-qubit quantum reservoir in which layer-specific inputs are injected through a parameterized encoding circuit. Each layer evolves under an analog Hamiltonian featuring local fields and qubit-qubit interactions, with one qubit reset between layers. The reservoir is executed on QiliSim, and expectation values of selected observables are measured after each layer, producing the feature vectors.
import numpy as np
from qilisdk.backends import QiliSim
from qilisdk.core import ket, QTensor
from qilisdk.digital import Circuit, U2
from qilisdk.functionals.quantum_reservoirs import QuantumReservoir, ReservoirInput, ReservoirLayer
from qilisdk.analog import Schedule, X, Z
from qilisdk.readout import Readout
pre_processing = Circuit(2)
pre_processing.add(U2(1, phi=ReservoirInput("phi_1", 0.1), gamma=ReservoirInput("gamma_1", 0.1)))
res_layer = ReservoirLayer(
evolution_dynamics=Schedule(
hamiltonians={"h": Z(0) + Z(1) + Z(0) * Z(1) + 0.5 * (X(0) + X(1))},
total_time=1.0,
dt=0.01,
),
input_encoding=pre_processing,
qubits_to_reset=[1],
)
reservoir = QuantumReservoir(
initial_state=QTensor.uniform(2),
reservoir_layer=res_layer,
input_per_layer=[
{"phi_1": 0.2, "gamma_1": 0.1},
{"phi_1": 0.3, "gamma_1": 0.2},
{"phi_1": 0.4, "gamma_1": 0.3},
],
)
results = QiliSim().execute(
reservoir,
Readout().with_expectation(observables=[Z(0), Z(1), Z(0) * Z(1)]),
)
print(results)
5. QTensor in C++: Quantum Information Processing
An overview of the QTensor class operations. QTensor is QiliSDK’s core data structure for representing quantum states and operators in sparse form, supporting kets, bras, density matrices, and scalars. Its operations are grouped into standard matrix operations (exponential, logarithm, square root, eigen decomposition, trace, and more), state initialization helpers (zero, uniform, GHZ, ket, bra, identity, basis state), and quantum-specific operations (partial trace, entropy, commutator, anticommutator, fidelity, and probabilities).
- Standard matrix operations. QTensor exposes matrix functions and decompositions directly on quantum operators and states: exp (matrix exponential), log, sqrt, integer/fractional pow, eigen decomposition (eig), rank, trace, and a family of norms (Frobenius, trace/nuclear, ℓ1/ℓ2/∞). These capabilities allow to manipulate Hamiltonians and density matrices analytically, for example to build Lindbladians, compute operator functions, or check spectral properties.
- State and operator initialization. Convenient constructors for many commonly used quantum states and operators, including zero, identity, QTensor.uniform(n) (uniform superposition), ghz (maximally entangled GHZ states), ket/bra, and basis_state.
- Quantum-information primitives. Native methods for the standard quantities of quantum-information science:
-
- partial_trace: reduction to subsystems for studying entanglement and correlations.
- entropy_von_neumann and entropy_renyi(α): measures of quantum state entropy.
- fidelity: comparison of states, for instance against an ideal target for benchmarking or tomography.
- commutator and anticommutator: algebraic structure of operators and conserved quantities.
- probabilities and expectation_value: measurement statistics and observable values.
- dagger: Hermitian conjugation, with density-matrix and dimensionality validation enforced throughout.
from qilisdk.core import QTensor
# Build a Bell state, and inspect a subsystem
bell = QTensor.ghz(2)
rho_A = bell.partial_trace(keep={0}) # reduced state of qubit 0
print(rho_A.probabilities()) # [0.5, 0.5]
# Bloch-sphere Visualization
psi = QTensor.uniform(1)
psi.draw()
6. Extra Features
6.1 Interoperability: OpenQASM and QIR
- OpenQASM 2 and 3. Native import and export support for OpenQASM, including OpenQASM 3 parsing. The functionality is provided through qilisdk.utils.openqasm and can be installed as an optional dependency with pip install qilisdk[openqasm].
- QIR (Quantum Intermediate Representation). Interoperability between Circuit and Microsoft’s LLVM-based QIR (via pyqir), supporting standard gates with textual-IR and file round-trips: to_qir() / from_qir() and to_qir_file() / from_qir_file(). Available as an optional dependency via pip install qilisdk[qir].
from qilisdk.digital import Circuit, H, CNOT
from qilisdk.utils.openqasm import to_qasm3
from qilisdk.utils.qir import to_qir
c = Circuit(2)
c.add(H(0))
c.add(CNOT(0, 1))
qasm = to_qasm3(c) # export to OpenQASM
qir = to_qir(c) # export to QIR textual IR
6.2 Trotterization of Analog Evolution
Analog schedules can be compiled into digital circuits via Trotterization. The new TrotterizedSchedule ansatz generates a parameterized circuit that approximates the evolution of a Schedule over a chosen number of Trotter steps.
The example below constructs a simple analog schedule that interpolates linearly from an initial Hamiltonian X(0) to a final Hamiltonian Z(0). The schedule is then converted into a digital circuit using the TrotterizedSchedule ansatz with a single Trotter step, and the resulting circuit is visualized. This workflow illustrates how analog evolutions can be translated into gate-based circuits for execution on digital quantum hardware.
from qilisdk.analog.hamiltonian import Z, X
from qilisdk.analog.schedule import Schedule
from qilisdk.digital.ansatz import TrotterizedSchedule
schedule = Schedule.linear(
initial_hamiltonian=X(0),
final_hamiltonian=Z(0),
dt=0.1,
total_time=1,
)
ansatz = TrotterizedSchedule(
schedule=schedule,
trotter_steps=1,
)
ansatz.draw()
6.3 Documentation and Tutorials in Spanish and Catalan
A new Tutorials section has been added to the documentation, providing an introduction to quantum-computing concepts and hands-on examples. To improve navigation and readability, several large reference pages have been reorganized into smaller units. The Backends documentation has been expanded with QiliSim method references, functional-support tables, and noise-model notes. In addition, the documentation and tutorials are now available in English (EN), Spanish (ES) and Catalan (CA).
6.4 Other Changes
- Composable CircuitTranspiler pipeline: identity-pair cancellation, single-qubit gate fusion, canonical-basis decomposition, multi-controlled-gate decomposition, and SABRE-based layout/routing for hardware-aware compilation.
- Readout refactor: unified FunctionalResult and a Readout builder (with_sampling(), with_expectation(), with_state_tomography()) that can combine multiple readout types in a single execution.
- CUDA 13 support with a cleaner optional-dependency system.
- Automatic QUBO linearization of higher-order terms via Rosenberg penalties.
- Cached gate matrices that reduce serialization overhead.
- Improved object representations across the library, and added an about() helper for installation diagnostics.
7. Performance and Benchmarks
QiliSDK 0.2.0 delivers significant performance improvements across the simulation stack for the workload and problem sizes tested. These gains come from:
- QTensor in C++: the migration of QiliSDK’s core quantum tensor type to native code accelerates state and operator manipulation throughout the library.
- Matrix-free state-vector simulation: now the default for circuit sampling, avoiding full gate-matrix materialization and reducing both memory usage and execution time.
- Matrix-free analog integrator, plus an adaptive RK45 option that selects step size based on the dynamics.
The plots below compare the performance of the QiliSDK simulation backends on representative analog and digital workloads.
The first benchmark measures the time required for a simple annealing schedule to reach 99% fidelity with the exact ground state as a function of the number of qubits. The results show that QiliSim consistently outperforms both the QuTiP and CUDA backends over the range of system sizes considered in this study. While QuTiP performs competitively for small systems, its execution time increases rapidly as the system size grows. For this particular workload, the CUDA backend incurs a relatively large overhead that outweighs the benefits of GPU acceleration at the tested scales. These results demonstrate that QiliSim provides highly efficient analog simulation on commodity CPU hardware, making it well suited for small- and medium-scale problems.
Execution time required to solve a simple annealing problem from an initial X Hamiltonian to a final ZZ Hamiltonian for different numbers of qubits. The plot shows the time taken by each solver to reach 99% fidelity of the exact ground state with QiliSim outperforming the other backends.
The second benchmark measures the execution time required to sample a quantum circuit composed of 1000 randomly generated gates with 100 measurement shots. The results show that QiliSim is competitive with state-of-the-art CPU simulators, including Qiskit Aer and Cirq for small to medium system sizes. While QuTiP scales poorly and quickly becomes impractical, PennyLane’s Lightning-Qubit backend also exhibits a steep increase in execution time as the number of qubits grows. For larger circuits, the CUDA backend achieves the best overall performance, significantly outperforming all CPU-based simulators.
Execution time required to simulate a circuit of 1000 random gates with 100 measurement shots for different numbers of qubits. The plot shows that QiliSim is competitive with state-of-the-art CPU simulators, while the QiliSDK CUDA backend offers strong performance for large-scale simulations.
Together, these benchmarks demonstrate that QiliSDK provides efficient execution across both CPU and GPU platforms through the QiliSim and CUDA backends. Users can therefore select the backend best suited to their workload and available hardware, balancing performance, scalability, and resource requirements.
8. Getting Started
QiliSDK is open source, Apache-2.0 licensed, and available through PyPI. QiliSDK supports Windows, Mac and Linux, for Python versions 3.11, 3.12 and 3.13. The core package, including the QiliSim simulator, can be installed with:
pip install qilisdk
Optional dependencies are available for additional functionality:
pip install "qilisdk[cuda13]" # GPU acceleration (CUDA 13)
pip install "qilisdk[openqasm]" # OpenQASM 2/3 interoperability
pip install "qilisdk[qir]" # QIR interoperability
To learn more, explore the documentation, tutorials, and source code:
- Documentation and Tutorials (EN / ES / CA): https://qilimanjaro-tech.github.io/qilisdk/
- Source Code and Issue Tracker: https://github.com/qilimanjaro-tech/qilisdk
- Release Notes: https://github.com/qilimanjaro-tech/qilisdk/releases/tag/0.2.0
- Citation (Zenodo): DOI 10.5281/zenodo.20411054
Whether targeting CPU simulation, GPU acceleration, or Qilimanjaro’s quantum hardware, QiliSDK provides a unified environment for developing, simulating, and executing digital, analog, and hybrid quantum workflows.