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.
Files changed (29) hide show
  1. perceval_interop-0.1.2/LICENSE +21 -0
  2. perceval_interop-0.1.2/PKG-INFO +125 -0
  3. perceval_interop-0.1.2/README.md +78 -0
  4. perceval_interop-0.1.2/perceval_interop/__init__.py +27 -0
  5. perceval_interop-0.1.2/perceval_interop/abstract_converter.py +221 -0
  6. perceval_interop-0.1.2/perceval_interop/cqasm/__init__.py +24 -0
  7. perceval_interop-0.1.2/perceval_interop/cqasm/cqasm_converter.py +367 -0
  8. perceval_interop-0.1.2/perceval_interop/myqlm/__init__.py +23 -0
  9. perceval_interop-0.1.2/perceval_interop/myqlm/myqlm_converter.py +72 -0
  10. perceval_interop-0.1.2/perceval_interop/qiskit/__init__.py +26 -0
  11. perceval_interop-0.1.2/perceval_interop/qiskit/circuit_to_graph_converter.py +160 -0
  12. perceval_interop-0.1.2/perceval_interop/qiskit/converter_statevector.py +177 -0
  13. perceval_interop-0.1.2/perceval_interop/qiskit/qiskit_converter.py +88 -0
  14. perceval_interop-0.1.2/perceval_interop/qiskit/resources_estimator.py +82 -0
  15. perceval_interop-0.1.2/perceval_interop/utils/__init__.py +24 -0
  16. perceval_interop-0.1.2/perceval_interop/utils/converter_utils.py +127 -0
  17. perceval_interop-0.1.2/perceval_interop/utils/metadata.py +51 -0
  18. perceval_interop-0.1.2/perceval_interop.egg-info/PKG-INFO +125 -0
  19. perceval_interop-0.1.2/perceval_interop.egg-info/SOURCES.txt +27 -0
  20. perceval_interop-0.1.2/perceval_interop.egg-info/dependency_links.txt +1 -0
  21. perceval_interop-0.1.2/perceval_interop.egg-info/requires.txt +21 -0
  22. perceval_interop-0.1.2/perceval_interop.egg-info/top_level.txt +5 -0
  23. perceval_interop-0.1.2/setup.cfg +4 -0
  24. perceval_interop-0.1.2/setup.py +51 -0
  25. perceval_interop-0.1.2/tests/test_circuit_to_graph_resources_estimator.py +129 -0
  26. perceval_interop-0.1.2/tests/test_converter_cqasm.py +377 -0
  27. perceval_interop-0.1.2/tests/test_converter_myqlm.py +269 -0
  28. perceval_interop-0.1.2/tests/test_converter_qiskit.py +359 -0
  29. 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
+ [![GitHub release](https://img.shields.io/github/v/release/Quandela/Perceval_Interop.svg?style=plastic)](https://github.com/Quandela/Perceval_Interop/releases/latest)
50
+ ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/perceval-interop?style=plastic)
51
+ [![CI](https://github.com/Quandela/Perceval_Interop/actions/workflows/python-publish.yml/badge.svg)](https://github.com/Quandela/Perceval-Interop/actions/workflows/python-publish.yml)
52
+
53
+ [![CI](https://github.com/Quandela/Perceval_Interop/actions/workflows/autotests.yml/badge.svg)](https://github.com/Quandela/Perceval_Interop/actions/workflows/autotests.yml)
54
+ [![CI](https://github.com/Quandela/Perceval_Interop/actions/workflows/build-and-deploy-docs.yml/badge.svg)](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
+ [![Twitter Follow](https://img.shields.io/twitter/follow/Quandela_SAS?style=social)](https://twitter.com/Quandela_SAS)
125
+ [![YouTube Channel Subscribers](https://img.shields.io/youtube/channel/subscribers/UCl5YMpSqknJ1n-IT-XWfLsQ?style=social)](https://www.youtube.com/channel/UCl5YMpSqknJ1n-IT-XWfLsQ)
@@ -0,0 +1,78 @@
1
+
2
+ [![GitHub release](https://img.shields.io/github/v/release/Quandela/Perceval_Interop.svg?style=plastic)](https://github.com/Quandela/Perceval_Interop/releases/latest)
3
+ ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/perceval-interop?style=plastic)
4
+ [![CI](https://github.com/Quandela/Perceval_Interop/actions/workflows/python-publish.yml/badge.svg)](https://github.com/Quandela/Perceval-Interop/actions/workflows/python-publish.yml)
5
+
6
+ [![CI](https://github.com/Quandela/Perceval_Interop/actions/workflows/autotests.yml/badge.svg)](https://github.com/Quandela/Perceval_Interop/actions/workflows/autotests.yml)
7
+ [![CI](https://github.com/Quandela/Perceval_Interop/actions/workflows/build-and-deploy-docs.yml/badge.svg)](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
+ [![Twitter Follow](https://img.shields.io/twitter/follow/Quandela_SAS?style=social)](https://twitter.com/Quandela_SAS)
78
+ [![YouTube Channel Subscribers](https://img.shields.io/youtube/channel/subscribers/UCl5YMpSqknJ1n-IT-XWfLsQ?style=social)](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)