roqoqo_qiskit_devices/
devices.rs

1// Copyright © 2023-2025 HQS Quantum Simulations GmbH. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
4// in compliance with the License. You may obtain a copy of the License at
5//
6//     http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software distributed under the
9// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
10// express or implied. See the License for the specific language governing permissions and
11// limitations under the License.
12
13//! IBM Devices
14//!
15//! Provides the devices that are used to execute quantum programs on IBM's devices.
16
17use roqoqo::devices::{GenericDevice, QoqoDevice};
18use roqoqo::RoqoqoError;
19
20mod ibm_belem;
21pub use crate::devices::ibm_belem::IBMBelemDevice;
22
23mod ibm_jakarta;
24pub use crate::devices::ibm_jakarta::IBMJakartaDevice;
25
26mod ibm_lagos;
27pub use crate::devices::ibm_lagos::IBMLagosDevice;
28
29mod ibm_lima;
30pub use crate::devices::ibm_lima::IBMLimaDevice;
31
32mod ibm_manila;
33pub use crate::devices::ibm_manila::IBMManilaDevice;
34
35mod ibm_nairobi;
36pub use crate::devices::ibm_nairobi::IBMNairobiDevice;
37
38mod ibm_perth;
39pub use crate::devices::ibm_perth::IBMPerthDevice;
40
41mod ibm_quito;
42pub use crate::devices::ibm_quito::IBMQuitoDevice;
43
44/// Collection of IBM quantum devices.
45///
46pub enum IBMDevice {
47    IBMLagosDevice(IBMLagosDevice),
48    IBMNairobiDevice(IBMNairobiDevice),
49    IBMPerthDevice(IBMPerthDevice),
50    IBMBelemDevice(IBMBelemDevice),
51    IBMJakartaDevice(IBMJakartaDevice),
52    IBMLimaDevice(IBMLimaDevice),
53    IBMManilaDevice(IBMManilaDevice),
54    IBMQuitoDevice(IBMQuitoDevice),
55}
56
57impl IBMDevice {
58    /// Returns the IBM's identifier.
59    ///
60    /// # Returns
61    ///
62    /// A str of the name IBM uses as identifier.
63    pub fn name(self) -> &'static str {
64        match self {
65            IBMDevice::IBMLagosDevice(x) => x.name(),
66            IBMDevice::IBMNairobiDevice(x) => x.name(),
67            IBMDevice::IBMPerthDevice(x) => x.name(),
68            IBMDevice::IBMBelemDevice(x) => x.name(),
69            IBMDevice::IBMJakartaDevice(x) => x.name(),
70            IBMDevice::IBMLimaDevice(x) => x.name(),
71            IBMDevice::IBMManilaDevice(x) => x.name(),
72            IBMDevice::IBMQuitoDevice(x) => x.name(),
73        }
74    }
75
76    /// Setting the gate time of a single qubit gate.
77    ///
78    /// # Arguments
79    ///
80    /// * `gate` - hqslang name of the single-qubit-gate.
81    /// * `qubit` - The qubit for which the gate time is set.
82    /// * `gate_time` - gate time for the given gate.
83    pub fn set_single_qubit_gate_time(
84        &mut self,
85        gate: &str,
86        qubit: usize,
87        gate_time: f64,
88    ) -> Result<(), RoqoqoError> {
89        match self {
90            IBMDevice::IBMLagosDevice(x) => x.set_single_qubit_gate_time(gate, qubit, gate_time),
91            IBMDevice::IBMNairobiDevice(x) => x.set_single_qubit_gate_time(gate, qubit, gate_time),
92            IBMDevice::IBMPerthDevice(x) => x.set_single_qubit_gate_time(gate, qubit, gate_time),
93            IBMDevice::IBMBelemDevice(x) => x.set_single_qubit_gate_time(gate, qubit, gate_time),
94            IBMDevice::IBMJakartaDevice(x) => x.set_single_qubit_gate_time(gate, qubit, gate_time),
95            IBMDevice::IBMLimaDevice(x) => x.set_single_qubit_gate_time(gate, qubit, gate_time),
96            IBMDevice::IBMManilaDevice(x) => x.set_single_qubit_gate_time(gate, qubit, gate_time),
97            IBMDevice::IBMQuitoDevice(x) => x.set_single_qubit_gate_time(gate, qubit, gate_time),
98        }
99    }
100
101    /// Setting the gate time of a two qubit gate.
102    ///
103    /// # Arguments
104    ///
105    /// * `gate` - hqslang name of the two-qubit-gate.
106    /// * `control` - The control qubit for which the gate time is set.
107    /// * `target` - The target qubit for which the gate time is set.
108    /// * `gate_time` - gate time for the given gate.
109    pub fn set_two_qubit_gate_time(
110        &mut self,
111        gate: &str,
112        control: usize,
113        target: usize,
114        gate_time: f64,
115    ) -> Result<(), RoqoqoError> {
116        match self {
117            IBMDevice::IBMLagosDevice(x) => {
118                x.set_two_qubit_gate_time(gate, control, target, gate_time)
119            }
120            IBMDevice::IBMNairobiDevice(x) => {
121                x.set_two_qubit_gate_time(gate, control, target, gate_time)
122            }
123            IBMDevice::IBMPerthDevice(x) => {
124                x.set_two_qubit_gate_time(gate, control, target, gate_time)
125            }
126            IBMDevice::IBMBelemDevice(x) => {
127                x.set_two_qubit_gate_time(gate, control, target, gate_time)
128            }
129            IBMDevice::IBMJakartaDevice(x) => {
130                x.set_two_qubit_gate_time(gate, control, target, gate_time)
131            }
132            IBMDevice::IBMLimaDevice(x) => {
133                x.set_two_qubit_gate_time(gate, control, target, gate_time)
134            }
135            IBMDevice::IBMManilaDevice(x) => {
136                x.set_two_qubit_gate_time(gate, control, target, gate_time)
137            }
138            IBMDevice::IBMQuitoDevice(x) => {
139                x.set_two_qubit_gate_time(gate, control, target, gate_time)
140            }
141        }
142    }
143
144    /// Adds qubit damping to noise rates.
145    ///
146    /// # Arguments
147    ///
148    /// * `qubit` - The qubit for which the dampins is added.
149    /// * `daming` - The damping rates.
150    pub fn add_damping(&mut self, qubit: usize, damping: f64) -> Result<(), RoqoqoError> {
151        match self {
152            IBMDevice::IBMLagosDevice(x) => x.add_damping(qubit, damping),
153            IBMDevice::IBMNairobiDevice(x) => x.add_damping(qubit, damping),
154            IBMDevice::IBMPerthDevice(x) => x.add_damping(qubit, damping),
155            IBMDevice::IBMBelemDevice(x) => x.add_damping(qubit, damping),
156            IBMDevice::IBMJakartaDevice(x) => x.add_damping(qubit, damping),
157            IBMDevice::IBMLimaDevice(x) => x.add_damping(qubit, damping),
158            IBMDevice::IBMManilaDevice(x) => x.add_damping(qubit, damping),
159            IBMDevice::IBMQuitoDevice(x) => x.add_damping(qubit, damping),
160        }
161    }
162
163    /// Adds qubit dephasing to noise rates.
164    ///
165    /// # Arguments
166    ///
167    /// * `qubit` - The qubit for which the dephasing is added.
168    /// * `dephasing` - The dephasing rates.
169    pub fn add_dephasing(&mut self, qubit: usize, dephasing: f64) -> Result<(), RoqoqoError> {
170        match self {
171            IBMDevice::IBMLagosDevice(x) => x.add_dephasing(qubit, dephasing),
172            IBMDevice::IBMNairobiDevice(x) => x.add_dephasing(qubit, dephasing),
173            IBMDevice::IBMPerthDevice(x) => x.add_dephasing(qubit, dephasing),
174            IBMDevice::IBMBelemDevice(x) => x.add_dephasing(qubit, dephasing),
175            IBMDevice::IBMJakartaDevice(x) => x.add_dephasing(qubit, dephasing),
176            IBMDevice::IBMLimaDevice(x) => x.add_dephasing(qubit, dephasing),
177            IBMDevice::IBMManilaDevice(x) => x.add_dephasing(qubit, dephasing),
178            IBMDevice::IBMQuitoDevice(x) => x.add_dephasing(qubit, dephasing),
179        }
180    }
181
182    /// Converts the device to a qoqo GenericDevice.
183    ///
184    /// # Returns
185    ///
186    /// * `GenericDevice` - The converted device.
187    /// * `RoqoqoError` - The error propagated from adding gate times and decoherence rates.
188    pub fn to_generic_device(&self) -> Result<GenericDevice, RoqoqoError> {
189        let mut new_generic_device = GenericDevice::new(self.number_qubits());
190
191        // Gate times
192        for gate in self.single_qubit_gate_names() {
193            for qubit in 0..self.number_qubits() {
194                if let Some(x) = self.single_qubit_gate_time(gate.as_str(), &qubit) {
195                    new_generic_device.set_single_qubit_gate_time(gate.as_str(), qubit, x)?;
196                }
197            }
198        }
199        for gate in self.two_qubit_gate_names() {
200            for (control, target) in self.two_qubit_edges() {
201                if let Some(x) = self.two_qubit_gate_time(gate.as_str(), &control, &target) {
202                    new_generic_device.set_two_qubit_gate_time(
203                        gate.as_str(),
204                        control,
205                        target,
206                        x,
207                    )?;
208                }
209            }
210            for (control, target) in self.two_qubit_edges() {
211                if let Some(x) = self.two_qubit_gate_time(gate.as_str(), &target, &control) {
212                    new_generic_device.set_two_qubit_gate_time(
213                        gate.as_str(),
214                        target,
215                        control,
216                        x,
217                    )?;
218                }
219            }
220        }
221        // for gate in self.multi_qubit_gate_names() {} // - skipped here as none of the devies have multi-qubit gates
222
223        // Decoherence rates
224        for qubit in 0..self.number_qubits() {
225            if let Some(x) = self.qubit_decoherence_rates(&qubit) {
226                new_generic_device.set_qubit_decoherence_rates(qubit, x)?;
227            }
228        }
229
230        Ok(new_generic_device)
231    }
232}
233
234/// Implements the Device trait for IBMDevice.
235///
236/// Defines standard functions available for roqoqo-iqm devices.
237impl QoqoDevice for IBMDevice {
238    /// Returns the gate time of a single qubit operation if the single qubit operation is available on device.
239    ///
240    /// # Arguments
241    ///
242    /// * `hqslang` - The hqslang name of a single qubit gate.
243    /// * `qubit` - The qubit the gate acts on.
244    ///
245    /// # Returns
246    ///
247    /// * `Some<f64>` - The gate time.
248    /// * `None` - The gate is not available on the device.
249    ///
250    fn single_qubit_gate_time(&self, hqslang: &str, qubit: &usize) -> Option<f64> {
251        match self {
252            IBMDevice::IBMLagosDevice(x) => x.single_qubit_gate_time(hqslang, qubit),
253            IBMDevice::IBMNairobiDevice(x) => x.single_qubit_gate_time(hqslang, qubit),
254            IBMDevice::IBMPerthDevice(x) => x.single_qubit_gate_time(hqslang, qubit),
255            IBMDevice::IBMBelemDevice(x) => x.single_qubit_gate_time(hqslang, qubit),
256            IBMDevice::IBMJakartaDevice(x) => x.single_qubit_gate_time(hqslang, qubit),
257            IBMDevice::IBMLimaDevice(x) => x.single_qubit_gate_time(hqslang, qubit),
258            IBMDevice::IBMManilaDevice(x) => x.single_qubit_gate_time(hqslang, qubit),
259            IBMDevice::IBMQuitoDevice(x) => x.single_qubit_gate_time(hqslang, qubit),
260        }
261    }
262
263    /// Returns the names of a single qubit operations available on the device.
264    ///
265    /// # Returns
266    ///
267    /// * `Vec<String>` - The list of gate names.
268    ///
269    fn single_qubit_gate_names(&self) -> Vec<String> {
270        match self {
271            IBMDevice::IBMLagosDevice(x) => x.single_qubit_gate_names(),
272            IBMDevice::IBMNairobiDevice(x) => x.single_qubit_gate_names(),
273            IBMDevice::IBMPerthDevice(x) => x.single_qubit_gate_names(),
274            IBMDevice::IBMBelemDevice(x) => x.single_qubit_gate_names(),
275            IBMDevice::IBMJakartaDevice(x) => x.single_qubit_gate_names(),
276            IBMDevice::IBMLimaDevice(x) => x.single_qubit_gate_names(),
277            IBMDevice::IBMManilaDevice(x) => x.single_qubit_gate_names(),
278            IBMDevice::IBMQuitoDevice(x) => x.single_qubit_gate_names(),
279        }
280    }
281
282    /// Returns the gate time of a two qubit operation if the two qubit operation is available on device.
283    ///
284    /// # Arguments
285    ///
286    /// * `hqslang` - The hqslang name of a two qubit gate.
287    /// * `control` - The control qubit the gate acts on.
288    /// * `target` - The target qubit the gate acts on.
289    ///
290    /// # Returns
291    ///
292    /// * `Some<f64>` - The gate time.
293    /// * `None` - The gate is not available on the device.
294    ///
295    fn two_qubit_gate_time(&self, hqslang: &str, control: &usize, target: &usize) -> Option<f64> {
296        match self {
297            IBMDevice::IBMLagosDevice(x) => x.two_qubit_gate_time(hqslang, control, target),
298            IBMDevice::IBMNairobiDevice(x) => x.two_qubit_gate_time(hqslang, control, target),
299            IBMDevice::IBMPerthDevice(x) => x.two_qubit_gate_time(hqslang, control, target),
300            IBMDevice::IBMBelemDevice(x) => x.two_qubit_gate_time(hqslang, control, target),
301            IBMDevice::IBMJakartaDevice(x) => x.two_qubit_gate_time(hqslang, control, target),
302            IBMDevice::IBMLimaDevice(x) => x.two_qubit_gate_time(hqslang, control, target),
303            IBMDevice::IBMManilaDevice(x) => x.two_qubit_gate_time(hqslang, control, target),
304            IBMDevice::IBMQuitoDevice(x) => x.two_qubit_gate_time(hqslang, control, target),
305        }
306    }
307
308    /// Returns the names of a two qubit operations available on the device.
309    ///
310    /// # Returns
311    ///
312    /// * `Vec<String>` - The list of gate names.
313    ///
314    fn two_qubit_gate_names(&self) -> Vec<String> {
315        match self {
316            IBMDevice::IBMLagosDevice(x) => x.two_qubit_gate_names(),
317            IBMDevice::IBMNairobiDevice(x) => x.two_qubit_gate_names(),
318            IBMDevice::IBMPerthDevice(x) => x.two_qubit_gate_names(),
319            IBMDevice::IBMBelemDevice(x) => x.two_qubit_gate_names(),
320            IBMDevice::IBMJakartaDevice(x) => x.two_qubit_gate_names(),
321            IBMDevice::IBMLimaDevice(x) => x.two_qubit_gate_names(),
322            IBMDevice::IBMManilaDevice(x) => x.two_qubit_gate_names(),
323            IBMDevice::IBMQuitoDevice(x) => x.two_qubit_gate_names(),
324        }
325    }
326
327    /// Returns the gate time of a three qubit operation if the three qubit operation is available on device.
328    ///
329    /// # Arguments
330    ///
331    /// * `hqslang` - The hqslang name of a two qubit gate.
332    /// * `control` - The control qubit the gate acts on.
333    /// * `target` - The target qubit the gate acts on.
334    ///
335    /// # Returns
336    ///
337    /// * `Some<f64>` - The gate time.
338    /// * `None` - The gate is not available on the device.
339    ///
340    fn three_qubit_gate_time(
341        &self,
342        hqslang: &str,
343        control_0: &usize,
344        control_1: &usize,
345        target: &usize,
346    ) -> Option<f64> {
347        match self {
348            IBMDevice::IBMLagosDevice(x) => {
349                x.three_qubit_gate_time(hqslang, control_0, control_1, target)
350            }
351            IBMDevice::IBMNairobiDevice(x) => {
352                x.three_qubit_gate_time(hqslang, control_0, control_1, target)
353            }
354            IBMDevice::IBMPerthDevice(x) => {
355                x.three_qubit_gate_time(hqslang, control_0, control_1, target)
356            }
357            IBMDevice::IBMBelemDevice(x) => {
358                x.three_qubit_gate_time(hqslang, control_0, control_1, target)
359            }
360            IBMDevice::IBMJakartaDevice(x) => {
361                x.three_qubit_gate_time(hqslang, control_0, control_1, target)
362            }
363            IBMDevice::IBMLimaDevice(x) => {
364                x.three_qubit_gate_time(hqslang, control_0, control_1, target)
365            }
366            IBMDevice::IBMManilaDevice(x) => {
367                x.three_qubit_gate_time(hqslang, control_0, control_1, target)
368            }
369            IBMDevice::IBMQuitoDevice(x) => {
370                x.three_qubit_gate_time(hqslang, control_0, control_1, target)
371            }
372        }
373    }
374
375    /// Returns the gate time of a multi qubit operation if the multi qubit operation is available on device.
376    ///
377    /// # Arguments
378    ///
379    /// * `hqslang` - The hqslang name of a multi qubit gate.
380    /// * `qubits` - The qubits the gate acts on.
381    ///
382    /// # Returns
383    ///
384    /// * `Some<f64>` - The gate time.
385    /// * `None` - The gate is not available on the device.
386    ///
387    fn multi_qubit_gate_time(&self, hqslang: &str, qubits: &[usize]) -> Option<f64> {
388        match self {
389            IBMDevice::IBMLagosDevice(x) => x.multi_qubit_gate_time(hqslang, qubits),
390            IBMDevice::IBMNairobiDevice(x) => x.multi_qubit_gate_time(hqslang, qubits),
391            IBMDevice::IBMPerthDevice(x) => x.multi_qubit_gate_time(hqslang, qubits),
392            IBMDevice::IBMBelemDevice(x) => x.multi_qubit_gate_time(hqslang, qubits),
393            IBMDevice::IBMJakartaDevice(x) => x.multi_qubit_gate_time(hqslang, qubits),
394            IBMDevice::IBMLimaDevice(x) => x.multi_qubit_gate_time(hqslang, qubits),
395            IBMDevice::IBMManilaDevice(x) => x.multi_qubit_gate_time(hqslang, qubits),
396            IBMDevice::IBMQuitoDevice(x) => x.multi_qubit_gate_time(hqslang, qubits),
397        }
398    }
399
400    /// Returns the names of a multi qubit operations available on the device.
401    ///
402    /// The list of names also includes the three qubit gate operations.
403    ///
404    /// # Returns
405    ///
406    /// * `Vec<String>` - The list of gate names.
407    ///
408    fn multi_qubit_gate_names(&self) -> Vec<String> {
409        match self {
410            IBMDevice::IBMLagosDevice(x) => x.multi_qubit_gate_names(),
411            IBMDevice::IBMNairobiDevice(x) => x.multi_qubit_gate_names(),
412            IBMDevice::IBMPerthDevice(x) => x.multi_qubit_gate_names(),
413            IBMDevice::IBMBelemDevice(x) => x.multi_qubit_gate_names(),
414            IBMDevice::IBMJakartaDevice(x) => x.multi_qubit_gate_names(),
415            IBMDevice::IBMLimaDevice(x) => x.multi_qubit_gate_names(),
416            IBMDevice::IBMManilaDevice(x) => x.multi_qubit_gate_names(),
417            IBMDevice::IBMQuitoDevice(x) => x.multi_qubit_gate_names(),
418        }
419    }
420
421    /// Returns the matrix of the decoherence rates of the Lindblad equation.
422    ///
423    /// # Arguments
424    ///
425    /// * `qubit` - The qubit for which the rate matrix is returned.
426    ///
427    /// # Returns
428    ///
429    /// * `Some<Array2<f64>>` - The decoherence rates.
430    /// * `None` - The qubit is not part of the device.
431    ///
432    fn qubit_decoherence_rates(&self, qubit: &usize) -> Option<ndarray::Array2<f64>> {
433        match self {
434            IBMDevice::IBMLagosDevice(x) => x.qubit_decoherence_rates(qubit),
435            IBMDevice::IBMNairobiDevice(x) => x.qubit_decoherence_rates(qubit),
436            IBMDevice::IBMPerthDevice(x) => x.qubit_decoherence_rates(qubit),
437            IBMDevice::IBMBelemDevice(x) => x.qubit_decoherence_rates(qubit),
438            IBMDevice::IBMJakartaDevice(x) => x.qubit_decoherence_rates(qubit),
439            IBMDevice::IBMLimaDevice(x) => x.qubit_decoherence_rates(qubit),
440            IBMDevice::IBMManilaDevice(x) => x.qubit_decoherence_rates(qubit),
441            IBMDevice::IBMQuitoDevice(x) => x.qubit_decoherence_rates(qubit),
442        }
443    }
444
445    /// Returns the number of qubits the device supports.
446    ///
447    /// # Returns
448    ///
449    /// `usize` - The number of qubits in the device.
450    ///
451    fn number_qubits(&self) -> usize {
452        match self {
453            IBMDevice::IBMLagosDevice(x) => x.number_qubits(),
454            IBMDevice::IBMNairobiDevice(x) => x.number_qubits(),
455            IBMDevice::IBMPerthDevice(x) => x.number_qubits(),
456            IBMDevice::IBMBelemDevice(x) => x.number_qubits(),
457            IBMDevice::IBMJakartaDevice(x) => x.number_qubits(),
458            IBMDevice::IBMLimaDevice(x) => x.number_qubits(),
459            IBMDevice::IBMManilaDevice(x) => x.number_qubits(),
460            IBMDevice::IBMQuitoDevice(x) => x.number_qubits(),
461        }
462    }
463
464    /// Return a list of longest linear chains through the device.
465    ///
466    /// Returns at least one chain of qubits with linear connectivity in the device,
467    /// that has the maximum possible number of qubits with linear connectivity in the device.
468    /// Can return more that one of the possible chains but is not guaranteed to return
469    /// all possible chains. (For example for all-to-all connectivity only one chain will be returned).
470    ///
471    /// # Returns
472    ///
473    /// * `Vec<Vec<usize>>` - A list of the longest chains given by vectors of qubits in the chain.
474    ///
475    fn longest_chains(&self) -> Vec<Vec<usize>> {
476        match self {
477            IBMDevice::IBMLagosDevice(x) => x.longest_chains(),
478            IBMDevice::IBMNairobiDevice(x) => x.longest_chains(),
479            IBMDevice::IBMPerthDevice(x) => x.longest_chains(),
480            IBMDevice::IBMBelemDevice(x) => x.longest_chains(),
481            IBMDevice::IBMJakartaDevice(x) => x.longest_chains(),
482            IBMDevice::IBMLimaDevice(x) => x.longest_chains(),
483            IBMDevice::IBMManilaDevice(x) => x.longest_chains(),
484            IBMDevice::IBMQuitoDevice(x) => x.longest_chains(),
485        }
486    }
487
488    /// Return a list of longest closed linear chains through the device.
489    ///
490    /// Returns at least one chain of qubits with linear connectivity in the device ,
491    /// that has the maximum possible number of qubits with linear connectivity in the device.
492    /// The chain must be closed, the first qubit needs to be connected to the last qubit.
493    /// Can return more that one of the possible chains but is not guaranteed to return
494    /// all possible chains. (For example for all-to-all connectivity only one chain will be returned).
495    ///
496    /// # Returns
497    ///
498    /// * `Vec<Vec<usize>>` - A list of the longest chains given by vectors of qubits in the chain.
499    ///
500    fn longest_closed_chains(&self) -> Vec<Vec<usize>> {
501        match self {
502            IBMDevice::IBMLagosDevice(x) => x.longest_closed_chains(),
503            IBMDevice::IBMNairobiDevice(x) => x.longest_closed_chains(),
504            IBMDevice::IBMPerthDevice(x) => x.longest_closed_chains(),
505            IBMDevice::IBMBelemDevice(x) => x.longest_closed_chains(),
506            IBMDevice::IBMJakartaDevice(x) => x.longest_closed_chains(),
507            IBMDevice::IBMLimaDevice(x) => x.longest_closed_chains(),
508            IBMDevice::IBMManilaDevice(x) => x.longest_closed_chains(),
509            IBMDevice::IBMQuitoDevice(x) => x.longest_closed_chains(),
510        }
511    }
512
513    /// Returns the list of pairs of qubits linked with a native two-qubit-gate in the device.
514    ///
515    /// A pair of qubits is considered linked by a native two-qubit-gate if the device
516    /// can implement a two-qubit-gate between the two qubits without decomposing it
517    /// into a sequence of gates that involves a third qubit of the device.
518    /// The two-qubit-gate also has to form a universal set together with the available
519    /// single qubit gates.
520    ///
521    /// The returned vectors is a simple, graph-library independent, representation of
522    /// the undirected connectivity graph of the device.
523    /// It can be used to construct the connectivity graph in a graph library of the users
524    /// choice from a list of edges and can be used for applications like routing in quantum algorithms.
525    ///
526    /// # Returns
527    ///
528    /// * `Vec<(usize, usize)>` - A list of pairs of qubits linked with a native two-qubit-gate in
529    ///   the device.
530    ///
531    fn two_qubit_edges(&self) -> Vec<(usize, usize)> {
532        match self {
533            IBMDevice::IBMLagosDevice(x) => x.two_qubit_edges(),
534            IBMDevice::IBMNairobiDevice(x) => x.two_qubit_edges(),
535            IBMDevice::IBMPerthDevice(x) => x.two_qubit_edges(),
536            IBMDevice::IBMBelemDevice(x) => x.two_qubit_edges(),
537            IBMDevice::IBMJakartaDevice(x) => x.two_qubit_edges(),
538            IBMDevice::IBMLimaDevice(x) => x.two_qubit_edges(),
539            IBMDevice::IBMManilaDevice(x) => x.two_qubit_edges(),
540            IBMDevice::IBMQuitoDevice(x) => x.two_qubit_edges(),
541        }
542    }
543}