# Circuit execution#

Qibolab can be used as a `qibo` backend for executing executions. The purpose of this section is to show how to do it, without entering into the details of circuits definition that we leave to the Qibo documentation.

```import numpy as np
import qibo
from qibo import Circuit, gates

np.random.seed(0)

# create a single qubit circuit
circuit = Circuit(1)

# attach Hadamard gate and a measurement

# execute on quantum hardware
qibo.set_backend("qibolab", platform="dummy")
hardware_result = circuit(nshots=5000)

# retrieve measured probabilities
freq = hardware_result.frequencies()
p0 = freq["0"] / 5000 if "0" in freq else 0
p1 = freq["1"] / 5000 if "1" in freq else 0
hardware = [p0, p1]

# execute with classical quantum simulation
qibo.set_backend("numpy")
simulation_result = circuit(nshots=5000)

simulation = simulation_result.probabilities(qubits=(0,))
```

In this snippet, we first define a single-qubit circuit containing a single Hadamard gate and a measurement. We then proceed to define the qibo backend as `qibolab` using the `tii1q_b1` platform. Finally, we change the backend to `numpy`, a simulation one, to compare the results with ideality. After executing the script we can print our results that will appear more or less as:

```print(f"Qibolab: P(0) = {hardware[0]:.2f}\tP(1) = {hardware[1]:.2f}")
print(f"Numpy:   P(0) = {simulation[0]:.2f}\tP(1) = {simulation[1]:.2f}")
```

Returns:

```Qibolab: P(0) = 0.49    P(1) = 0.51
Numpy:   P(0) = 0.50    P(1) = 0.50
```

Clearly, we do not expect the results to be exactly equal due to the non ideality of current NISQ devices.

Note

Qibo circuits and gates are backend agnostic. The same circuit can be executed on multiple backends, including simulation and quantum platforms.

A slightly more complex circuit, a variable rotation, will produce similar results:

```import matplotlib.pyplot as plt
import numpy as np
import qibo
from qibo import Circuit, gates

def execute_rotation():
# create single qubit circuit
circuit = Circuit(1)

# attach Rotation on X-Pauli with angle = 0

# define range of angles from [0, 2pi]
exp_angles = np.arange(0, 2 * np.pi, np.pi / 16)

res = []
for angle in exp_angles:
# update circuit's rotation angle
circuit.set_parameters([angle])

# execute circuit
result = circuit.execute(nshots=4000)
freq = result.frequencies()
p0 = freq['0'] / 4000 if '0' in freq else 0
p1 = freq['1'] / 4000 if '1' in freq else 0

# store probability in state |1>
res.append(p1)

return res

# execute on quantum hardware
qibo.set_backend("qibolab", platform="dummy")
hardware = execute_rotation()

# execute with classical quantum simulation
qibo.set_backend("numpy")
simulation = execute_rotation()

# plot results
exp_angles = np.arange(0, 2 * np.pi, np.pi / 16)
plt.plot(exp_angles, hardware, label="qibolab hardware")
plt.plot(exp_angles, simulation, label="numpy")

plt.legend()
plt.ylabel("P(1)")
plt.show()
```

Returns the following plot:

Note

Executing circuits using the Qibolab backend results to automatic application of the compilation pipeline (Transpiler and Compiler) which convert the circuit to a pulse sequence that is executed by the given platform. It is possible to modify these pipelines following the instructions in the How to modify the default circuit compilation example.

## QASM Execution#

Qibolab also supports the execution of circuits starting from a QASM string. The QASM circuit:

```circuit = """// Generated by QIBO 0.2.4
OPENQASM 2.0;
include "qelib1.inc";
qreg q[3];
creg a[2];
cz q[0],q[2];
gpi2(0.3) q[1];
cz q[1],q[2];
measure q[0] -> a[0];
measure q[2] -> a[1];"""
```

can be executed by passing it together with the platform name to the `qibolab.execute_qasm()` function:

```from qibolab import execute_qasm

result = execute_qasm(circuit, platform="dummy")
```

## C-API#

Qibolab also supports the execution of circuits starting from a QASM string using a C-API. Please refer to the C-API documentation.