# Benchmarking Quantum Circuits

In this tutorial, we'll explore quantum computing with LunaBench, focusing on creating datasets from arbitrary programs using quantum circuits. This guide is tailored for those who don't want to use our use case library or mathematical formats for optimization problems but prefer quantum circuits containing any desired program.

Before we begin, ensure you have installed the LunaBencch Python SDK.

Upon completing this tutorial, you will be able to:

- Compile custom datasets for quantum circuits.
- Select and configure quantum backends.
- Run a benchmarking pipeline with LunaBench for quantum circuits.

## 1. Creating a Dataset of Quantum Circuits

LunaBench supports the execution of Qiskit Quantum Circuits, providing a seamless way to explore and benchmark your quantum computing strategies.

This flexibility means you can experiment with any quantum circuit you're interested in, whether that’s testing a specific optimization problem or exploring different quantum algorithms. It’s a more hands-on way to see how well different approaches work on quantum computers.

Creating a dataset of quantum circuits in LunaBench follows a straightforward process, similar to how you would prepare any dataset. In this tutorial, we'll walk through setting up a couple of basic quantum circuits using Qiskit, demonstrating how these can be directly incorporated into LunaBench for analysis.

```
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
# Define the problem type as circuit
problem_name = "circuit"
# Create the first quantum circuit
circuit_zero = QuantumCircuit(2, 2)
circuit_zero.h(0)
circuit_zero.cx(0, 1)
circuit_zero.measure([0, 1], [0, 1])
```

Output:

```
┌───┐ ┌─┐
q_0: ┤ H ├──■──┤M├───
└───┘┌─┴─┐└╥┘┌─┐
q_1: ─────┤ X ├─╫─┤M├
└───┘ ║ └╥┘
c: 2/═══════════╩══╩═
0 1
```

```
# Create the second quantum circuit
qr = QuantumRegister(3, "q")
anc = QuantumRegister(1, "ancilla")
cr = ClassicalRegister(3, "c")
circuit_one = QuantumCircuit(qr, anc, cr)
circuit_one.x(anc[0])
circuit_one.h(anc[0])
circuit_one.h(qr[0:3])
circuit_one.cx(qr[0:3], anc[0])
circuit_one.h(qr[0:3])
circuit_one.barrier(qr)
circuit_one.measure(qr, cr)
```

Output:

```
┌───┐ ┌───┐ ░ ┌─┐
q_0: ┤ H ├───────■──┤ H ├───────────░─┤M├──────
├───┤ │ └───┘┌───┐ ░ └╥┘┌─┐
q_1: ┤ H ├───────┼────■──┤ H ├──────░──╫─┤M├───
├───┤ │ │ └───┘┌───┐ ░ ║ └╥┘┌─┐
q_2: ┤ H ├───────┼────┼────■──┤ H ├─░──╫──╫─┤M├
├───┤┌───┐┌─┴─┐┌─┴─┐┌─┴─┐└───┘ ░ ║ ║ └╥┘
ancilla: ┤ X ├┤ H ├┤ X ├┤ X ├┤ X ├─────────╫──╫──╫─
└───┘└───┘└───┘└───┘└───┘ ║ ║ ║
c: 3/══════════════════════════════════╩══╩══╩═
0 1 2
```

These examples illustrate two types of circuits:

**Circuit Zero**: A basic circuit that demonstrates entanglement and quantum measurement.**Circuit One**: A more advanced circuit that utilizes an ancilla qubit for more complex operations, illustrating how quantum states can be manipulated and measured.

To incorporate these circuits into a dataset for LunaBench, we simply prepare a dictionary, mapping a unique identifier to each circuit's QASM representation or the circuit object itself:

```
from qiskit import qasm2
# Define the dataset using either a QASM representation or the Qiskit circuit
dataset = {
"circuit_00": {"circuit": qasm2.dumps(circuit_zero)},
"circuit_01": {"circuit": circuit_one}
}
```

## 2. Selecting Quantum Hardware for Circuit Benchmarking

Just as with optimization problems, handling datasets of quantum circuits in LunaBench follows a straightforward process. However, instead of selecting algorithms, the focus shifts towards choosing the quantum hardware where you'll execute these circuits. This distinction is key, as the 'algorithms' in this context refer to the physical or simulated quantum environments that run your quantum circuits.

For this tutorial, we'll concentrate on two execution environments: the QASM simulator and actual IBM quantum hardware. These choices allow us to benchmark circuits in a simulated environment for quick testing and also on real quantum systems to see how they perform under actual quantum conditions.

```
# Specify the quantum environments with their configurations
algorithms = {
"aer": {
"aer_backend": "qasm_simulator"
},
"ibm": {
"backend": "ibm_kyoto",
"token": "<YOUR_IBM_TOKEN>",
"seed_simulator": 42, "shots": 10
}
}
n_runs = 3
```

## 3. Launching the Benchmark Pipeline

Completing the setup for benchmarking quantum circuits in LunaBench is similar to any other benchmarking process within the framework. Regardless of whether you're working with quantum circuits or other types of optimization problems, launching the benchmark pipeline follows the same straightforward procedure. Once initiated, LunaBench efficiently processes your dataset, executing the circuits on the selected quantum hardware.

After the benchmarking run is complete, your results will be systematically organized and accessible in the usual results directory.

```
from lunabench import solve_dataset
# Solve the entire dataset
solved, result_id = solve_dataset(
problem_name=problem_name,
dataset=dataset,
solve_algorithms=algorithms,
n_runs=n_runs
)
```