Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Copy circuits and parameters when adding them to the EquivalenceLibrary in Rust. #13532

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions crates/accelerate/src/equivalence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use rustworkx_core::petgraph::{

use qiskit_circuit::circuit_data::CircuitData;
use qiskit_circuit::circuit_instruction::OperationFromPython;
use qiskit_circuit::imports::{ImportOnceCell, QUANTUM_CIRCUIT};
use qiskit_circuit::imports::{PYDIGRAPH, QUANTUM_CIRCUIT};
use qiskit_circuit::operations::Param;
use qiskit_circuit::operations::{Operation, OperationRef};
use qiskit_circuit::packed_instruction::PackedOperation;
Expand All @@ -46,7 +46,6 @@ mod exceptions {
use pyo3::import_exception_bound;
import_exception_bound! {qiskit.circuit.exceptions, CircuitError}
}
pub static PYDIGRAPH: ImportOnceCell = ImportOnceCell::new("rustworkx", "PyDiGraph");

// Custom Structs

Expand Down Expand Up @@ -605,7 +604,7 @@ impl EquivalenceLibrary {
raise_if_param_mismatch(py, params, equivalent_circuit.0.unsorted_parameters(py)?)?;
let key: Key = Key::from_operation(gate);
let equiv = Equivalence {
circuit: equivalent_circuit.clone(),
circuit: CircuitFromPython(equivalent_circuit.0.copy(py, true, false)?),
params: params.into(),
};

Expand Down
1 change: 1 addition & 0 deletions crates/circuit/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ pub static PARAMETER_EXPRESSION: ImportOnceCell =
ImportOnceCell::new("qiskit.circuit.parameterexpression", "ParameterExpression");
pub static PARAMETER_VECTOR: ImportOnceCell =
ImportOnceCell::new("qiskit.circuit.parametervector", "ParameterVector");
pub static PYDIGRAPH: ImportOnceCell = ImportOnceCell::new("rustworkx", "PyDiGraph");
pub static QUANTUM_CIRCUIT: ImportOnceCell =
ImportOnceCell::new("qiskit.circuit.quantumcircuit", "QuantumCircuit");
pub static SINGLETON_GATE: ImportOnceCell =
Expand Down
6 changes: 6 additions & 0 deletions releasenotes/notes/fix-equivalence-copy-205adf94f0380219.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
fixes:
- |
Add missing calls to `copy` to the :class:`.Parameter` and :class:`.CircuitData` instances
being added to an `Equivalence` when calling :meth:`.EquivalenceLibrary.add_equivalence` in
:class:`.EquivalenceLibrary`.
25 changes: 25 additions & 0 deletions test/python/transpiler/test_basis_translator.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@
"""Test the BasisTranslator pass"""

import os
from pickle import loads, dumps

from numpy import pi
import scipy

from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
from qiskit import transpile
from qiskit.circuit import Gate, Parameter, EquivalenceLibrary, Qubit, Clbit, Measure
from qiskit.circuit.equivalence_library import StandardEquivalenceLibrary as std_eq_lib
from qiskit.circuit.classical import expr, types
from qiskit.circuit.library import (
HGate,
Expand Down Expand Up @@ -481,6 +483,29 @@ def test_different_bits(self):
out = BasisTranslator(std_eqlib, basis).run(circuit_to_dag(base))
self.assertEqual(set(out.count_ops(recurse=True)), basis)

def test_equivalence_library_serialization(self):
"""Test correct serialization of the EquivalenceLibrart that the BasisTranslator
depends on."""
pass_ = BasisTranslator(
equivalence_library=std_eq_lib, target_basis=["cx", "id", "rz", "sx", "x"]
)

# Add a parameter a which we will share between circuits
param = Parameter("a")
gate = RXGate(param)

qc = QuantumCircuit(1)
qc.append(gate, [0])

# Before serialization, should not fail.
first = pass_.run(circuit_to_dag(qc))

# After serialization, should not fail.
pass_ = BasisTranslator(
equivalence_library=loads(dumps(std_eq_lib)), target_basis=["cx", "id", "rz", "sx", "x"]
)
self.assertEqual(first, pass_.run(circuit_to_dag(qc)))


class TestUnrollerCompatability(QiskitTestCase):
"""Tests backward compatability with the Unroller pass.
Expand Down
Loading