Skip to content

Commit 3c7d272

Browse files
Merge pull request #117 from ColibrITD-SAS/dev
Version 0.3.1
2 parents 1d7dd57 + 1cd4e15 commit 3c7d272

File tree

7 files changed

+103
-32
lines changed

7 files changed

+103
-32
lines changed

docs/getting-started.rst

+30-2
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,52 @@ For now, we support Python versions 3.9 to 3.11, and all of Windows, Linux and
1111
MacOS (specifically, Linux was validated on Ubuntu LTS 20.04, while Ubuntu 18.04
1212
is not supported, so your milage may vary).
1313

14+
To install mpqp, you can run in a terminal
15+
1416
.. code-block:: console
1517
1618
$ pip install mpqp
1719
20+
And if you have already a previous version and want to update to the latest
21+
version, run instead
22+
23+
.. code-block:: console
24+
25+
$ pip install -U mpqp
26+
1827
.. note::
1928
For Mac users, additional steps are required before installation,
2029
specifically because of the ``myqlm`` library. To run these steps, you can
2130
either follow their instructions on
2231
`this page <https://myqlm.github.io/01_getting_started/%3Amyqlm%3Amacos.html#macos>`_
2332
or run the script we created to facilitate this step:
2433

25-
.. code-block:: bash
34+
.. code-block:: console
2635
27-
curl -L https://raw.githubusercontent.com/ColibrITD-SAS/mpqp/main/mac-install.sh | bash -s -- <your-python-bin>
36+
$ curl -L https://raw.githubusercontent.com/ColibrITD-SAS/mpqp/main/mac-install.sh | bash -s -- <your-python-bin>
2837
2938
where ``<your-python-bin>`` is the binary you use to invoke python. For instance, it could
3039
be ``python``, ``python3``, or ``python3.9``.
3140

41+
.. warning::
42+
The migration from ``qiskit`` version ``0.x`` to ``1.x`` caused a few issues.
43+
In case you had a ``qiskit 0.x`` environment, you might encounter an error
44+
such as
45+
46+
.. code-block:: bash
47+
48+
ImportError: Qiskit is installed in an invalid environment that has both Qiskit >=1.0 and an earlier version...
49+
50+
To fix this, we provide a script you can run that will fix your environment.
51+
In a terminal, simply run.
52+
53+
.. code-block:: console
54+
55+
$ update_qiskit
56+
57+
Alternatively, if you want to keep your old qiskit environment, you can also
58+
create a new virtual environment.
59+
3260
Your first circuit
3361
------------------
3462

mpqp/execution/providers/ibm.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
from mpqp.execution.devices import AZUREDevice, IBMDevice
2222
from mpqp.execution.job import Job, JobStatus, JobType
2323
from mpqp.execution.result import Result, Sample, StateVector
24-
from mpqp.execution.simulated_devices import IBMSimulatedDevice
2524
from mpqp.noise import DimensionalNoiseModel
2625
from mpqp.tools.errors import DeviceJobIncompatibleError, IBMRemoteExecutionError
2726

@@ -38,6 +37,7 @@
3837
from qiskit_aer import AerSimulator
3938
from qiskit_aer.noise import NoiseModel as Qiskit_NoiseModel
4039
from qiskit_ibm_runtime import RuntimeJobV2
40+
from mpqp.execution.simulated_devices import IBMSimulatedDevice
4141

4242

