From c52df62167ff8cd3c7fc520ae2f52bf9b5403f42 Mon Sep 17 00:00:00 2001 From: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com> Date: Mon, 7 Oct 2024 13:30:23 -0400 Subject: [PATCH 1/4] Initial: Add missing docstrings for `EquivalenceLibrary` --- crates/accelerate/src/equivalence.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/crates/accelerate/src/equivalence.rs b/crates/accelerate/src/equivalence.rs index 55e1b0336ae4..0253f8a31da8 100644 --- a/crates/accelerate/src/equivalence.rs +++ b/crates/accelerate/src/equivalence.rs @@ -340,6 +340,8 @@ impl ToPyObject for CircuitFromPython { type GraphType = StableDiGraph>; type KTIType = IndexMap; +/// A library providing a one-way mapping of Gates to their equivalent +/// implementations as QuantumCircuits. #[pyclass( subclass, name = "BaseEquivalenceLibrary", @@ -469,6 +471,16 @@ impl EquivalenceLibrary { } // TODO: Remove once BasisTranslator is in Rust. + /// Return graph representing the equivalence library data. + /// + /// This property should be treated as read-only as it provides + /// a reference to the internal state of the :class:`~.EquivalenceLibrary` object. + /// If the graph returned by this property is mutated it could corrupt the + /// the contents of the object. If you need to modify the output ``PyDiGraph`` + /// be sure to make a copy prior to any modification. + /// + /// Returns: + /// PyDiGraph: A graph object with equivalence data in each node. #[getter] fn get_graph(&mut self, py: Python) -> PyResult { if let Some(graph) = &self._graph { @@ -492,6 +504,10 @@ impl EquivalenceLibrary { } } + /// Return list of keys to key to node index map. + /// + /// Returns: + /// List: Keys to the key to node index map. #[pyo3(name = "keys")] fn py_keys(slf: PyRef) -> PyResult { let py_dict = PyDict::new_bound(slf.py()); @@ -501,6 +517,13 @@ impl EquivalenceLibrary { Ok(py_dict.as_any().call_method0("keys")?.into()) } + /// Return node index for a given key. + /// + /// Args: + /// key (Key): Key to an equivalence. + /// + /// Returns: + /// Int: Index to the node in the graph for the given key. #[pyo3(name = "node_index")] fn py_node_index(&self, key: &Key) -> usize { self.node_index(key).index() @@ -664,6 +687,7 @@ impl EquivalenceLibrary { self.key_to_node_index.contains_key(&key) } + /// Returns an iterator with all the Keys in the `EquivalenceLibrary`. pub fn keys(&self) -> impl Iterator { self.key_to_node_index.keys() } @@ -783,6 +807,8 @@ impl Display for EquivalenceError { } } +// Conversion helpers + fn to_pygraph(py: Python, pet_graph: &StableDiGraph) -> PyResult where N: IntoPy + Clone, From 262f813f0d74ce20e1dd0305b5bb39ae9f89f526 Mon Sep 17 00:00:00 2001 From: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com> Date: Mon, 7 Oct 2024 16:13:29 -0400 Subject: [PATCH 2/4] Fix: Use code-refs to refer to structs in rust. --- crates/accelerate/src/equivalence.rs | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/crates/accelerate/src/equivalence.rs b/crates/accelerate/src/equivalence.rs index 0253f8a31da8..3feb43dabbf5 100644 --- a/crates/accelerate/src/equivalence.rs +++ b/crates/accelerate/src/equivalence.rs @@ -277,7 +277,7 @@ impl Display for EdgeData { } /// Enum that helps extract the Operation and Parameters on a Gate. -/// It is highly derivative of `PackedOperation` while also tracking the specific +/// It is highly derivative of [PackedOperation] while also tracking the specific /// parameter objects. #[derive(Debug, Clone)] pub struct GateOper { @@ -299,7 +299,7 @@ impl<'py> FromPyObject<'py> for GateOper { /// It also ensures seamless conversion back to `QuantumCircuit` once sent /// back to Python. /// -/// TODO: Remove this implementation once the `EquivalenceLibrary` is no longer +/// TODO: Remove this implementation once the [EquivalenceLibrary] is no longer /// called from Python, or once the API is able to seamlessly accept instances /// of [CircuitData]. #[derive(Debug, Clone)] @@ -637,7 +637,7 @@ impl EquivalenceLibrary { Ok(()) } - /// Set the equivalence record for a Gate. Future queries for the Gate + /// Set the equivalence record for a [PackedOperation]. Future queries for the Gate /// will return only the circuits provided. pub fn set_entry( &mut self, @@ -672,22 +672,20 @@ impl EquivalenceLibrary { Ok(()) } - /// Rust native equivalent to `EquivalenceLibrary.has_entry()` - /// /// Check if a library contains any decompositions for gate. /// /// # Arguments: - /// * `operation` OperationType: A Gate instance. + /// * `operation` [PackedOperation]: A gate instance. /// /// # Returns: - /// `bool`: `true` if gate has a known decomposition in the library. + /// [bool]: `true` if gate has a known decomposition in the library. /// `false` otherwise. pub fn has_entry(&self, operation: &PackedOperation) -> bool { let key = Key::from_operation(operation); self.key_to_node_index.contains_key(&key) } - /// Returns an iterator with all the Keys in the `EquivalenceLibrary`. + /// Returns an iterator with all the [Key] instances in the [EquivalenceLibrary]. pub fn keys(&self) -> impl Iterator { self.key_to_node_index.keys() } @@ -706,13 +704,13 @@ impl EquivalenceLibrary { } } - /// Retrieve the `NodeIndex` that represents a `Key` + /// Retrieve the [NodeIndex] that represents a [Key]. /// - /// # Arguments: - /// * `key`: The `Key` to look for. + /// ## Arguments: + /// * `key`: The [Key] to look for. /// - /// # Returns: - /// `NodeIndex` + /// ## Returns: + /// [NodeIndex] pub fn node_index(&self, key: &Key) -> NodeIndex { self.key_to_node_index[key] } From 01e40abd0cd34e5a0118b92dc0abd30a1172ebfb Mon Sep 17 00:00:00 2001 From: Raynel Sanchez Date: Tue, 5 Nov 2024 11:24:52 -0500 Subject: [PATCH 3/4] Remove `Arguments` and `Returns` sections. - Add docs links based on @kevinhartman's comments. - Add sphinx friendly labels in docstrings. --- crates/accelerate/src/equivalence.rs | 33 ++++++++++------------------ 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/crates/accelerate/src/equivalence.rs b/crates/accelerate/src/equivalence.rs index 3feb43dabbf5..ce80c1a7b750 100644 --- a/crates/accelerate/src/equivalence.rs +++ b/crates/accelerate/src/equivalence.rs @@ -295,13 +295,15 @@ impl<'py> FromPyObject<'py> for GateOper { } } -/// Used to extract an instance of [CircuitData] from a `QuantumCircuit`. -/// It also ensures seamless conversion back to `QuantumCircuit` once sent +/// Used to extract an instance of [CircuitData] from a [`QuantumCircuit`]. +/// It also ensures seamless conversion back to [`QuantumCircuit`] once sent /// back to Python. /// /// TODO: Remove this implementation once the [EquivalenceLibrary] is no longer /// called from Python, or once the API is able to seamlessly accept instances /// of [CircuitData]. +/// +/// [`QuantumCircuit`]: https://docs.quantum.ibm.com/api/qiskit/qiskit.circuit.QuantumCircuit #[derive(Debug, Clone)] pub struct CircuitFromPython(pub CircuitData); @@ -341,7 +343,7 @@ type GraphType = StableDiGraph>; type KTIType = IndexMap; /// A library providing a one-way mapping of Gates to their equivalent -/// implementations as QuantumCircuits. +/// implementations as :class:`.QuantumCircuit` instances. #[pyclass( subclass, name = "BaseEquivalenceLibrary", @@ -426,7 +428,7 @@ impl EquivalenceLibrary { /// /// Args: /// gate (Gate): A Gate instance. - /// entry (List['QuantumCircuit']) : A list of QuantumCircuits, each + /// entry (List['QuantumCircuit']) : A list of :class:`.QuantumCircuit` instances, each /// equivalently implementing the given Gate. #[pyo3(name = "set_entry")] fn py_set_entry( @@ -438,8 +440,8 @@ impl EquivalenceLibrary { self.set_entry(py, &gate.operation, &gate.params, entry) } - /// Gets the set of QuantumCircuits circuits from the library which - /// equivalently implement the given Gate. + /// Gets the set of :class:`.QuantumCircuit` instances circuits from the + /// library which equivalently implement the given Gate. /// /// Parameterized circuits will have their parameters replaced with the /// corresponding entries from Gate.params. @@ -448,8 +450,8 @@ impl EquivalenceLibrary { /// gate (Gate) - Gate: A Gate instance. /// /// Returns: - /// List[QuantumCircuit]: A list of equivalent QuantumCircuits. If empty, - /// library contains no known decompositions of Gate. + /// List[QuantumCircuit]: A list of equivalent :class:`.QuantumCircuit` instances. + /// If empty, library contains no known decompositions of Gate. /// /// Returned circuits will be ordered according to their insertion in /// the library, from earliest to latest, from top to base. The @@ -672,14 +674,7 @@ impl EquivalenceLibrary { Ok(()) } - /// Check if a library contains any decompositions for gate. - /// - /// # Arguments: - /// * `operation` [PackedOperation]: A gate instance. - /// - /// # Returns: - /// [bool]: `true` if gate has a known decomposition in the library. - /// `false` otherwise. + /// Check if the [EquivalenceLibrary] instance contains any decompositions for gate. pub fn has_entry(&self, operation: &PackedOperation) -> bool { let key = Key::from_operation(operation); self.key_to_node_index.contains_key(&key) @@ -705,12 +700,6 @@ impl EquivalenceLibrary { } /// Retrieve the [NodeIndex] that represents a [Key]. - /// - /// ## Arguments: - /// * `key`: The [Key] to look for. - /// - /// ## Returns: - /// [NodeIndex] pub fn node_index(&self, key: &Key) -> NodeIndex { self.key_to_node_index[key] } From c608c4a5f23acf6d734a037f5d6ed0fe5195e52a Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Wed, 6 Nov 2024 12:49:48 -0500 Subject: [PATCH 4/4] Apply suggestions from code review --- crates/accelerate/src/equivalence.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/accelerate/src/equivalence.rs b/crates/accelerate/src/equivalence.rs index ce80c1a7b750..8787abcb8399 100644 --- a/crates/accelerate/src/equivalence.rs +++ b/crates/accelerate/src/equivalence.rs @@ -342,7 +342,7 @@ impl ToPyObject for CircuitFromPython { type GraphType = StableDiGraph>; type KTIType = IndexMap; -/// A library providing a one-way mapping of Gates to their equivalent +/// A library providing a one-way mapping of gates to their equivalent /// implementations as :class:`.QuantumCircuit` instances. #[pyclass( subclass, @@ -441,7 +441,7 @@ impl EquivalenceLibrary { } /// Gets the set of :class:`.QuantumCircuit` instances circuits from the - /// library which equivalently implement the given Gate. + /// library which equivalently implement the given :class:`.Gate`. /// /// Parameterized circuits will have their parameters replaced with the /// corresponding entries from Gate.params.