---
file_format: mystnb
kernelspec:
  name: python3
mystnb:
  number_source_lines: true
---

```{code-cell} ipython3
:tags: [remove-cell]
%config InlineBackend.figure_formats = ['svg']
```

# Quickstart

```{code-cell} ipython3
from mqt.bench import BenchmarkLevel, get_benchmark
from mqt.bench.targets import get_device, get_target_for_gateset
```

## Algorithmic Level

```{code-cell} ipython3
qc_algorithmic_level = get_benchmark(benchmark="dj", level=BenchmarkLevel.ALG, circuit_size=5)
qc_algorithmic_level.draw(output="mpl")
```

## Target-independent Level

```{code-cell} ipython3
qc_target_independent_level = get_benchmark(benchmark="dj", level=BenchmarkLevel.INDEP, circuit_size=5)
qc_target_independent_level.draw(output="mpl")
```

## Target-dependent Native Gates Level

```{code-cell} ipython3
qc_native_gates_level = get_benchmark(
    benchmark="dj",
    level=BenchmarkLevel.NATIVEGATES,
    circuit_size=5,
    target=get_target_for_gateset("ibm_falcon", 5),
    opt_level=2,
)
qc_native_gates_level.draw(output="mpl")
```

(mapped-level)=

## Target-dependent Mapped Level

```{code-cell} ipython3
qc_mapped_level = get_benchmark(
    benchmark="dj",
    level=BenchmarkLevel.MAPPED,
    circuit_size=5,
    target=get_device("ibm_falcon_27"),
    opt_level=2,
)
qc_mapped_level.draw(output="mpl")
```

## Mirror Circuits

Mirror circuits replicate a given benchmark circuit and its mirror image (inverse) concatenated together. This is useful for performance benchmarking because the ideal final state is known (all qubits should return to their initial state), making deviations easy to detect. Here, we mirror the circuit obtained in the {ref}`mapped-level` section.

```{code-cell} ipython3
qc_mirrored = get_benchmark(
    benchmark="dj",
    level=BenchmarkLevel.MAPPED,
    circuit_size=5,
    target=get_device("ibm_falcon_27"),
    opt_level=2,
    generate_mirror_circuit=True,
)
qc_mirrored.draw(output="mpl")
```

## Self-defined Circuits

Sometimes you want to derive benchmark circuits from an original circuit that you created yourself. You can create a `qiskit.QuantumCircuit`, pass it directly to `get_benchmark`, and let MQT Bech compile it for your chosen target backend.

```{code-cell} ipython3
from qiskit import QuantumCircuit

qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)

qc_circuit = get_benchmark(benchmark=qc, level=BenchmarkLevel.NATIVEGATES, target=get_target_for_gateset("ibm_falcon", 2))
qc_circuit.draw(output="mpl")
```

## Self-defined Targets

You can also provide a target manually. Here we build a 5‑qubit `GenericBackendV2` with a custom basis and attach a short description before feeding it into `get_benchmark`.

```{code-cell} ipython3
from qiskit.providers.fake_provider import GenericBackendV2

standard_gates = ["id", "x", "sx", "rz", "cx"]
backend = GenericBackendV2(num_qubits=5, basis_gates=standard_gates)
target = backend.target
target.description = "Awesome Target"

qc_target = get_benchmark(
    benchmark="dj",
    level=BenchmarkLevel.NATIVEGATES,
    circuit_size=5,
    target=target,
    opt_level=2,
)
qc_target.draw(output="mpl")
```

## Random and Symbolic Parameters

Variational benchmarks such as QAOA require sets of real parameters. MQT Bench can either choose random numeric values for you (default) or leave the parameters symbolic so that you can optimize them later.

### Random Parameters (Default)

Random numeric values are generated by default.

```{code-cell} ipython3
qc_random = get_benchmark(benchmark="qaoa", level=BenchmarkLevel.ALG, circuit_size=2)
qc_random.draw(output="mpl")
```

### Symbolic Parameters

Set `random_parameters=False` to keep the parameters symbolic instead of sampling them.

```{code-cell} ipython3
qc_symbolic = get_benchmark(benchmark="qaoa", level=BenchmarkLevel.ALG, circuit_size=2, random_parameters=False)
qc_symbolic.draw(output="mpl")
```

## Output Formats

The `save_circuit` function lets you export circuits in several industry‑standard formats so that they can be run or analyzed by other tools.

### OpenQASM2

```{code-cell} ipython3
---
mystnb:
  text_lexer: 'qasm2'
---
from pathlib import Path
from mqt.bench.output import (
    OutputFormat,
    save_circuit,
)

qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)

save_circuit(qc, "qasm2", BenchmarkLevel.INDEP, output_format=OutputFormat.QASM2)
text_qasm2 = Path("qasm2.qasm").read_text()
print(text_qasm2)
Path("qasm2.qasm").unlink()
```

### OpenQASM3

```{code-cell} ipython3
---
mystnb:
  text_lexer: 'qasm3'
---
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)

save_circuit(qc, "qasm3", BenchmarkLevel.INDEP, output_format=OutputFormat.QASM3)
text_qasm3 = Path("qasm3.qasm").read_text()
print(text_qasm3)
Path("qasm3.qasm").unlink()
```

### QPY

```{code-cell} ipython3
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)

save_circuit(qc, "qpy", BenchmarkLevel.INDEP, output_format=OutputFormat.QPY)
Path("qpy.qpy").unlink()
```
