Metadata-Version: 2.4
Name: qevedo-compiler
Version: 0.2.0
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Rust
Classifier: Topic :: Scientific/Engineering :: Physics
Requires-Dist: pyyaml>=6.0
Requires-Dist: numpy>=1.24
Requires-Dist: openqasm>=3,<4
Requires-Dist: pytest>=7.0 ; extra == 'dev'
Requires-Dist: qevedo-simulator>=0.1 ; extra == 'dev'
Provides-Extra: dev
License-File: LICENSE
Summary: QCC, the Quantum Compiler Collection: a technology-agnostic quantum circuit compiler (qevedo.compiler)
Keywords: quantum,compiler,openqasm,transpiler,gate synthesis,multi-core,modular quantum computing,distributed quantum computing,qubit mapping,qubit routing,hungarian qubit assignment,sabre
License-Expression: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Documentation, https://github.com/qevedo/qcc/blob/master/docs/MULTICORE.md
Project-URL: Homepage, https://github.com/qevedo/qcc
Project-URL: Repository, https://github.com/qevedo/qcc

# QCC: the Quantum Compiler Collection

A technology-agnostic quantum circuit compiler, part of the Qevedo packages:
it installs as `qevedo-compiler` and imports as `qevedo.compiler`.

## Install

```bash
pip install qevedo-compiler
```

For development, from a checkout (this builds the Rust core, so it needs a
Rust toolchain, from https://rustup.rs):

```bash
cd qcc/python
pip install -e ".[dev]"            # or: maturin develop --release
```

The Rust core lives in `../core` (`cargo test --release` there runs its own
tests); `src/` holds its Python bindings.

`openqasm` 3.x is installed from PyPI. To develop both together, also install
the sibling checkout: `pip install -e ../../openqasm`.

## Usage

```bash
qcc compile examples/bell.qasm -o /tmp/out.qasm --device qevedo/compiler/profiles/all_to_all.yaml
qcc compile program.qasm -o /tmp/out.qasm --qasm-version 3 -I lib/
```

From Python:

```python
from qevedo.compiler import compile_source, emit_qasm

circuit = compile_source(open("examples/bell.qasm").read())
print(emit_qasm(circuit))
```

The reference device profiles ship with the package, in
`qevedo/compiler/profiles/`.

Input can be OpenQASM 2 or 3. Programs are checked by `openqasm.analyze`
before lowering, so errors are reported with their location. The frontend
supports qubit and bit registers, gate calls with constant parameters
(broadcast over registers), measurements, resets, barriers, `let` aliases of
qubits and `const` values. Control flow, gate modifiers, classical variables,
timing and hardware qubits are rejected with an error until the IR supports
them. Gates defined by the program (or its own include files) are expanded
into their bodies; gates from `qelib1.inc` and `stdgates.inc` stay named so
the compiler can lower them optimally.

## Lowering to native gates

`compile_source` and `compile_file` rewrite every gate into the device
profile's `native_gates`, with the fewest gates:

- single-qubit gates through an Euler decomposition into the device's
  single-qubit basis (`rz`+`sx`, `rz`+`rx`, `rz`+`ry`, `rx`+`ry` or `u3`);
- two-qubit gates through a KAK decomposition into the device's two-qubit
  gate (`cx`, `cz`, `cy`, `ch`, `ecr`, `rxx`, `ryy`, `rzz` or `rzx`), using
  the minimal number of two-qubit gates (at most 3; on a `cx` device, 1 for
  `cz`, 2 for `crz` and 3 for `swap`);
- standard gates with a shorter textbook definition, and gates on three or
  more qubits, through their definitions.

After lowering, the circuit is optimized: single-qubit runs are merged,
gates cancel or merge across gates they commute with, and every run of gates
on one pair of qubits is resynthesized as a single two-qubit unitary when
that is cheaper. On a 12-qubit QFT and Qiskit's random circuits this gives the
same CX counts as Qiskit's `optimization_level=3` and equal or lower total
gate counts (see `docs/ARCHITECTURE.md`).

```python
from qevedo.compiler import CompileOptions, compile_source
from qevedo.compiler.device import DeviceSpec

ion_trap = DeviceSpec(name="ions", topology="all_to_all", qubits=4,
                      native_gates={"rx", "ry", "rxx"})
circuit = compile_source(open("program.qasm").read(), CompileOptions(device=ion_trap))
print(circuit.gate_counts())
```

## Multi-core architectures

`qevedo.compiler.multicore` compiles circuits for modular quantum computers
made of several cores joined by quantum links, in Rust:

- **mapping**: before each timeslice, which core every qubit is in, with as
  few teleportations as possible: Hungarian Qubit Assignment (HQA, Escofet
  et al.), FGP-rOEE and a naive mapper, on cores linked all to all, in a
  line, a ring, a grid or any connected way;
- **routing inside the cores** (`map_and_route`): each core routed on its own
  coupling graph with SABRE, giving a circuit on physical qubits with SWAPs
  and teleportations, optionally through fixed communication qubits (ports);
- **timing**: how long the circuit takes when links make EPR pairs a few at
  a time, and `"hqa-latency"`, an HQA that plans for it.

```python
from qevedo.compiler.multicore import Timing, map_and_route, map_to_cores

mapping = map_to_cores(open("circuit.qasm").read(), cores=4, qubits_per_core=10)
print(mapping.communications)            # teleportations

result = map_and_route(open("circuit.qasm").read(), cores=4, qubits_per_core=9,
                       chip="grid:3x3", topology="line", ports="central",
                       method="hqa-latency", timing=Timing(link_capacity=2))
print(result.teleportations, result.swaps, result.schedule().duration)
```

It reproduces Escofet et al.'s comparison (HQA needs 1.24× fewer
teleportations than FGP-rOEE), and on TeleSABRE's own device and circuits,
HQA with ports uses 0.26× its EPR pairs and 0.51× its SWAPs. See
[docs/MULTICORE.md](https://github.com/qevedo/qcc/blob/master/docs/MULTICORE.md)
for the model, the methods and every benchmark.

## Tests

```bash
pytest
```