4343
@typechecked
@@ -84,6 +84,7 @@ def compute_expectation_value(
8484
:func:`~mpqp.execution.runner.run` instead.
8585
"""
8686
from qiskit.quantum_info import SparsePauliOp
87+
from mpqp.execution.simulated_devices import IBMSimulatedDevice
8788

8889
if not isinstance(job.measure, ExpectationMeasure):
8990
raise ValueError(
@@ -150,6 +151,8 @@ def check_job_compatibility(job: Job):
150151
contained in the job (measure and job_type, device and job_type,
151152
etc...).
152153
"""
154+
from mpqp.execution.simulated_devices import IBMSimulatedDevice
155+
153156
if TYPE_CHECKING:
154157
assert isinstance(job.device, (IBMDevice, IBMSimulatedDevice))
155158

@@ -413,6 +416,7 @@ def run_aer(job: Job):
413416

414417
from qiskit import QuantumCircuit, transpile
415418
from qiskit_aer import AerSimulator
419+
from mpqp.execution.simulated_devices import IBMSimulatedDevice
416420

417421
job_circuit = job.circuit
418422

@@ -582,7 +586,7 @@ def run_remote_ibm(job: Job) -> Result:
582586
def extract_result(
583587
result: "QiskitResult | EstimatorResult | PrimitiveResult[PubResult | SamplerPubResult]",
584588
job: Optional[Job],
585-
device: IBMDevice | IBMSimulatedDevice | AZUREDevice,
589+
device: "IBMDevice | IBMSimulatedDevice | AZUREDevice",
586590
) -> Result:
587591
"""Parses a result from ``IBM`` execution (remote or local) in a ``MPQP``
588592
:class:`~mpqp.execution.result.Result`.

mpqp/tools/circuit.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@
3939
from qiskit.circuit.quantumcircuitdata import CircuitInstruction
4040

4141

42-
# @typechecked
43-
# FIXME: Resolve type-checking errors encountered during test execution.
42+
@typechecked
4443
def random_circuit(
4544
gate_classes: Optional[Sequence[type[Gate]]] = None,
4645
nb_qubits: int = 5,
@@ -85,7 +84,7 @@ def random_circuit(
8584
rng = np.random.default_rng(seed)
8685

8786
if nb_gates is None:
88-
nb_gates = rng.integers(5, 10)
87+
nb_gates = int(rng.integers(5, 10))
8988

9089
qcircuit = QCircuit(nb_qubits)
9190
for _ in range(nb_gates):

mpqp/tools/display.py

+20-22
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,8 @@ def state_vector_ket_shape(sv: npt.NDArray[np.complex64]) -> str:
3131
)[2:]
3232

3333

34-
# @typechecked
35-
# FIXME: Resolve type-checking errors encountered during test execution.
36-
def with_sign(val: np.complex64) -> str:
34+
@typechecked
35+
def with_sign(val: Union[np.complex64, np.complex128]) -> str:
3736
"""Sometimes, we want values under a specific format, in particular
3837
``<sign> <value>``. Where value is as simple as possible (*e.g.* no period
3938
or no imaginary part if there is no need).
@@ -57,18 +56,20 @@ def with_sign(val: np.complex64) -> str:
5756
return "+ " + str_rounded
5857

5958

60-
# @typechecked
61-
# FIXME: Resolve type-checking errors encountered during test execution.
62-
def _remove_null_imag(val: np.complex64) -> np.complex64 | np.float32 | int:
59+
@typechecked
60+
def _remove_null_imag(
61+
val: np.complex64 | np.complex128,
62+
) -> np.complex64 | np.complex128 | np.float32 | int:
6363
val = np.round(val, 3)
6464
if val.imag != 0:
6565
return val
6666
return _remove_unnecessary_decimals(val.real)
6767

6868

69-
# @typechecked
70-
# FIXME: Resolve type-checking errors encountered during test execution.
71-
def _remove_unnecessary_decimals(val: np.float32 | int) -> np.float32 | int:
69+
@typechecked
70+
def _remove_unnecessary_decimals(
71+
val: np.float32 | np.float64 | int,
72+
) -> np.float32 | int:
7273
val = np.float32(val)
7374
if val.is_integer():
7475
return int(val)
@@ -190,9 +191,8 @@ def clean_1D_array(
190191
)
191192

192193

193-
# @typechecked
194-
# FIXME: Resolve type-checking errors encountered during test execution.
195-
def clean_number_repr(number: complex, round: int = 7):
194+
@typechecked
195+
def clean_number_repr(number: Union[complex, np.complex64], round: int = 7):
196196
"""Cleans and formats a number. This function rounds the parts of
197197
complex numbers and formats them as integers if appropriate. It returns a
198198
string representation of the number.
@@ -234,8 +234,7 @@ def clean_number_repr(number: complex, round: int = 7):
234234
return f"{str(real_part)}{str(imag_part)}"
235235

236236

237-
# @typechecked
238-
# FIXME: Resolve type-checking errors encountered during test execution.
237+
@typechecked
239238
def clean_matrix(matrix: Matrix, round: int = 5, align: bool = True):
240239
"""Cleans and formats elements of a 2D matrix. This function rounds the
241240
parts of the numbers in the matrix and formats them as integers if
@@ -250,9 +249,9 @@ def clean_matrix(matrix: Matrix, round: int = 5, align: bool = True):
250249
A string representation of the cleaned matrix.
251250
252251
Examples:
253-
>>> print(clean_matrix([[1.234567895546, 2.3456789645645, 3.45678945645],
254-
... [1+5j, 0+1j, 5.],
255-
... [1.223123425+0.95113462364j, 2.0, 3.0]]))
252+
>>> print(clean_matrix(np.array([[1.234567895546, 2.3456789645645, 3.45678945645],
253+
... [1+5j, 0+1j, 5.],
254+
... [1.223123425+0.95113462364j, 2.0, 3.0]])))
256255
[[1.23457 , 2.34568, 3.45679],
257256
[1+5j , 1j , 5 ],
258257
[1.22312+0.95113j, 2 , 3 ]]
@@ -280,8 +279,7 @@ def clean_matrix(matrix: Matrix, round: int = 5, align: bool = True):
280279
)
281280

