Skip to content

Commit b34024b

Browse files
authored
Fixes issues with rs sparse sim for older simulation workflow (#106)
* Add reset to pecos-python sparse-sim * fix using state.bindings for rs sparse sim * Adding older gate symbols * Fixing rs bindings measurement output * linting
1 parent a8264f9 commit b34024b

File tree

2 files changed

+248
-241
lines changed

2 files changed

+248
-241
lines changed

crates/pecos-python/src/sparse_sim.rs

Lines changed: 155 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,9 @@
1010
// or implied. See the License for the specific language governing permissions and limitations under
1111
// the License.
1212

13-
// use pecos_core::VecSet;
14-
// use pecos_qsims::CliffordSimulator;
15-
// use pecos_qsims::SparseStab;
1613
use pecos::prelude::*;
1714
use pyo3::prelude::*;
1815
use pyo3::types::{PyDict, PyTuple};
19-
use std::collections::HashMap;
2016

2117
#[pyclass]
2218
pub struct SparseSim {
@@ -32,195 +28,117 @@ impl SparseSim {
3228
}
3329
}
3430

31+
fn reset(&mut self) {
32+
self.inner.reset();
33+
}
34+
3535
#[allow(clippy::too_many_lines)]
3636
#[pyo3(signature = (symbol, location, params=None))]
37-
fn run_gate(
37+
fn run_1q_gate(
3838
&mut self,
3939
symbol: &str,
40-
location: &Bound<'_, PyTuple>,
40+
location: usize,
4141
params: Option<&Bound<'_, PyDict>>,
42-
) -> PyResult<Option<HashMap<usize, u8>>> {
43-
match (symbol, location.len()) {
44-
("X", 1) => {
45-
self.inner.x(location.get_item(0)?.extract()?);
46-
Ok(None)
47-
}
48-
("Y", 1) => {
49-
self.inner.y(location.get_item(0)?.extract()?);
50-
Ok(None)
51-
}
52-
("Z", 1) => {
53-
self.inner.z(location.get_item(0)?.extract()?);
54-
Ok(None)
55-
}
56-
("H", 1) => {
57-
self.inner.h(location.get_item(0)?.extract()?);
42+
) -> PyResult<Option<u8>> {
43+
match symbol {
44+
"X" => {
45+
self.inner.x(location);
5846
Ok(None)
5947
}
60-
("H2", 1) => {
61-
self.inner.h2(location.get_item(0)?.extract()?);
48+
"Y" => {
49+
self.inner.y(location);
6250
Ok(None)
6351
}
64-
("H3", 1) => {
65-
self.inner.h3(location.get_item(0)?.extract()?);
52+
"Z" => {
53+
self.inner.z(location);
6654
Ok(None)
6755
}
68-
("H4", 1) => {
69-
self.inner.h4(location.get_item(0)?.extract()?);
56+
"H" => {
57+
self.inner.h(location);
7058
Ok(None)
7159
}
72-
("H5", 1) => {
73-
self.inner.h5(location.get_item(0)?.extract()?);
60+
"H2" => {
61+
self.inner.h2(location);
7462
Ok(None)
7563
}
76-
("H6", 1) => {
77-
self.inner.h6(location.get_item(0)?.extract()?);
64+
"H3" => {
65+
self.inner.h3(location);
7866
Ok(None)
7967
}
80-
("F", 1) => {
81-
self.inner.f(location.get_item(0)?.extract()?);
68+
"H4" => {
69+
self.inner.h4(location);
8270
Ok(None)
8371
}
84-
("Fdg", 1) => {
85-
self.inner.fdg(location.get_item(0)?.extract()?);
72+
"H5" => {
73+
self.inner.h5(location);
8674
Ok(None)
8775
}
88-
("F2", 1) => {
89-
self.inner.f2(location.get_item(0)?.extract()?);
76+
"H6" => {
77+
self.inner.h6(location);
9078
Ok(None)
9179
}
92-
("F2dg", 1) => {
93-
self.inner.f2dg(location.get_item(0)?.extract()?);
80+
"F" => {
81+
self.inner.f(location);
9482
Ok(None)
9583
}
96-
("F3", 1) => {
97-
self.inner.f3(location.get_item(0)?.extract()?);
84+
"Fdg" => {
85+
self.inner.fdg(location);
9886
Ok(None)
9987
}
100-
("F3dg", 1) => {
101-
self.inner.f3dg(location.get_item(0)?.extract()?);
88+
"F2" => {
89+
self.inner.f2(location);
10290
Ok(None)
10391
}
104-
("F4", 1) => {
105-
self.inner.f4(location.get_item(0)?.extract()?);
92+
"F2dg" => {
93+
self.inner.f2dg(location);
10694
Ok(None)
10795
}
108-
("F4dg", 1) => {
109-
self.inner.f4dg(location.get_item(0)?.extract()?);
96+
"F3" => {
97+
self.inner.f3(location);
11098
Ok(None)
11199
}
112-
("SX", 1) => {
113-
self.inner.sx(location.get_item(0)?.extract()?);
100+
"F3dg" => {
101+
self.inner.f3dg(location);
114102
Ok(None)
115103
}
116-
("SXdg", 1) => {
117-
self.inner.sxdg(location.get_item(0)?.extract()?);
104+
"F4" => {
105+
self.inner.f4(location);
118106
Ok(None)
119107
}
120-
("SY", 1) => {
121-
self.inner.sy(location.get_item(0)?.extract()?);
108+
"F4dg" => {
109+
self.inner.f4dg(location);
122110
Ok(None)
123111
}
124-
("SYdg", 1) => {
125-
self.inner.sydg(location.get_item(0)?.extract()?);
112+
"SX" => {
113+
self.inner.sx(location);
126114
Ok(None)
127115
}
128-
("SZ", 1) => {
129-
self.inner.sz(location.get_item(0)?.extract()?);
116+
"SXdg" => {
117+
self.inner.sxdg(location);
130118
Ok(None)
131119
}
132-
("SZdg", 1) => {
133-
self.inner.szdg(location.get_item(0)?.extract()?);
120+
"SY" => {
121+
self.inner.sy(location);
134122
Ok(None)
135123
}
136-
("CX", 2) => {
137-
self.inner.cx(
138-
location.get_item(0)?.extract()?,
139-
location.get_item(1)?.extract()?,
140-
);
124+
"SYdg" => {
125+
self.inner.sydg(location);
141126
Ok(None)
142127
}
143-
("CY", 2) => {
144-
self.inner.cy(
145-
location.get_item(0)?.extract()?,
146-
location.get_item(1)?.extract()?,
147-
);
128+
"SZ" => {
129+
self.inner.sz(location);
148130
Ok(None)
149131
}
150-
("CZ", 2) => {
151-
self.inner.cz(
152-
location.get_item(0)?.extract()?,
153-
location.get_item(1)?.extract()?,
154-
);
132+
"SZdg" => {
133+
self.inner.szdg(location);
155134
Ok(None)
156135
}
157-
("SXX", 2) => {
158-
self.inner.sxx(
159-
location.get_item(0)?.extract()?,
160-
location.get_item(1)?.extract()?,
161-
);
162-
Ok(None)
163-
}
164-
("SXXdg", 2) => {
165-
self.inner.sxxdg(
166-
location.get_item(0)?.extract()?,
167-
location.get_item(1)?.extract()?,
168-
);
169-
Ok(None)
170-
}
171-
("SYY", 2) => {
172-
self.inner.syy(
173-
location.get_item(0)?.extract()?,
174-
location.get_item(1)?.extract()?,
175-
);
176-
Ok(None)
177-
}
178-
("SYYdg", 2) => {
179-
self.inner.syydg(
180-
location.get_item(0)?.extract()?,
181-
location.get_item(1)?.extract()?,
182-
);
183-
Ok(None)
184-
}
185-
("SZZ", 2) => {
186-
self.inner.szz(
187-
location.get_item(0)?.extract()?,
188-
location.get_item(1)?.extract()?,
189-
);
190-
Ok(None)
191-
}
192-
("SZZdg", 2) => {
193-
self.inner.szzdg(
194-
location.get_item(0)?.extract()?,
195-
location.get_item(1)?.extract()?,
196-
);
197-
Ok(None)
198-
}
199-
("SWAP", 2) => {
200-
self.inner.swap(
201-
location.get_item(0)?.extract()?,
202-
location.get_item(1)?.extract()?,
203-
);
204-
Ok(None)
205-
}
206-
207-
("G2", 2) => {
208-
self.inner.g2(
209-
location.get_item(0)?.extract()?,
210-
location.get_item(1)?.extract()?,
211-
);
212-
Ok(None)
213-
}
214-
(
215-
"MZ" | "MX" | "MY" | "MZForced" | "PZ" | "PX" | "PY" | "PZForced" | "PnZ" | "PnX"
216-
| "PnY",
217-
1,
218-
) => {
219-
let qubit: usize = location.get_item(0)?.extract()?;
136+
"MZ" | "MX" | "MY" | "MZForced" | "PZ" | "PX" | "PY" | "PZForced" | "PnZ" | "PnX"
137+
| "PnY" => {
220138
let (result, _) = match symbol {
221-
"MZ" => self.inner.mz(qubit),
222-
"MX" => self.inner.mx(qubit),
223-
"MY" => self.inner.my(qubit),
139+
"MZ" => self.inner.mz(location),
140+
"MX" => self.inner.mx(location),
141+
"MY" => self.inner.my(location),
224142
"MZForced" => {
225143
let forced_value = params
226144
.ok_or_else(|| {
@@ -236,11 +154,11 @@ impl SparseSim {
236154
})?
237155
.call_method0("__bool__")?
238156
.extract::<bool>()?;
239-
self.inner.mz_forced(qubit, forced_value)
157+
self.inner.mz_forced(location, forced_value)
240158
}
241-
"PZ" => self.inner.pz(qubit),
242-
"PX" => self.inner.px(qubit),
243-
"PY" => self.inner.py(qubit),
159+
"PZ" => self.inner.pz(location),
160+
"PX" => self.inner.px(location),
161+
"PY" => self.inner.py(location),
244162
"PZForced" => {
245163
let forced_value = params
246164
.ok_or_else(|| {
@@ -256,21 +174,103 @@ impl SparseSim {
256174
})?
257175
.call_method0("__bool__")?
258176
.extract::<bool>()?;
259-
self.inner.pz_forced(qubit, forced_value)
177+
self.inner.pz_forced(location, forced_value)
260178
}
261-
"PnZ" => self.inner.pnz(qubit),
262-
"PnX" => self.inner.pnx(qubit),
263-
"PnY" => self.inner.pny(qubit),
179+
"PnZ" => self.inner.pnz(location),
180+
"PnX" => self.inner.pnx(location),
181+
"PnY" => self.inner.pny(location),
264182
_ => unreachable!(),
265183
};
266-
let mut map = HashMap::new();
267-
if result {
268-
map.insert(qubit, 1);
269-
}
270-
Ok(Some(map))
184+
Ok(Some(u8::from(result)))
185+
}
186+
_ => Err(PyErr::new::<pyo3::exceptions::PyValueError, _>(
187+
"Unsupported single-qubit gate",
188+
)),
189+
}
190+
}
191+
192+
#[pyo3(signature = (symbol, location, _params))]
193+
fn run_2q_gate(
194+
&mut self,
195+
symbol: &str,
196+
location: &Bound<'_, PyTuple>,
197+
_params: Option<&Bound<'_, PyDict>>,
198+
) -> PyResult<Option<u8>> {
199+
if location.len() != 2 {
200+
return Err(PyErr::new::<pyo3::exceptions::PyValueError, _>(
201+
"Two-qubit gate requires exactly 2 qubit locations",
202+
));
203+
}
204+
205+
let q1: usize = location.get_item(0)?.extract()?;
206+
let q2: usize = location.get_item(1)?.extract()?;
207+
208+
match symbol {
209+
"CX" => {
210+
self.inner.cx(q1, q2);
211+
Ok(None)
212+
}
213+
"CY" => {
214+
self.inner.cy(q1, q2);
215+
Ok(None)
216+
}
217+
"CZ" => {
218+
self.inner.cz(q1, q2);
219+
Ok(None)
220+
}
221+
"SXX" => {
222+
self.inner.sxx(q1, q2);
223+
Ok(None)
224+
}
225+
"SXXdg" => {
226+
self.inner.sxxdg(q1, q2);
227+
Ok(None)
228+
}
229+
"SYY" => {
230+
self.inner.syy(q1, q2);
231+
Ok(None)
232+
}
233+
"SYYdg" => {
234+
self.inner.syydg(q1, q2);
235+
Ok(None)
236+
}
237+
"SZZ" => {
238+
self.inner.szz(q1, q2);
239+
Ok(None)
240+
}
241+
"SZZdg" => {
242+
self.inner.szzdg(q1, q2);
243+
Ok(None)
244+
}
245+
"SWAP" => {
246+
self.inner.swap(q1, q2);
247+
Ok(None)
248+
}
249+
"G2" => {
250+
self.inner.g2(q1, q2);
251+
Ok(None)
252+
}
253+
_ => Err(PyErr::new::<pyo3::exceptions::PyValueError, _>(
254+
"Unsupported two-qubit gate",
255+
)),
256+
}
257+
}
258+
259+
#[pyo3(signature = (symbol, location, params=None))]
260+
fn run_gate(
261+
&mut self,
262+
symbol: &str,
263+
location: &Bound<'_, PyTuple>,
264+
params: Option<&Bound<'_, PyDict>>,
265+
) -> PyResult<Option<u8>> {
266+
match location.len() {
267+
1 => {
268+
let qubit: usize = location.get_item(0)?.extract()?;
269+
self.run_1q_gate(symbol, qubit, params)
271270
}
271+
2 => self.run_2q_gate(symbol, location, params),
272272
_ => Err(PyErr::new::<pyo3::exceptions::PyValueError, _>(
273-
"Unsupported gate or incorrect number of qubits",
273+
"Gate location must be specified for either 1 or 2 qubits",
274274
)),
275275
}
276276
}

0 commit comments

Comments
 (0)