perceval-interop 0.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- perceval_interop-0.1.2/LICENSE +21 -0
- perceval_interop-0.1.2/PKG-INFO +125 -0
- perceval_interop-0.1.2/README.md +78 -0
- perceval_interop-0.1.2/perceval_interop/__init__.py +27 -0
- perceval_interop-0.1.2/perceval_interop/abstract_converter.py +221 -0
- perceval_interop-0.1.2/perceval_interop/cqasm/__init__.py +24 -0
- perceval_interop-0.1.2/perceval_interop/cqasm/cqasm_converter.py +367 -0
- perceval_interop-0.1.2/perceval_interop/myqlm/__init__.py +23 -0
- perceval_interop-0.1.2/perceval_interop/myqlm/myqlm_converter.py +72 -0
- perceval_interop-0.1.2/perceval_interop/qiskit/__init__.py +26 -0
- perceval_interop-0.1.2/perceval_interop/qiskit/circuit_to_graph_converter.py +160 -0
- perceval_interop-0.1.2/perceval_interop/qiskit/converter_statevector.py +177 -0
- perceval_interop-0.1.2/perceval_interop/qiskit/qiskit_converter.py +88 -0
- perceval_interop-0.1.2/perceval_interop/qiskit/resources_estimator.py +82 -0
- perceval_interop-0.1.2/perceval_interop/utils/__init__.py +24 -0
- perceval_interop-0.1.2/perceval_interop/utils/converter_utils.py +127 -0
- perceval_interop-0.1.2/perceval_interop/utils/metadata.py +51 -0
- perceval_interop-0.1.2/perceval_interop.egg-info/PKG-INFO +125 -0
- perceval_interop-0.1.2/perceval_interop.egg-info/SOURCES.txt +27 -0
- perceval_interop-0.1.2/perceval_interop.egg-info/dependency_links.txt +1 -0
- perceval_interop-0.1.2/perceval_interop.egg-info/requires.txt +21 -0
- perceval_interop-0.1.2/perceval_interop.egg-info/top_level.txt +5 -0
- perceval_interop-0.1.2/setup.cfg +4 -0
- perceval_interop-0.1.2/setup.py +51 -0
- perceval_interop-0.1.2/tests/test_circuit_to_graph_resources_estimator.py +129 -0
- perceval_interop-0.1.2/tests/test_converter_cqasm.py +377 -0
- perceval_interop-0.1.2/tests/test_converter_myqlm.py +269 -0
- perceval_interop-0.1.2/tests/test_converter_qiskit.py +359 -0
- perceval_interop-0.1.2/tests/test_converter_statevector.py +118 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Quandela
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: perceval-interop
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: Interoperability packages between Quantum Computing Framework
|
|
5
|
+
Home-page: https://github.com/Quandela/Perceval_Interop
|
|
6
|
+
Author: quandela
|
|
7
|
+
Project-URL: Documentation, https://perceval.quandela.net/interopdocs/
|
|
8
|
+
Project-URL: Source, https://github.com/Quandela/Perceval_Interop
|
|
9
|
+
Project-URL: Tracker, https://github.com/Quandela/Perceval_Interop/issues
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Requires-Python: >=3.9,<3.14
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Requires-Dist: perceval-quandela~=0.13.1
|
|
21
|
+
Provides-Extra: qiskit-bridge
|
|
22
|
+
Requires-Dist: qiskit~=1.3.1; extra == "qiskit-bridge"
|
|
23
|
+
Requires-Dist: seaborn~=0.13; extra == "qiskit-bridge"
|
|
24
|
+
Provides-Extra: qutip-bridge
|
|
25
|
+
Requires-Dist: qutip~=5.0.4; extra == "qutip-bridge"
|
|
26
|
+
Provides-Extra: myqlm-bridge
|
|
27
|
+
Requires-Dist: myqlm~=1.10.4; extra == "myqlm-bridge"
|
|
28
|
+
Provides-Extra: cqasm-bridge
|
|
29
|
+
Requires-Dist: libqasm==0.6.7; extra == "cqasm-bridge"
|
|
30
|
+
Provides-Extra: all
|
|
31
|
+
Requires-Dist: qiskit~=1.3.1; extra == "all"
|
|
32
|
+
Requires-Dist: seaborn~=0.13; extra == "all"
|
|
33
|
+
Requires-Dist: qutip~=5.0.4; extra == "all"
|
|
34
|
+
Requires-Dist: myqlm~=1.10.4; extra == "all"
|
|
35
|
+
Requires-Dist: libqasm==0.6.7; extra == "all"
|
|
36
|
+
Dynamic: author
|
|
37
|
+
Dynamic: classifier
|
|
38
|
+
Dynamic: description
|
|
39
|
+
Dynamic: description-content-type
|
|
40
|
+
Dynamic: home-page
|
|
41
|
+
Dynamic: license-file
|
|
42
|
+
Dynamic: project-url
|
|
43
|
+
Dynamic: provides-extra
|
|
44
|
+
Dynamic: requires-dist
|
|
45
|
+
Dynamic: requires-python
|
|
46
|
+
Dynamic: summary
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
[](https://github.com/Quandela/Perceval_Interop/releases/latest)
|
|
50
|
+

|
|
51
|
+
[](https://github.com/Quandela/Perceval-Interop/actions/workflows/python-publish.yml)
|
|
52
|
+
|
|
53
|
+
[](https://github.com/Quandela/Perceval_Interop/actions/workflows/autotests.yml)
|
|
54
|
+
[](https://github.com/Quandela/Perceval_Interop/actions/workflows/build-and-deploy-docs.yml)
|
|
55
|
+
|
|
56
|
+
# Perceval_Interop <a href="https://perceval.quandela.net" target="_blank"> <img src="logo-perceval.png" width="50" height="50"> </a>
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
Perceval_Interop is designed to facilitate a bridge between Perceval, a photonic quantum
|
|
60
|
+
computing framework, and several leading gate-based frameworks through a python API.
|
|
61
|
+
|
|
62
|
+
It provides converters to translate gate-based quantum circuits from various frameworks
|
|
63
|
+
into Perceval's linear optical circuits using dual rail encoding. Currently
|
|
64
|
+
supported frameworks include:
|
|
65
|
+
|
|
66
|
+
- Quantum gate circuit conversion from **Qiskit**, **myQLM**, and **cQASM**.
|
|
67
|
+
- Quantum states conversion from **Qutip**.
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
# Installation
|
|
71
|
+
|
|
72
|
+
Perceval-Interop requires:
|
|
73
|
+
|
|
74
|
+
* Python between 3.9 and 3.13
|
|
75
|
+
|
|
76
|
+
## PIP
|
|
77
|
+
We recommend installing it with `pip`, and selecting any interop package such as `qiskit`, `qutip`, `myqlm`, or `cqasm`:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
pip install --upgrade pip
|
|
81
|
+
pip install perceval-interop[qiskit_bridge] #install qiskit and seaborn
|
|
82
|
+
pip install perceval-interop[qutip_bridge] #install qutip
|
|
83
|
+
pip install perceval-interop[myqlm_bridge] #install myqlm
|
|
84
|
+
pip install perceval-interop[cqasm_bridge] #install cqasm
|
|
85
|
+
pip install perceval-interop[all] #install all above
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## GitHub
|
|
89
|
+
```bash
|
|
90
|
+
git clone https://github.com/quandela/Perceval
|
|
91
|
+
```
|
|
92
|
+
then to install Perceval:
|
|
93
|
+
```bash
|
|
94
|
+
pip install .
|
|
95
|
+
```
|
|
96
|
+
Or for developers:
|
|
97
|
+
```bash
|
|
98
|
+
pip install -e .
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
# Running tests
|
|
102
|
+
|
|
103
|
+
Unit tests files are part of the repository in `tests/` and can be run with:
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
pip install -r tests/requirements.txt
|
|
107
|
+
pytest
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Additionally, you can see a coverage report with the command:
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
pytest --cov=perceval-interop
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
# Documentation and Forum
|
|
117
|
+
|
|
118
|
+
* The [documentation](https://perceval.quandela.net/interopdocs/)
|
|
119
|
+
* The [Community Forum](https://perceval.quandela.net/forum)
|
|
120
|
+
|
|
121
|
+
#
|
|
122
|
+
[<img src="logo-quandela.png" width="300" height=auto>](https://www.quandela.com/)
|
|
123
|
+
|
|
124
|
+
[](https://twitter.com/Quandela_SAS)
|
|
125
|
+
[](https://www.youtube.com/channel/UCl5YMpSqknJ1n-IT-XWfLsQ)
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
|
|
2
|
+
[](https://github.com/Quandela/Perceval_Interop/releases/latest)
|
|
3
|
+

|
|
4
|
+
[](https://github.com/Quandela/Perceval-Interop/actions/workflows/python-publish.yml)
|
|
5
|
+
|
|
6
|
+
[](https://github.com/Quandela/Perceval_Interop/actions/workflows/autotests.yml)
|
|
7
|
+
[](https://github.com/Quandela/Perceval_Interop/actions/workflows/build-and-deploy-docs.yml)
|
|
8
|
+
|
|
9
|
+
# Perceval_Interop <a href="https://perceval.quandela.net" target="_blank"> <img src="logo-perceval.png" width="50" height="50"> </a>
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
Perceval_Interop is designed to facilitate a bridge between Perceval, a photonic quantum
|
|
13
|
+
computing framework, and several leading gate-based frameworks through a python API.
|
|
14
|
+
|
|
15
|
+
It provides converters to translate gate-based quantum circuits from various frameworks
|
|
16
|
+
into Perceval's linear optical circuits using dual rail encoding. Currently
|
|
17
|
+
supported frameworks include:
|
|
18
|
+
|
|
19
|
+
- Quantum gate circuit conversion from **Qiskit**, **myQLM**, and **cQASM**.
|
|
20
|
+
- Quantum states conversion from **Qutip**.
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# Installation
|
|
24
|
+
|
|
25
|
+
Perceval-Interop requires:
|
|
26
|
+
|
|
27
|
+
* Python between 3.9 and 3.13
|
|
28
|
+
|
|
29
|
+
## PIP
|
|
30
|
+
We recommend installing it with `pip`, and selecting any interop package such as `qiskit`, `qutip`, `myqlm`, or `cqasm`:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install --upgrade pip
|
|
34
|
+
pip install perceval-interop[qiskit_bridge] #install qiskit and seaborn
|
|
35
|
+
pip install perceval-interop[qutip_bridge] #install qutip
|
|
36
|
+
pip install perceval-interop[myqlm_bridge] #install myqlm
|
|
37
|
+
pip install perceval-interop[cqasm_bridge] #install cqasm
|
|
38
|
+
pip install perceval-interop[all] #install all above
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## GitHub
|
|
42
|
+
```bash
|
|
43
|
+
git clone https://github.com/quandela/Perceval
|
|
44
|
+
```
|
|
45
|
+
then to install Perceval:
|
|
46
|
+
```bash
|
|
47
|
+
pip install .
|
|
48
|
+
```
|
|
49
|
+
Or for developers:
|
|
50
|
+
```bash
|
|
51
|
+
pip install -e .
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
# Running tests
|
|
55
|
+
|
|
56
|
+
Unit tests files are part of the repository in `tests/` and can be run with:
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
pip install -r tests/requirements.txt
|
|
60
|
+
pytest
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Additionally, you can see a coverage report with the command:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
pytest --cov=perceval-interop
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
# Documentation and Forum
|
|
70
|
+
|
|
71
|
+
* The [documentation](https://perceval.quandela.net/interopdocs/)
|
|
72
|
+
* The [Community Forum](https://perceval.quandela.net/forum)
|
|
73
|
+
|
|
74
|
+
#
|
|
75
|
+
[<img src="logo-quandela.png" width="300" height=auto>](https://www.quandela.com/)
|
|
76
|
+
|
|
77
|
+
[](https://twitter.com/Quandela_SAS)
|
|
78
|
+
[](https://www.youtube.com/channel/UCl5YMpSqknJ1n-IT-XWfLsQ)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2025 Quandela
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
# furnished to do so, subject to the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
# copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
# SOFTWARE.
|
|
22
|
+
|
|
23
|
+
from .abstract_converter import AGateConverter
|
|
24
|
+
from .myqlm import MyQLMConverter
|
|
25
|
+
from .qiskit import QiskitConverter, StatevectorConverter, CircuitToGraphConverter
|
|
26
|
+
from .cqasm import CQASMConverter, ConversionSyntaxError, ConversionUnsupportedFeatureError, ConversionBadVersionError
|
|
27
|
+
from .utils import *
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2025 Quandela
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
# furnished to do so, subject to the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
# copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
# SOFTWARE.
|
|
22
|
+
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
from abc import ABC, abstractmethod
|
|
26
|
+
|
|
27
|
+
from perceval.components import Port, Circuit, Processor, catalog, AProcessor
|
|
28
|
+
from perceval.utils import P, BasicState, Encoding, global_params, PostSelect, NoiseModel
|
|
29
|
+
from perceval.utils.algorithms.optimize import optimize
|
|
30
|
+
from perceval.utils.algorithms.norm import frobenius
|
|
31
|
+
import perceval.components.unitary_components as comp
|
|
32
|
+
from perceval_interop.utils.converter_utils import label_cnots_in_gate_sequence
|
|
33
|
+
|
|
34
|
+
def _create_mode_map(c_idx: int, c_data: int) -> dict:
|
|
35
|
+
return {c_idx: 0, c_idx + 1: 1, c_data: 2, c_data + 1: 3}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class UnknownGateError(Exception):
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class AGateConverter(ABC):
|
|
43
|
+
r"""
|
|
44
|
+
Converter class for gate based Circuits to perceval processor
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
def __init__(self, backend_name: str = "SLOS", noise_model: NoiseModel = None):
|
|
48
|
+
self._converted_processor: AProcessor | None = None # TODO: replace by Experiment?
|
|
49
|
+
self._input_list = None # input state in list
|
|
50
|
+
self._noise_model = noise_model
|
|
51
|
+
self._backend_name = backend_name
|
|
52
|
+
|
|
53
|
+
# Define function handler to create complex components
|
|
54
|
+
# Users could override them
|
|
55
|
+
self.create_hcnot_processor = catalog["heralded cnot"].build_processor
|
|
56
|
+
self.create_hcz_processor = catalog["heralded cz"].build_processor
|
|
57
|
+
self.create_ppcnot_processor = catalog["postprocessed cnot"].build_processor
|
|
58
|
+
self.create_generic_2mode_circuit = catalog["generic 2 mode circuit"].build_circuit
|
|
59
|
+
self.create_lower_phase_circuit = lambda: Circuit(2) // (0, comp.PS(P("phi2")))
|
|
60
|
+
self.create_upper_phase_circuit = lambda: Circuit(2) // (1, comp.PS(P("phi1")))
|
|
61
|
+
self.create_2phase_circuit = lambda: Circuit(2) // (0, comp.PS(P("phi1"))) // (1, comp.PS(P("phi2")))
|
|
62
|
+
|
|
63
|
+
@abstractmethod
|
|
64
|
+
def count_qubits(self, gate_circuit) -> int:
|
|
65
|
+
pass
|
|
66
|
+
|
|
67
|
+
@abstractmethod
|
|
68
|
+
def _get_gate_sequence(self, gate_circuit) -> list[list]:
|
|
69
|
+
"""
|
|
70
|
+
Iterates over the gate circuit to return a list of Gate operations in the circuit to convert to LO circuit.
|
|
71
|
+
The information in each element of the list is - [gate name, gate qubit positions, gate parameters, gate unitary]
|
|
72
|
+
Note - Gate parameter or gate unitary can be None if value is not needed.
|
|
73
|
+
"""
|
|
74
|
+
pass
|
|
75
|
+
|
|
76
|
+
@abstractmethod
|
|
77
|
+
def _get_qubit_names(self, gate_circuit, n_qbits) -> list:
|
|
78
|
+
"""
|
|
79
|
+
Returns a list of Qubit names for a given 'n_qubits' gate circuit. Use 'Q' as the default name
|
|
80
|
+
unless the framework provides a custom name.
|
|
81
|
+
"""
|
|
82
|
+
pass
|
|
83
|
+
|
|
84
|
+
def _configure_processor(self, gate_circuit, **kwargs):
|
|
85
|
+
"""
|
|
86
|
+
Sets port Encoding and default input state for the Processor
|
|
87
|
+
"""
|
|
88
|
+
n_qbits = self.count_qubits(gate_circuit)
|
|
89
|
+
qubit_names = self._get_qubit_names(gate_circuit, n_qbits)
|
|
90
|
+
|
|
91
|
+
n_moi = n_qbits * 2 # In dual rail, number of modes of interest = 2 * number of qbits
|
|
92
|
+
self._input_list = [0] * n_moi
|
|
93
|
+
self._converted_processor = Processor(self._backend_name, n_moi, noise=self._noise_model)
|
|
94
|
+
for i in range(n_qbits):
|
|
95
|
+
self._converted_processor.add_port(i * 2, Port(Encoding.DUAL_RAIL, qubit_names[i]))
|
|
96
|
+
self._input_list[i * 2] = 1
|
|
97
|
+
|
|
98
|
+
def apply_input_state(self):
|
|
99
|
+
default_input_state = BasicState(self._input_list)
|
|
100
|
+
self._converted_processor.min_detected_photons_filter(default_input_state.n)
|
|
101
|
+
self._converted_processor.with_input(default_input_state)
|
|
102
|
+
|
|
103
|
+
def convert(self, gate_circuit, use_postselection: bool = True) -> Processor:
|
|
104
|
+
"""Convert a gate-based quantum circuit into a `Processor`.
|
|
105
|
+
|
|
106
|
+
:param gate_circuit: gate-based quantum circuit (Qiskit, Myqlm or CQASM)
|
|
107
|
+
:param use_postselection: when True (default), uses optimized number of `postprocessed CNOT` and
|
|
108
|
+
'Heralded CNOT' gates. Otherwise, uses only `heralded CNOT`.
|
|
109
|
+
|
|
110
|
+
:return: the converted processor
|
|
111
|
+
"""
|
|
112
|
+
self._configure_processor(gate_circuit) # empty processor with ports initialized
|
|
113
|
+
gate_sequence = self._get_gate_sequence(gate_circuit)
|
|
114
|
+
|
|
115
|
+
return self._generate_converted_processor(gate_sequence, use_postselection=use_postselection)
|
|
116
|
+
|
|
117
|
+
def _generate_converted_processor(self, gate_sequence: list, use_postselection: bool) -> Processor:
|
|
118
|
+
# gate_inf -> [gate name, gate qubit pos, gate parameter if any or None, unitary Matrix or None]
|
|
119
|
+
|
|
120
|
+
optimized_gate_sequence = label_cnots_in_gate_sequence(gate_sequence)
|
|
121
|
+
|
|
122
|
+
for gate_index, gate_inf in enumerate(gate_sequence):
|
|
123
|
+
gate_name = gate_inf[0]
|
|
124
|
+
|
|
125
|
+
if len(gate_inf[1]) == 1:
|
|
126
|
+
if gate_name in catalog:
|
|
127
|
+
gate_param = gate_inf[2]
|
|
128
|
+
ins = self._create_catalog_1_qubit_gate(gate_name, param=gate_param)
|
|
129
|
+
else:
|
|
130
|
+
ins = self._create_generic_1_qubit_gate(gate_inf[3])
|
|
131
|
+
ins._name = gate_inf[0]
|
|
132
|
+
self._converted_processor.add(gate_inf[1][0] * 2, ins.copy())
|
|
133
|
+
|
|
134
|
+
else:
|
|
135
|
+
if len(gate_inf[1]) > 2:
|
|
136
|
+
raise NotImplementedError("2+ Qubit gates not implemented")
|
|
137
|
+
|
|
138
|
+
c_idx = gate_inf[1][0] * 2
|
|
139
|
+
c_data = gate_inf[1][1] * 2
|
|
140
|
+
self._create_2_qubit_gates_from_catalog(optimized_gate_sequence[gate_index], c_idx, c_data,
|
|
141
|
+
use_postselection)
|
|
142
|
+
self.apply_input_state()
|
|
143
|
+
return self._converted_processor
|
|
144
|
+
|
|
145
|
+
def _create_catalog_1_qubit_gate(self, gate_name: str, **kwargs) -> Processor:
|
|
146
|
+
param = kwargs.get("param", None)
|
|
147
|
+
if gate_name in ["rx", "ry", "rz"]:
|
|
148
|
+
return catalog[gate_name].build_processor(theta=param)
|
|
149
|
+
elif gate_name in ["ph"]:
|
|
150
|
+
return catalog[gate_name].build_processor(phi=param)
|
|
151
|
+
else:
|
|
152
|
+
return catalog[gate_name].build_processor()
|
|
153
|
+
|
|
154
|
+
def _create_generic_1_qubit_gate(self, u) -> Circuit:
|
|
155
|
+
# universal method, takes in unitary and approximates one using
|
|
156
|
+
# Frobenius method
|
|
157
|
+
if abs(u[1, 0]) + abs(u[0, 1]) < 2 * global_params["min_precision_gate"]:
|
|
158
|
+
# diagonal matrix - we can handle with phases, we consider that gate unitary parameters has
|
|
159
|
+
# limited numeric precision
|
|
160
|
+
if abs(u[0, 0] - 1) < global_params["min_precision_gate"]:
|
|
161
|
+
if abs(u[1, 1] - 1) < global_params["min_precision_gate"]:
|
|
162
|
+
return Circuit(2, name="I") # returns Identity/empty circuit
|
|
163
|
+
ins = self.create_upper_phase_circuit()
|
|
164
|
+
else:
|
|
165
|
+
if abs(u[1, 1] - 1) < global_params["min_precision_gate"]:
|
|
166
|
+
ins = self.create_lower_phase_circuit()
|
|
167
|
+
else:
|
|
168
|
+
ins = self.create_2phase_circuit()
|
|
169
|
+
optimize(ins, u, frobenius, sign=-1)
|
|
170
|
+
else:
|
|
171
|
+
ins = self.create_generic_2mode_circuit()
|
|
172
|
+
optimize(ins, u, frobenius, sign=-1)
|
|
173
|
+
return ins
|
|
174
|
+
|
|
175
|
+
def _create_2_qubit_gates_from_catalog(self, gate_name: str, c_idx: int, c_data: int, use_postselection: bool):
|
|
176
|
+
r"""
|
|
177
|
+
List of Gates implemented:
|
|
178
|
+
CNOT - Heralded and post-processed
|
|
179
|
+
CZ - Heralded
|
|
180
|
+
CRz - Heralded and post-processed (uses two CNOTs)
|
|
181
|
+
SWAP
|
|
182
|
+
"""
|
|
183
|
+
# Save and clear current post-selection data from the converted processor before adding the next gate
|
|
184
|
+
if self._converted_processor.post_select_fn is not None:
|
|
185
|
+
post_select_curr = self._converted_processor.post_select_fn
|
|
186
|
+
else:
|
|
187
|
+
post_select_curr = PostSelect() # save empty if I need to merge incoming PostSelect to it
|
|
188
|
+
self._converted_processor.clear_postselection() # clear current post-selection
|
|
189
|
+
|
|
190
|
+
gate_name = gate_name.upper()
|
|
191
|
+
if gate_name in ["POSTPROCESSED CNOT", "HERALDED CNOT"]:
|
|
192
|
+
if use_postselection and gate_name == "POSTPROCESSED CNOT":
|
|
193
|
+
cnot_processor = self.create_ppcnot_processor()
|
|
194
|
+
else:
|
|
195
|
+
cnot_processor = self.create_hcnot_processor()
|
|
196
|
+
|
|
197
|
+
self._converted_processor.add(_create_mode_map(c_idx, c_data), cnot_processor)
|
|
198
|
+
if self._converted_processor.post_select_fn is not None:
|
|
199
|
+
post_select_curr.merge(self._converted_processor.post_select_fn)
|
|
200
|
+
|
|
201
|
+
elif gate_name in ["CSIGN", "CZ"]:
|
|
202
|
+
# Controlled Z in myqlm is named CSIGN
|
|
203
|
+
cz_processor = self.create_hcz_processor()
|
|
204
|
+
self._converted_processor.add(_create_mode_map(c_idx, c_data), cz_processor)
|
|
205
|
+
elif gate_name == "SWAP":
|
|
206
|
+
# Works for any FIRST and LAST, everything in-between is unchanged.
|
|
207
|
+
c_first = min(c_idx, c_data)
|
|
208
|
+
c_last = max(c_idx, c_data)
|
|
209
|
+
n = (c_last - c_first) // 2 + 1
|
|
210
|
+
perm = [i for i in range(n * 2)]
|
|
211
|
+
perm[0] = c_last - c_first
|
|
212
|
+
perm[1] = perm[0] + 1
|
|
213
|
+
perm[perm[0]] = 0
|
|
214
|
+
perm[perm[1]] = 1
|
|
215
|
+
self._converted_processor.add(c_first, comp.PERM(perm))
|
|
216
|
+
else:
|
|
217
|
+
raise UnknownGateError(f"Gate not yet supported: {gate_name}")
|
|
218
|
+
|
|
219
|
+
# re-apply the cleared post-selection
|
|
220
|
+
self._converted_processor.set_postselection(post_select_curr)
|
|
221
|
+
return self._converted_processor
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2025 Quandela
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
# furnished to do so, subject to the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
# copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
# SOFTWARE.
|
|
22
|
+
|
|
23
|
+
from .cqasm_converter import (CQASMConverter, ConversionSyntaxError,
|
|
24
|
+
ConversionUnsupportedFeatureError, ConversionBadVersionError)
|