282281

283-
# @typechecked
284-
# FIXME: Resolve type-checking errors encountered during test execution.
282+
@typechecked
285283
def pprint(matrix: Matrix, round: int = 5, align: bool = True):
286284
"""Print a cleans and formats elements of a matrix. It rounds the real parts of complex numbers
287285
in the matrix places and formats them as integers if they are whole numbers. It returns a
@@ -293,9 +291,9 @@ def pprint(matrix: Matrix, round: int = 5, align: bool = True):
293291
align: Whether to align the elements for a cleaner output.
294292
295293
Example:
296-
>>> pprint([[1.234567895546, 2.3456789645645, 3.45678945645],
297-
... [1+5j, 0+1j, 5.],
298-
... [1.223123425+0.95113462364j, 2.0, 3.0]])
294+
>>> pprint(np.array([[1.234567895546, 2.3456789645645, 3.45678945645],
295+
... [1+5j, 0+1j, 5.],
296+
... [1.223123425+0.95113462364j, 2.0, 3.0]]))
299297
[[1.23457 , 2.34568, 3.45679],
300298
[1+5j , 1j , 5 ],
301299
[1.22312+0.95113j, 2 , 3 ]]

mpqp/tools/theoretical_simulation.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,7 @@ def exp_id_dist(
216216
return float(jensenshannon(mpqp_counts, noisy_probs * sum(mpqp_counts)))
217217

218218

219-
# @typechecked
220-
# FIXME: Resolve type-checking errors encountered during test execution.
219+
@typechecked
221220
def validate_noisy_circuit(
222221
circuit: QCircuit,
223222
shots: int = 1024,
@@ -233,7 +232,7 @@ def validate_noisy_circuit(
233232
Returns:
234233
Weather our noise pipeline matches the theory or not.
235234
"""
236-
return exp_id_dist(circuit, shots, device) <= trust_int(circuit)
235+
return bool(exp_id_dist(circuit, shots, device) <= trust_int(circuit))
237236

238237

239238
@typechecked

mpqp_scripts/update_qiskit.py

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import subprocess
2+
import sys
3+
4+
qiskit_packages = [
5+
"qiskit",
6+
"qiskit-aer",
7+
"qiskit-algorithms",
8+
"qiskit_alice_bob_provider",
9+
"qiskit-aqua",
10+
"qiskit-finance",
11+
"qiskit-ibm-provider",
12+
"qiskit-ibm-runtime",
13+
"qiskit-ibmq-provider",
14+
"qiskit-ignis",
15+
"qiskit-optimization",
16+
"qiskit-qir-alice-bob-fork",
17+
"qiskit-terra",
18+
"ibm-cloud-sdk-core",
19+
"ibm-platform-services",
20+
"IBMQuantumExperience",
21+
]
22+
23+
24+
def run_command(command: str):
25+
"""Run a shell command and handle errors."""
26+
result = subprocess.run(command, shell=True)
27+
if result.returncode != 0:
28+
print(f"Error running command: {command}")
29+
30+
31+
def update_packages():
32+
"""Uninstall all specified Qiskit packages."""
33+
print(f"Uninstalling qiskit package...")
34+
for pkg in qiskit_packages:
35+
run_command(f"{sys.executable} -m pip uninstall -y {pkg}")
36+
print("Installing mpqp...")
37+
run_command(f"{sys.executable} -m pip install --upgrade mpqp")
38+
39+
40+
if __name__ == "__main__":
41+
print(f"Using Python executable: {sys.executable}")
42+
update_packages()

setup.py

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
entry_points={
3434
"console_scripts": [
3535
"setup_connections = mpqp_scripts.setup_connections:main_setup",
36+
"update_qiskit = mpqp_scripts.update_qiskit:update_packages",
3637
]
3738
},
3839
project_urls={

0 commit comments

Comments
 (0)