Installation

QC Executor is a lightweight abstraction layer with a plugin-based backend architecture. The core package depends on no quantum framework at all — its circuits, operators and parameters are built on a columnar instruction store and SymPy. Every backend, Qiskit included, is installed on demand through an optional dependency group (extra).

Requirements

  • Python 3.10, 3.11, 3.12 or 3.13

  • Core runtime dependencies (installed automatically):

    • numpy >= 1.20

    • sympy >= 1.12.1 — symbolic parameter expressions

That is the whole list. No quantum framework is imported by import qc_executor; backends resolve on first use and are None when their extra is absent. See Backends and optional dependencies below.

Install from PyPI

The released package is published as qc-executor:

pip install qc-executor

This installs the core package: you can build circuits, operators and parameter expressions, and run them on the pure-Python pauli_propagation backend. Add an extra for any other backend.

Install from GitHub

To install the latest (unreleased) development version directly from the repository:

pip install git+https://github.com/flaqship/qc-executor.git

You can pin to a specific branch, tag, or commit:

pip install "git+https://github.com/flaqship/qc-executor.git@main"

Build from source

Clone the repository and install in editable mode. The project uses uv for environment and dependency management, but plain pip works as well.

Using uv (recommended for development):

git clone https://github.com/flaqship/qc-executor.git
cd qc-executor
uv sync --all-extras --group dev

Using pip:

git clone https://github.com/flaqship/qc-executor.git
cd qc-executor
pip install -e ".[all]"

Run the test suite to verify the installation:

uv run pytest tests/        # or: pytest tests/

Backends and optional dependencies

Each simulator/hardware backend is shipped as a plugin and enabled through an extra. Install only the backends you need:

Backend name

Install command

Description

pauli_propagation

(core install)

Heisenberg-picture Pauli propagation for sparse observables. Pure Python, so it needs no extra.

qiskit

pip install "qc-executor[qiskit]"

Statevector simulation via Qiskit.

qiskit (full)

pip install "qc-executor[qiskit-full]"

Adds the Aer simulator and IBM Quantum Runtime. Needed for shot-based sampling and for dynamic circuits: the local Qiskit primitives reject circuits containing measurements or control flow.

pennylane

pip install "qc-executor[pennylane]"

Simulation and automatic differentiation via PennyLane devices.

qulacs

pip install "qc-executor[qulacs]"

Fast C++ statevector simulation via Qulacs.

Install several backends at once, or all of them:

# Multiple specific backends
pip install "qc-executor[qiskit,pennylane,qulacs]"

# Everything
pip install "qc-executor[all]"

When installing from GitHub, extras are appended with #egg=:

pip install "git+https://github.com/flaqship/qc-executor.git#egg=qc-executor[pennylane]"

The plugin architecture

QC Executor discovers backends through Python entry points in the qc_executor.backends group. Each installed plugin registers itself with the Executor factory the first time a backend is requested, so Executor.available_backends() reflects exactly which backends are present in your environment.

This has two practical consequences:

  • You never import backend classes directly. Selecting a backend by name (Executor.create("qiskit")) is enough; the matching plugin is loaded lazily and only if its dependencies are installed. Asking for a backend whose extra is missing raises ValueError naming the extra to install.

  • Adding a backend does not require changing the core. A third-party package can ship its own executor and expose it under the qc_executor.backends entry-point group.

The entry points bundled with the package are declared in pyproject.toml:

[project.entry-points."qc_executor.backends"]
pennylane = "qc_executor.pennylane:PennyLaneExecutor"
qiskit = "qc_executor.qiskit:QiskitExecutor"
qulacs = "qc_executor.qulacs:QulacsExecutor"
pauli_propagation = "qc_executor.pauli_propagation:PauliPropagationExecutor"

To contribute a new backend, implement a subclass of ExecutorBase and register it either via the @Executor.register("<name>") decorator or by exposing it under the qc_executor.backends entry-point group. See Usage Guide for the methods a backend must implement.