Metadata-Version: 2.3
Name: qprof
Version: 1.5.0
Summary: A quantum profiler inspired by gprof
Author: Adrien Suau
Author-email: Adrien Suau <12374487+nelimee@users.noreply.github.com>
Requires-Dist: qcw>=0.2
Requires-Dist: qcw-qiskit ; extra == 'all'
Requires-Dist: qcw-openqasm2 ; extra == 'all'
Requires-Dist: qcw-myqlm ; extra == 'all'
Requires-Dist: qcw-myqlm ; extra == 'myqlm'
Requires-Dist: qcw-openqasm2 ; extra == 'openqasm2'
Requires-Dist: qcw-qiskit ; extra == 'qiskit'
Requires-Python: >=3.10, <3.12
Provides-Extra: all
Provides-Extra: myqlm
Provides-Extra: openqasm2
Provides-Extra: qiskit
Description-Content-Type: text/markdown

# **qprof**

`qprof` stands for **q**uantum **prof**iler and aims at providing a
unique tool to profile quantum circuits.

For the moment, `qprof` is able to understand quantum circuits generated
with [qiskit](https://qiskit.org) and [myQLM](https://myqlm.github.io)
and can generate profiling results in 
[JSON](https://fr.wikipedia.org/wiki/JavaScript_Object_Notation) and a
[gprof](https://sourceware.org/binutils/docs/gprof/) compatible format.

## Installation

`qprof` being a Python module, it is installable with `pip`.

### From Gitlab

```bash
git clone https://gitlab.com/qcomputing/qprof/qprof.git
pip install qprof/
```

### From PyPi

`qprof` is now available on PyPi! To download and install the last
version, just type

```bash
pip install qprof
```

Plugins for library support are not installed by default in order to
avoid pulling silently huge dependencies like `qiskit` in your project.
In order to install the plugins you can use the appropriate target when installing `qprof`:

```bash
pip install qprof[qiskit]
pip install qprof[myqlm]
```

## Usage

### Profiling

The profiling is performed with the `qprof.profile` function.

The `qprof.profile` function needs a quantum routine implemented with
one of the supported frameworks along with the "base" gate times,
provided as a dictionary, and an exporter, given either as a string or
as an instance of `BaseExporter`.

Example of profiling:

```python
# Import the qprof tools
from qprof import profile

# Import the framework tools to generate a quantum routine
from qiskit.aqua.algorithms import Grover
from qiskit.aqua.components.oracles import LogicalExpressionOracle


# Generate the routine to benchmark.
input_3sat = """
c example DIMACS-CNF 3-SAT
p cnf 3 5
-1 -2 -3 0
1 -2 3 0
1 2 -3 0
1 -2 -3 0
-1 2 3 0
"""

oracle = LogicalExpressionOracle(input_3sat)
grover = Grover(oracle)
circuit = grover.construct_circuit()

# Hard-coded gate times retrieved by hand
gate_times = {"U1": 0, "U2": 89, "U3": 178, "CX": 930, "BARRIER": 0}

# Profile the resulting quantum routine and use the "gprof" exporter
qprof_out = profile(circuit, gate_times, "gprof")

# Print to stdout the analysis report
print(qprof_out)
```

## Full profiling example

### Requirements for the example

You should have the `dot` tool installed on your machine, along with the
[gprof2dot](https://github.com/jrfonseca/gprof2dot) tool that can be
installed with `pip install gprof2dot`.

### Profile the code

Let save the code of the previous section in a file
`profile.py`.

You can generate the following graph with the command

```bash
python3 profile.py | gprof2dot -n 0 -e 0 | dot -Tpng -o profiling_result.png
```

![image](docs/images/profile_result.png)

## Limitations

- `qprof` is not able to analyse recursive routine calls yet. If your
  quantum circuit contains calls to recursive routines, expect the
  unexpected.
  
- The call-graph analysis is done as if all the quantum gates were executed 
  sequentially. Parallel execution support is a work in progress in the
  [parallel_support](https://gitlab.com/qcomputing/qprof/qprof/-/tree/parallel_support)
  branch. The main issue that still needs to be solved is the output format.

## Troubleshooting

### `Unknown` routines shows up in reports

If `Unknown` routines are showing up in the reports, check that you
named correctly all the routines you defined.

If the problem is still present, open an issue.

### Reported times using `gprof` output format are false

The `gprof` output format has a very limited precision of 10
milli-seconds when dealing with timings. This means that routines
running in less than 5 milli-seconds will, due to rounding error, appear
as taking 0 milli-seconds.

In order to circumvent this issue, the `qprof.exporters.GprofExporter`
takes an optional parameter `default_time` in its constructor. This
`default_time` will be used to scale all the execution times such that
the longest routine will take exactly `default_time` seconds on the
report.

By default, the value of `default_time` is 10 seconds. In order to
change it you need to instantiate the exporter yourself:

```python
from qprof import profile
from qprof.exporters import GprofExporter

routine = # ...
gate_times = # ...
exporter = GprofExporter(default_time=100) # 100 seconds for default_time

result = profile(routine, gate_times, exporter)
```

Note that giving `None` to `default_time` will disable the execution
time scaling.

## Who is using `qprof`?

Here is a list of projects using `qprof`.

If you used `qprof` in your project and would like to appear in this
list, please let me know (open an issue, send me a mail, anything you
want).

-   [QatHS](https://gitlab.com/cerfacs/qaths)
