use crate::dem_decoder::{DecodeError, Prediction};
use super::state::{Scratch, BOUNDARY, NONE, NO_TIME};
use super::Solver;
fn flip(s: &mut Scratch, id: u32) {
let f = &mut s.flipped[id as usize];
*f = !*f;
if *f {
s.edge_set.push(id);
}
}
fn clear_search(s: &mut Scratch) {
for &v in &s.seen {
s.dist[v as usize] = NO_TIME;
}
s.seen.clear();
s.heap.clear();
}
impl<'a> Solver<'a> {
pub(crate) fn pass_one(&mut self, defects: &[u32]) -> Result<Prediction, DecodeError> {
self.reset();
self.run(defects, false)?;
let prediction = self.extract();
self.trace_pairs()?;
Ok(prediction)
}
pub(crate) fn trace_pairs(&mut self) -> Result<(), DecodeError> {
self.s.ensure_paths(self.g);
self.s.edge_set.clear();
for i in 0..self.s.pairs.len() {
let (a, b) = self.s.pairs[i];
if let Err(e) = self.trace(a, b) {
let s = &mut *self.s;
for &id in &s.edge_set {
s.flipped[id as usize] = false;
}
s.edge_set.clear();
return Err(e);
}
}
let s = &mut *self.s;
let flipped = &mut s.flipped;
s.edge_set.retain(|&e| std::mem::replace(&mut flipped[e as usize], false));
Ok(())
}
fn trace(&mut self, a: u32, b: u32) -> Result<(), DecodeError> {
let g = self.g;
let s = &mut *self.s;
s.dist[a as usize] = 0;
s.seen.push(a);
s.heap.push(0, a);
let mut exit = (NO_TIME, NONE, NONE);
while let Some((d, u)) = s.heap.pop() {
if d > s.dist[u as usize] {
continue;
}
if u == b || (b == BOUNDARY && exit.0 <= d) {
break;
}
for e in g.edges(u) {
let v = g.to[e];
let nd = d + s.weight(e);
if v == BOUNDARY {
if nd < exit.0 {
exit = (nd, u, g.edge_of[e]);
}
continue;
}
if nd < s.dist[v as usize] {
if s.dist[v as usize] == NO_TIME {
s.seen.push(v);
}
s.dist[v as usize] = nd;
s.pred[v as usize] = (u, g.edge_of[e]);
s.heap.push(nd, v);
}
}
}
let mut v = if b == BOUNDARY {
if exit.1 == NONE {
clear_search(s);
return Err(DecodeError::MatcherDeclined);
}
flip(s, exit.2);
exit.1
} else {
if s.dist[b as usize] == NO_TIME {
clear_search(s);
return Err(DecodeError::MatcherDeclined);
}
b
};
while v != a {
let (u, id) = s.pred[v as usize];
flip(s, id);
v = u;
}
clear_search(s);
Ok(())
}
}