Metadata-Version: 2.4
Name: qcompile
Version: 0.1.6
Summary: AI-guided hardware-aware quantum circuit layout optimization for Qiskit
Author-email: Shagun Tembhurne <shaxtembhurne@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/shaxtembhurne/qcompile
Project-URL: Repository, https://github.com/shaxtembhurne/qcompile
Project-URL: Issues, https://github.com/shaxtembhurne/qcompile/issues
Keywords: quantum-computing,qiskit,compiler,transpiler,layout,optimization,graph-neural-network,machine-learning
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Operating System :: OS Independent
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: numpy
Requires-Dist: networkx
Requires-Dist: joblib
Requires-Dist: qiskit
Requires-Dist: qiskit-ibm-runtime
Requires-Dist: torch
Requires-Dist: torch-geometric

# qcompile

`qcompile` is a quantum layout optimization tool for IBM heavy-hex hardware.

It helps choose better qubit placements before routing begins, so quantum circuits can be compiled with fewer SWAPs, lower depth, and less noise exposure.

---

## What qcompile is

Quantum computers are very sensitive to layout. A circuit can be correct on paper and still perform poorly after transpilation if the qubits are placed badly on the hardware.

`qcompile` is designed to improve that first placement decision.

It takes a logical circuit graph and searches for a better hardware mapping before the normal compiler has to do the hard work of fixing a bad layout.

---

## Why it helps

A poor initial layout usually causes:

* more SWAP gates
* deeper circuits
* more two-qubit gate usage
* more exposure to hardware noise
* worse execution fidelity

`qcompile` reduces this pressure by trying to start from a stronger layout. That means the downstream transpiler has less damage to repair.

In practice, this can help when:

* the logical circuit is dense
* the hardware connectivity is limited
* you are targeting IBM heavy-hex devices
* you care about lowering SWAP overhead
* you want better performance on noisy hardware

---

## What makes it different

Most compilers start with a default or heuristic layout and then route from there.

`qcompile` tries to learn and search for a better mapping first, so the final compilation step begins from a stronger position.

It is useful when you want the compiler to do more than just “make it fit.”

---

## Main benefits

* fewer SWAPs in many cases
* lower circuit depth
* better hardware-aware placement
* improved chance of surviving noisy execution
* more stable layout decisions across runs
* better benchmarking against standard Qiskit transpilation

---

## How to use it

### Basic usage

```python
import networkx as nx
from qcompile import generate_optimized_layout

num_qubits = 20
edge_probability = 0.4

G = nx.erdos_renyi_graph(num_qubits, edge_probability, seed=1337)
while not nx.is_connected(G):
    G = nx.erdos_renyi_graph(num_qubits, edge_probability)

logical_edges = list(G.edges())

final_layout = generate_optimized_layout(
    num_qubits=num_qubits,
    logical_edges=logical_edges,
    backend_name="ibm_fez",
    train_samples=2500,
    opt_level=3,
)

print(final_layout)
```

---

## Parameters

### `num_qubits`

Number of logical qubits in the circuit.

### `logical_edges`

The interaction graph of the logical circuit.

### `backend_name`

The IBM backend used to fetch live hardware data.

### `train_samples`

How many expert layouts to harvest before training.

### `opt_level`

Controls how aggressively the final layout evaluation is done.

* `1` → fastest
* `2` → balanced
* `3` → strongest evaluation

---

## Example stress test

```python
import time
import networkx as nx
from qcompile import generate_optimized_layout


def run_stress_test():
    num_qubits = 20
    edge_probability = 0.4

    print("=" * 60)
    print(f"INITIATING QCOMPILE STRESS TEST: {num_qubits}-QUBIT DENSE GRAPH")
    print("=" * 60)

    G = nx.erdos_renyi_graph(num_qubits, edge_probability, seed=1337)
    while not nx.is_connected(G):
        G = nx.erdos_renyi_graph(num_qubits, edge_probability)

    logical_edges = list(G.edges())

    start_time = time.time()

    try:
        final_layout = generate_optimized_layout(
            num_qubits=num_qubits,
            logical_edges=logical_edges,
            backend_name="ibm_fez",
            train_samples=2500,
            opt_level=3,
        )
        elapsed_minutes = (time.time() - start_time) / 60
        print(f"Completed in {elapsed_minutes:.2f} minutes")
        print(final_layout)
    except Exception as e:
        print(f"Stress test failed: {e}")


if __name__ == "__main__":
    run_stress_test()
```

---

## When to use it

Use `qcompile` when your circuit is hard to place on hardware and you want a smarter starting layout before full transpilation.

It is especially useful for:

* dense interaction graphs
* medium-sized circuits that struggle on heavy-hex topology
* benchmarking compiler quality
* comparing layout quality across transpilers
* experimenting with hardware-aware quantum compilation

---

## Output

The function returns a final layout mapping that can be used as the starting point for compilation on IBM hardware.

You can then compare the result against standard Qiskit routing using metrics like:

* SWAP count
* circuit depth
* estimated success probability

---

## Why this matters

On noisy quantum hardware, the first layout decision can make or break the run.

A better initial layout means the compiler spends less time fixing avoidable mistakes. That is the main idea behind `qcompile`.

---

## Installation

```bash
pip install qiskit qiskit-ibm-runtime networkx numpy torch torch-geometric joblib
```

You also need IBM Quantum access configured:

```python
from qiskit_ibm_runtime import QiskitRuntimeService
QiskitRuntimeService.save_account(token="YOUR_IBM_API_TOKEN", overwrite=True)
```

---

## License

Add your project license here.
