1#[cfg(feature = "serialize")]
2use serde::{Deserialize, Serialize};
3use std::fmt::Debug;
4use std::iter::FromIterator;
5
6pub trait Op: Clone + Debug {
8 type Vars: FromIterator<usize> + AsRef<[usize]> + AsMut<[usize]> + Debug;
10 type SubState: FromIterator<bool> + AsRef<[bool]> + AsMut<[bool]> + Debug;
12
13 fn diagonal<A, B>(vars: A, bond: usize, state: B, constant: bool) -> Self
15 where
16 A: Into<Self::Vars>,
17 B: Into<Self::SubState>;
18
19 fn offdiagonal<A, B, C>(vars: A, bond: usize, inputs: B, outputs: C, constant: bool) -> Self
21 where
22 A: Into<Self::Vars>,
23 B: Into<Self::SubState>,
24 C: Into<Self::SubState>;
25
26 fn make_vars<V>(vars: V) -> Self::Vars
28 where
29 V: IntoIterator<Item = usize>,
30 {
31 vars.into_iter().collect()
32 }
33
34 fn make_substate<S>(state: S) -> Self::SubState
36 where
37 S: IntoIterator<Item = bool>,
38 {
39 state.into_iter().collect()
40 }
41
42 fn index_of_var(&self, var: usize) -> Option<usize>;
44
45 fn is_diagonal(&self) -> bool {
47 self.get_inputs() == self.get_outputs()
48 }
49
50 fn get_vars(&self) -> &[usize];
52
53 fn get_bond(&self) -> usize;
55
56 fn get_inputs(&self) -> &[bool];
58
59 fn get_outputs(&self) -> &[bool];
61
62 fn clone_and_edit_in_out<F>(&self, f: F) -> Self
64 where
65 F: Fn(&mut [bool], &mut [bool]);
66
67 fn clone_and_edit_in_out_symmetric<F>(&self, f: F) -> Self
70 where
71 F: Fn(&mut [bool]);
72
73 fn edit_in_out<F>(&mut self, f: F)
75 where
76 F: Fn(&mut [bool], &mut [bool]);
77
78 fn edit_in_out_symmetric<F>(&mut self, f: F)
81 where
82 F: Fn(&mut [bool]);
83
84 fn clone_inputs(&self) -> Self::SubState;
86
87 fn clone_outputs(&self) -> Self::SubState;
89
90 fn is_constant(&self) -> bool;
93}
94
95pub trait OpNode<O: Op> {
97 fn get_op(&self) -> O;
99 fn get_op_ref(&self) -> &O;
101 fn get_op_mut(&mut self) -> &mut O;
103}
104
105pub trait OpContainerConstructor {
107 fn new(nvars: usize) -> Self;
109 fn new_with_bonds(nvars: usize, nbonds: usize) -> Self;
111}
112
113pub trait OpContainer {
115 type Op: Op;
117
118 fn get_cutoff(&self) -> usize;
120 fn set_cutoff(&mut self, cutoff: usize);
122 fn get_n(&self) -> usize;
124 fn get_nvars(&self) -> usize;
126 fn get_pth(&self, p: usize) -> Option<&Self::Op>;
128 fn get_count(&self, bond: usize) -> usize;
130
131 fn itime_fold<F, T>(&self, state: &mut [bool], fold_fn: F, init: T) -> T
133 where
134 F: Fn(T, &[bool]) -> T;
135
136 fn verify(&self, state: &[bool]) -> bool {
138 let mut rolling_state = state.to_vec();
139 for p in 0..self.get_cutoff() {
140 let op = self.get_pth(p);
141 if let Some(op) = op {
142 for (v, inp) in op.get_vars().iter().zip(op.get_inputs().iter()) {
143 if rolling_state[*v] != *inp {
144 return false;
145 }
146 }
147 op.get_vars()
148 .iter()
149 .zip(op.get_outputs().iter())
150 .for_each(|(v, out)| {
151 rolling_state[*v] = *out;
152 })
153 }
154 }
155 rolling_state
156 .into_iter()
157 .zip(state.iter().cloned())
158 .all(|(a, b)| a == b)
159 }
160}
161
162#[derive(Clone, Debug, PartialEq, Eq)]
164#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
165pub enum OpType<SubState>
166where
167 SubState: Clone + Debug + FromIterator<bool> + AsRef<[bool]> + AsMut<[bool]>,
168{
169 Diagonal(SubState),
171 Offdiagonal(SubState, SubState),
173}
174
175impl<SubState> OpType<SubState>
176where
177 SubState: Clone + Debug + FromIterator<bool> + AsRef<[bool]> + AsMut<[bool]>,
178{
179 fn edit_states<F>(&mut self, f: F)
180 where
181 F: Fn(&mut [bool], &mut [bool]),
182 {
183 let (inputs, outputs) = match self {
184 OpType::Diagonal(state) => {
185 let mut inputs = state.clone();
186 let mut outputs = state.clone();
187 f(inputs.as_mut(), outputs.as_mut());
188 (inputs, outputs)
189 }
190 OpType::Offdiagonal(inputs, outputs) => {
191 let mut inputs = inputs.clone();
192 let mut outputs = outputs.clone();
193 f(inputs.as_mut(), outputs.as_mut());
194 (inputs, outputs)
195 }
196 };
197
198 *self = if inputs.as_ref() == outputs.as_ref() {
199 Self::Diagonal(inputs)
200 } else {
201 Self::Offdiagonal(inputs, outputs)
202 };
203 }
204
205 fn edit_states_symmetric<F>(&mut self, f: F)
206 where
207 F: Fn(&mut [bool]),
208 {
209 match self {
210 OpType::Diagonal(state) => {
211 f(state.as_mut());
212 }
213 OpType::Offdiagonal(inputs, outputs) => {
214 f(inputs.as_mut());
215 f(outputs.as_mut());
216 }
217 };
218 }
219}
220
221#[derive(Clone, Debug, PartialEq, Eq)]
223#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
224pub struct BasicOp<Vars, SubState>
225where
226 Vars: FromIterator<usize> + AsRef<[usize]> + AsMut<[usize]> + Clone + Debug,
227 SubState: FromIterator<bool> + AsRef<[bool]> + AsMut<[bool]> + Clone + Debug,
228{
229 vars: Vars,
231 bond: usize,
233 in_out: OpType<SubState>,
235 constant: bool,
237}
238
239impl<Vars, SubState> Op for BasicOp<Vars, SubState>
240where
241 Vars: FromIterator<usize> + AsRef<[usize]> + AsMut<[usize]> + Clone + Debug,
242 SubState: FromIterator<bool> + AsRef<[bool]> + AsMut<[bool]> + Clone + Debug,
243{
244 type Vars = Vars;
245 type SubState = SubState;
246
247 fn diagonal<A, B>(vars: A, bond: usize, state: B, constant: bool) -> Self
248 where
249 A: Into<Self::Vars>,
250 B: Into<Self::SubState>,
251 {
252 Self {
253 vars: vars.into(),
254 bond,
255 in_out: OpType::Diagonal(state.into()),
256 constant,
257 }
258 }
259
260 fn offdiagonal<A, B, C>(vars: A, bond: usize, inputs: B, outputs: C, constant: bool) -> Self
261 where
262 A: Into<Self::Vars>,
263 B: Into<Self::SubState>,
264 C: Into<Self::SubState>,
265 {
266 Self {
267 vars: vars.into(),
268 bond,
269 in_out: OpType::Offdiagonal(inputs.into(), outputs.into()),
270 constant,
271 }
272 }
273
274 fn is_diagonal(&self) -> bool {
275 matches!(&self.in_out, OpType::Diagonal(_))
276 }
277
278 fn index_of_var(&self, var: usize) -> Option<usize> {
279 let res = self
280 .vars
281 .as_ref()
282 .iter()
283 .enumerate()
284 .try_for_each(|(indx, v)| if *v == var { Err(indx) } else { Ok(()) });
285 match res {
286 Ok(_) => None,
287 Err(v) => Some(v),
288 }
289 }
290
291 fn get_vars(&self) -> &[usize] {
292 self.vars.as_ref()
293 }
294
295 fn get_bond(&self) -> usize {
296 self.bond
297 }
298
299 fn get_inputs(&self) -> &[bool] {
300 match &self.in_out {
301 OpType::Diagonal(state) => state.as_ref(),
302 OpType::Offdiagonal(state, _) => state.as_ref(),
303 }
304 }
305
306 fn get_outputs(&self) -> &[bool] {
307 match &self.in_out {
308 OpType::Diagonal(state) => state.as_ref(),
309 OpType::Offdiagonal(_, state) => state.as_ref(),
310 }
311 }
312
313 fn clone_and_edit_in_out<F>(&self, f: F) -> Self
314 where
315 F: Fn(&mut [bool], &mut [bool]),
316 {
317 let (mut inputs, mut outputs) = match &self.in_out {
318 OpType::Diagonal(state) => {
319 let inputs = state.clone();
320 let outputs = state.clone();
321 (inputs, outputs)
322 }
323 OpType::Offdiagonal(inputs, outputs) => {
324 let inputs = inputs.clone();
325 let outputs = outputs.clone();
326 (inputs, outputs)
327 }
328 };
329 f(inputs.as_mut(), outputs.as_mut());
330 let all_eq = inputs.as_ref() == outputs.as_ref();
331 let in_out = if all_eq {
332 OpType::Diagonal(inputs)
333 } else {
334 OpType::Offdiagonal(inputs, outputs)
335 };
336 Self {
337 vars: self.vars.clone(),
338 bond: self.bond,
339 in_out,
340 constant: self.constant,
341 }
342 }
343
344 fn clone_and_edit_in_out_symmetric<F>(&self, f: F) -> Self
345 where
346 F: Fn(&mut [bool]),
347 {
348 let in_out = match &self.in_out {
349 OpType::Diagonal(state) => {
350 let mut inputs = state.clone();
351 f(inputs.as_mut());
352 OpType::Diagonal(inputs)
353 }
354 OpType::Offdiagonal(inputs, outputs) => {
355 let mut inputs = inputs.clone();
356 let mut outputs = outputs.clone();
357 f(inputs.as_mut());
358 f(outputs.as_mut());
359 OpType::Offdiagonal(inputs, outputs)
360 }
361 };
362 Self {
363 vars: self.vars.clone(),
364 bond: self.bond,
365 in_out,
366 constant: self.constant,
367 }
368 }
369
370 fn clone_inputs(&self) -> Self::SubState {
371 match &self.in_out {
372 OpType::Diagonal(state) => state.clone(),
373 OpType::Offdiagonal(state, _) => state.clone(),
374 }
375 }
376
377 fn clone_outputs(&self) -> Self::SubState {
378 match &self.in_out {
379 OpType::Diagonal(state) => state.clone(),
380 OpType::Offdiagonal(_, state) => state.clone(),
381 }
382 }
383
384 fn is_constant(&self) -> bool {
385 self.constant
386 }
387
388 fn edit_in_out<F>(&mut self, f: F)
389 where
390 F: Fn(&mut [bool], &mut [bool]),
391 {
392 self.in_out.edit_states(f)
393 }
394
395 fn edit_in_out_symmetric<F>(&mut self, f: F)
396 where
397 F: Fn(&mut [bool]),
398 {
399 self.in_out.edit_states_symmetric(f)
400 }
401}