in src/dachshund/beam.rs [149:234]
fn one_step_search(
&mut self,
num_to_search: usize,
beam_size: usize,
) -> CLQResult<(Candidate<'a, TGraph>, bool)> {
let mut scored_expansion_candidates: HashSet<Candidate<TGraph>> = HashSet::new();
let mut new_candidates: Vec<Candidate<TGraph>> = Vec::new();
let mut can_continue: bool = false;
// A map from a checksum to a reference to a candidate from the previous generation.
// Used as a hint when materializing the neighborhood for the next generation of candidates.
let mut previous_candidates = HashMap::new();
for candidate in &self.candidates {
if self.verbose {
eprintln!(
"Considering the following candidate (score = {}, hash={}):\n{}",
match candidate.get_score() {
Ok(n) => n.to_string(),
Err(_) => "No score".to_string(),
},
candidate,
candidate.to_printable_row(self.non_core_types)?,
);
}
if !self
.visited_candidates
.contains(&candidate.checksum.unwrap())
{
can_continue = true;
let v: Vec<Candidate<TGraph>> = candidate.one_step_search(
num_to_search,
&mut self.visited_candidates,
&self.scorer,
)?;
if self.verbose {
eprintln!("Have {} visited candidates:", self.visited_candidates.len());
eprintln!("Found the following expansion candidates:");
}
for ell in v {
if self.verbose {
eprintln!(
"(score = {}): {}",
ell.get_score()?,
ell.to_printable_row(self.non_core_types)?,
);
}
scored_expansion_candidates.insert(ell);
}
}
previous_candidates.insert(candidate.checksum.unwrap(), candidate);
scored_expansion_candidates.insert(candidate.replicate(true));
}
// sort by score, with node_id as tie breaker for deterministic behaviour
let mut v: Vec<Candidate<TGraph>> = scored_expansion_candidates.into_iter().collect();
let mut bad_sort = false;
v.sort_by(|a, b| {
if let (Ok(a_score), Ok(b_score)) = (a.get_score(), b.get_score()) {
let key_a = (a_score, a.checksum);
let key_b = (b_score, b.checksum);
if let Some(comparison) = key_a.partial_cmp(&key_b) {
return comparison.reverse();
}
}
bad_sort = true;
std::cmp::Ordering::Equal
});
if bad_sort {
return Err(CLQError::new(
"Failed to sort at least one unscored candidate.",
));
}
if self.verbose {
eprintln!("Beam now contains:");
}
for mut ell in v {
if new_candidates.len() < beam_size {
ell.set_neigbhorhood_with_hint(&previous_candidates);
new_candidates.push(ell);
}
}
self.candidates = new_candidates;
Ok((self.candidates[0].replicate(true), can_continue))
}