Skip to content
Merged
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
21 changes: 11 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion synir/src/ir/clifford_tableau.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ mod helper;
mod naive;
mod permrowcol;

#[derive(Default)]
#[derive(Default, Clone)]
pub enum CliffordTableauSynthStrategy {
#[default]
Naive,
Expand Down
2 changes: 1 addition & 1 deletion synir/src/ir/pauli_polynomial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pub mod naive;

pub use naive::NaivePauliPolynomialSynthesizer;

#[derive(Default)]
#[derive(Default, Clone)]
pub enum PauliPolynomialSynthStrategy {
#[default]
Naive,
Expand Down
1 change: 1 addition & 0 deletions synpy/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ crate-type = ["cdylib"]
[dependencies]
bitvec = "1.0.1"
pyo3 = "0.27.1"
pyo3-ffi = "0.27.2"
synir = { path = "../synir" }
31 changes: 30 additions & 1 deletion synpy/integration_tests/test_qiskit.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,45 @@
from qiskit import QuantumCircuit

from synpy.qiskit.plugin import SynPyCliffordPlugin
from synpy.synpy_rust import QiskitSynIR


def test_qiskit_synir() -> None:
qc = QuantumCircuit(2)
synir = QiskitSynIR(qc)

synir.s(0)
synir.v(0)
synir.s_dgr(0)
synir.v_dgr(0)
synir.x(0)
synir.y(0)
synir.z(0)
synir.h(0)
synir.cx(0, 1)
synir.cz(0, 1)
synir.rx(0, 1.23)
synir.ry(0, 1.23)
synir.rz(0, 1.23)

reference_circuit = ["s", "sx", "sdg", "sxdg", "x", "y", "z", "h", "cx", "cz", "rx", "ry", "rz"]
reference_angles = [None, None, None, None, None, None, None, None, None, None, 1.23, 1.23, 1.23]

for inst in qc.data:
assert inst.name == reference_circuit.pop(0)
reference_param = reference_angles.pop(0)
if inst.params:
assert inst.params[0] == reference_param


def test_qiskit_bell() -> None:
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)

cliff = Clifford(qc)

plugin = SynPyCliffordPlugin()
circ = plugin.run(cliff, None, None, [])
# circ.draw()

assert circ == qc
28 changes: 28 additions & 0 deletions synpy/python/synpy/synpy_rust.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,39 @@ class PyCliffordTableau(object):
def size(self, *args: Any, **kwargs: Any) -> Any: ...
def compose(self, *args: Any, **kwargs: Any) -> Any: ...

class PyPauliExponential(object):
def add_cx(self, *args: Any, **kwargs: Any) -> Any: ...
def add_h(self, *args: Any, **kwargs: Any) -> Any: ...
def add_rz(self, *args: Any, **kwargs: Any) -> Any: ...
def synthesize_to_qiskit(self, *args: Any, **kwargs: Any) -> Any: ...
def __init__(self, *args: Any, **kwargs: Any) -> None: ...
def __new__(*args: Any, **kwargs: Any) -> Any: ...

class QiskitSynIR(object):
def s(self, *args: Any, **kwargs: Any) -> Any: ...
def v(self, *args: Any, **kwargs: Any) -> Any: ...
def s_dgr(self, *args: Any, **kwargs: Any) -> Any: ...
def v_dgr(self, *args: Any, **kwargs: Any) -> Any: ...
def x(self, *args: Any, **kwargs: Any) -> Any: ...
def y(self, *args: Any, **kwargs: Any) -> Any: ...
def z(self, *args: Any, **kwargs: Any) -> Any: ...
def h(self, *args: Any, **kwargs: Any) -> Any: ...
def cx(self, *args: Any, **kwargs: Any) -> Any: ...
def cz(self, *args: Any, **kwargs: Any) -> Any: ...
def rx(self, *args: Any, **kwargs: Any) -> Any: ...
def ry(self, *args: Any, **kwargs: Any) -> Any: ...
def rz(self, *args: Any, **kwargs: Any) -> Any: ...
def get_circuit(self, *args: Any, **kwargs: Any) -> Any: ...
def __init__(self, *args: Any, **kwargs: Any) -> None: ...
def __new__(*args: Any, **kwargs: Any) -> Any: ...

__all__ = [
"PyCliffordTableau",
"PyPauliString",
"PyCommand",
"synthesize_pauli_exponential",
"PyPauliExponential",
"QiskitSynIR",
]

__loader__: Any = ...
Expand Down
6 changes: 5 additions & 1 deletion synpy/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
mod synthesis;
mod tableau;
mod validation;
mod wrapper;

use crate::synthesis::synthesize_pauli_exponential;
use crate::synthesis::{PyCommand, PyPauliString};
use crate::tableau::PyCliffordTableau;
use crate::wrapper::qiskit::QiskitSynIR;
use crate::wrapper::PyPauliExponential;
use pyo3::prelude::{PyModule, PyModuleMethods};
use pyo3::{pymodule, wrap_pyfunction, Bound, PyResult};

Expand All @@ -15,6 +18,7 @@ fn synpy_rust(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<PyCommand>()?;
let _ = m.add_function(wrap_pyfunction!(synthesize_pauli_exponential, m)?);
m.add_class::<PyCliffordTableau>()?;

m.add_class::<PyPauliExponential>()?;
m.add_class::<QiskitSynIR>()?;
Ok(())
}
70 changes: 70 additions & 0 deletions synpy/src/wrapper.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
pub(crate) mod qiskit;

extern crate pyo3;
extern crate pyo3_ffi;

use std::collections::VecDeque;

use pyo3::prelude::*;
use synir::{
data_structures::CliffordTableau,
ir::{
clifford_tableau::CliffordTableauSynthStrategy,
pauli_exponential::{PauliExponential, PauliExponentialSynthesizer},
pauli_polynomial::PauliPolynomialSynthStrategy,
CliffordGates, Gates, Synthesizer,
},
};

use crate::wrapper::qiskit::QiskitSynIR;

#[pyclass]
pub struct PyPauliExponential {
pe: PauliExponential,
pauli_strategy: PauliPolynomialSynthStrategy,
tableau_strategy: CliffordTableauSynthStrategy,
}

#[pymethods]
impl PyPauliExponential {
#[new]
pub fn new(num_qubits: usize) -> Self {
let pe = PauliExponential::new(VecDeque::from(vec![]), CliffordTableau::new(num_qubits));
Self {
pe,
pauli_strategy: PauliPolynomialSynthStrategy::Naive,
tableau_strategy: CliffordTableauSynthStrategy::PermRowCol,
}
}

pub fn synthesize_to_qiskit(&mut self, circuit: &mut QiskitSynIR) {
synthesize(self, circuit);
}

pub fn set_pauli_strategy(&mut self, strategy: String) {
match strategy.as_str() {
"Naive" => self.pauli_strategy = PauliPolynomialSynthStrategy::Naive,
_ => panic!("Unknown Pauli polynomial synthesis strategy: {}", strategy),
}
}

pub fn set_tableau_strategy(&mut self, strategy: String) {
match strategy.as_str() {
"Naive" => self.tableau_strategy = CliffordTableauSynthStrategy::Naive,
"PermRowCol" => self.tableau_strategy = CliffordTableauSynthStrategy::PermRowCol,
_ => panic!("Unknown Clifford tableau synthesis strategy: {}", strategy),
}
}
}

pub fn synthesize<G>(pe: &mut PyPauliExponential, circuit: &mut G)
where
G: CliffordGates + Gates,
{
let mut synth = PauliExponentialSynthesizer::from_strategy(
pe.pauli_strategy.clone(),
pe.tableau_strategy.clone(),
);
let pe = std::mem::take(&mut pe.pe);
synth.synthesize(pe, circuit)
}
Loading
Loading