unitaryfund / mitiq

Mitiq is an open source toolkit for implementing error mitigation techniques on most current intermediate-scale quantum computers.
https://mitiq.readthedocs.io
GNU General Public License v3.0
357 stars 157 forks source link

import problem with qiskit conversion #2471

Open GuusAvis opened 4 weeks ago

GuusAvis commented 4 weeks ago

Issue Description

I want to use mitiq to convert a circ circuit to a qiskit circuit, but the function I find in the documentation gives me an error. Importing the relevant module separately does fix it though.

The error I get is the following:

{
    "name": "AttributeError",
    "message": "module 'mitiq.interface' has no attribute 'mitiq_qiskit'",
    "stack": "---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[5], line 1
----> 1 mitiq.interface.mitiq_qiskit.conversions.to_qiskit(ct)

AttributeError: module 'mitiq.interface' has no attribute 'mitiq_qiskit'"
}

How to Reproduce

import mitiq
ct = mitiq.benchmarks.generate_random_clifford_t_circuit(5, 3, 3, 3)
mitiq.interface.mitiq_qiskit.conversions.to_qiskit(ct)

Expected behavior

This codes does implement the expected behavior:

import mitiq
import mitiq.interface.mitiq_qiskit.conversions as conv
ct = mitiq.benchmarks.generate_random_clifford_t_circuit(5, 3, 3, 3)
qiskit_ct = conv.to_qiskit(ct)

Environment Context
Mitiq: A Python toolkit for implementing error mitigation on quantum computers
==============================================================================
Authored by: Mitiq team, 2020 & later (https://github.com/unitaryfund/mitiq)

Mitiq Version:  0.39.0

Core Dependencies
-----------------
Cirq Version:   1.3.0
NumPy Version:  1.26.4
SciPy Version:  1.14.0

Optional Dependencies
---------------------
PyQuil Version: Not installed
Qiskit Version: Not installed
Braket Version: Not installed

Python Version: 3.11.9
Platform Info:  Linux (x86_64)
github-actions[bot] commented 4 weeks ago

Hello @GuusAvis, thank you for your interest in Mitiq! If this is a bug report, please provide screenshots and/or minimum viable code to reproduce your issue, so we can do our best to help get it fixed. If you have any questions in the meantime, you can also ask us on the Unitary Fund Discord.

cosenal commented 3 weeks ago

This issue came up in discussions a few times in the past already (with @natestemen and @jordandsullivan), so let me add some notes from those discussions.

Problem

In order to have a module like mitiq_qiskit accessible from the top-level module mitiq directly, that same module needs to be in the transitive closure of imports defined by all the __init__.py files starting from the root at https://github.com/unitaryfund/mitiq/blob/main/mitiq/__init__.py.

As an example, here is a chain of imports. In the root mitiq/__init__.py file we have

from mitiq.calibration import Calibrator

Then in the __init__.py of the calibration module we have

from mitiq.calibration.settings import Settings

and finally in the imports of settings we have

from mitiq.zne import execute_with_zne

This means that if one does

import mitiq
mitiq.zne.execute_with_zne

it will work with no issues.

At the moment, mitiq_qiskit is not in that transitive closure, hence the issue OP is reporting.

Notice this is different from doing import mitiq.interface.mitiq_qiskit.conversions directly, because the import operation will not follow those dunder-init files, but instead it will look into the filesystem path that corresponds to the modules being imported. In other words, what import does is something equivalent to actually doing cd mitiq/interface/mitiq_qiskit.

Solution

We could explicitly add all the functions we want the users to access directly from the top-level module by modifying those __init__.py files, but we need to keep in mind performance issues (we don't want import mitiq to take too much time) and namespace pollution (we need to be careful we don't have things like import *).

Imho the best approach here is to review what functions/modules/classes we want to expose to the end users and make only those accessible from the top module.