#![deny(missing_docs)]
extern crate fnv;
use std::fmt::Debug;
pub trait Puzzle: Clone {
type Pos: Copy + Debug;
type Val: Copy + Debug + PartialEq;
fn solve_simple<F: FnMut(&mut Self, Self::Pos, Self::Val)>(&mut self, _f: F) {}
fn set(&mut self, pos: Self::Pos, val: Self::Val);
fn get(&self, pos: Self::Pos) -> Self::Val;
fn print(&self);
fn is_solved(&self) -> bool;
fn remove(&mut self, other: &Self);
}
pub struct SolveSettings {
pub solve_simple: bool,
pub debug: bool,
pub difference: bool,
pub sleep_ms: Option<u64>,
pub max_iterations: Option<u64>,
pub print_millions: bool,
}
impl SolveSettings {
pub fn new() -> SolveSettings {
SolveSettings {
solve_simple: true,
debug: false,
difference: false,
sleep_ms: None,
max_iterations: None,
print_millions: false,
}
}
pub fn set_solve_simple(&mut self, val: bool) {
self.solve_simple = val;
}
pub fn solve_simple(mut self, val: bool) -> Self {
self.set_solve_simple(val);
self
}
pub fn set_debug(&mut self, val: bool) {
self.debug = val;
}
pub fn debug(mut self, val: bool) -> Self {
self.set_debug(val);
self
}
pub fn set_difference(&mut self, val: bool) {
self.difference = val;
}
pub fn difference(mut self, val: bool) -> Self {
self.set_difference(val);
self
}
pub fn set_maybe_sleep_ms(&mut self, val: Option<u64>) {
self.sleep_ms = val;
}
pub fn maybe_sleep_ms(mut self, val: Option<u64>) -> Self {
self.set_maybe_sleep_ms(val);
self
}
pub fn set_sleep_ms(&mut self, val: u64) {
self.sleep_ms = Some(val);
}
pub fn sleep_ms(mut self, val: u64) -> Self {
self.set_sleep_ms(val);
self
}
pub fn set_maybe_max_iterations(&mut self, val: Option<u64>) {
self.max_iterations = val;
}
pub fn maybe_max_iterations(mut self, val: Option<u64>) -> Self {
self.set_maybe_max_iterations(val);
self
}
pub fn set_max_iterations(&mut self, val: u64) {
self.max_iterations = Some(val);
}
pub fn max_iterations(mut self, val: u64) -> Self {
self.set_max_iterations(val);
self
}
pub fn set_print_millions(&mut self, val: bool) {
self.print_millions = val;
}
pub fn print_millions(mut self, val: bool) -> Self {
self.set_print_millions(val);
self
}
}
pub struct Solution<T> {
pub puzzle: T,
pub iterations: u64,
pub strategy: Option<usize>,
}
pub struct BackTrackSolver<T>
where T: Puzzle
{
pub original: T,
pub state: T,
pub prevs: Vec<(T::Pos, T::Val, bool)>,
pub choice: Vec<(T::Pos, Vec<T::Val>)>,
pub settings: SolveSettings,
}
impl<T> BackTrackSolver<T>
where T: Puzzle
{
pub fn new(puzzle: T, settings: SolveSettings) -> BackTrackSolver<T> {
BackTrackSolver {
original: puzzle.clone(),
state: puzzle,
prevs: vec![],
choice: vec![],
settings: settings,
}
}
pub fn solve<F, G>(mut self, mut f: F, mut g: G) -> Option<Solution<T>>
where F: FnMut(&T) -> Option<T::Pos>,
G: FnMut(&T, T::Pos) -> Vec<T::Val>
{
use std::thread::sleep;
use std::time::Duration;
let mut iterations: u64 = 0;
loop {
if self.settings.debug {
if let Some(ms) = self.settings.sleep_ms {
sleep(Duration::from_millis(ms));
}
}
if self.settings.solve_simple {
let ref mut prevs = self.prevs;
self.state.solve_simple(|state, pos, val| {
prevs.push((pos, state.get(pos), true));
state.set(pos, val);
});
}
if self.settings.debug {
self.state.print();
}
iterations += 1;
if let Some(max_iterations) = self.settings.max_iterations {
if iterations > max_iterations {
return None;
}
}
if self.state.is_solved() {
if self.settings.debug {
eprintln!("Solved! Iterations: {}", iterations);
}
if self.settings.difference {
self.state.remove(&self.original);
}
return Some(Solution { puzzle: self.state, iterations: iterations, strategy: None });
}
let empty = f(&self.state);
let mut possible = match empty {
None => vec![],
Some(x) => g(&self.state, x)
};
if possible.len() == 0 {
loop {
if self.choice.len() == 0 {
if self.settings.debug {
eprintln!("No more possible choices");
}
return None;
}
let (pos, mut possible) = self.choice.pop().unwrap();
if let Some(new_val) = possible.pop() {
while let Some((old_pos, old_val, simple)) = self.prevs.pop() {
self.state.set(old_pos, old_val);
if !simple {break}
}
self.prevs.push((pos, self.state.get(pos), false));
self.state.set(pos, new_val);
self.choice.push((pos, possible));
if self.settings.debug {
eprintln!("Try {:?}, {:?} depth ch: {} prev: {} (failed at {:?}) it: {}",
pos, new_val, self.choice.len(), self.prevs.len(), empty, iterations);
} else if self.settings.print_millions && (iterations % 1_000_000 == 0) {
eprintln!("Iteration: {}mill", iterations / 1_000_000);
}
break;
} else {
let mut undo = false;
while let Some((old_pos, old_val, simple)) = self.prevs.pop() {
self.state.set(old_pos, old_val);
undo = true;
if !simple {break}
}
if !undo {
return None;
}
}
}
} else {
let empty = empty.unwrap();
let v = possible.pop().unwrap();
self.prevs.push((empty, self.state.get(empty), false));
self.state.set(empty, v);
self.choice.push((empty, possible));
if self.settings.debug {
eprintln!("Guess {:?}, {:?} depth ch: {} prev: {} it: {}",
empty, v, self.choice.len(), self.prevs.len(), iterations);
} else if self.settings.print_millions && (iterations % 1_000_000 == 0) {
eprintln!("Iteration: {}mill", iterations / 1_000_000);
}
}
}
}
}
pub struct MultiBackTrackSolver<T>
where T: Puzzle
{
pub states: Vec<T>,
pub prevs: Vec<Vec<(T::Pos, T::Val, bool)>>,
pub choice: Vec<Vec<(T::Pos, Vec<T::Val>)>>,
pub settings: SolveSettings,
}
impl<T> MultiBackTrackSolver<T>
where T: Puzzle
{
pub fn new(settings: SolveSettings) -> MultiBackTrackSolver<T> {
MultiBackTrackSolver {
states: vec![],
prevs: vec![],
choice: vec![],
settings: settings,
}
}
pub fn solve(
mut self,
puzzle: T,
strategies: &[(fn(&T) -> Option<T::Pos>, fn(&T, T::Pos) -> Vec<T::Val>)]
) -> Option<Solution<T>> {
use std::thread::sleep;
use std::time::Duration;
let origin = puzzle.clone();
self.states = vec![puzzle; strategies.len()];
self.prevs = vec![vec![]; strategies.len()];
self.choice = vec![vec![]; strategies.len()];
let mut iterations: u64 = 0;
loop {
if self.settings.debug {
if let Some(ms) = self.settings.sleep_ms {
sleep(Duration::from_millis(ms));
}
}
iterations += 1;
if let Some(max_iterations) = self.settings.max_iterations {
if iterations > max_iterations {
return None;
}
}
for i in 0..strategies.len() {
let ref mut state = self.states[i];
let ref mut prevs = self.prevs[i];
let ref mut choice = self.choice[i];
let (f, g) = strategies[i];
if self.settings.solve_simple {
state.solve_simple(|state, pos, val| {
prevs.push((pos, state.get(pos), true));
state.set(pos, val)
});
}
if self.settings.debug {
println!("Strategy {}", i);
state.print();
}
if state.is_solved() {
if self.settings.debug {
println!("Solved! Iterations: {}", iterations);
}
if self.settings.difference {
state.remove(&origin);
}
return Some(Solution { puzzle: state.clone(), iterations: iterations, strategy: Some(i) });
}
let empty = f(&state);
let mut possible = match empty {
None => vec![],
Some(x) => g(&state, x)
};
if possible.len() == 0 {
loop {
if choice.len() == 0 {
if self.settings.debug {
println!("No more possible choices");
}
return None;
}
let (pos, mut possible) = choice.pop().unwrap();
if let Some(new_val) = possible.pop() {
while let Some((old_pos, old_val, simple)) = prevs.pop() {
state.set(old_pos, old_val);
if !simple {break}
}
prevs.push((pos, state.get(pos), false));
state.set(pos, new_val);
choice.push((pos, possible));
if self.settings.debug {
eprintln!("Try {:?}, {:?} depth ch: {} prev: {} (failed at {:?}) it: {}",
pos, new_val, self.choice.len(), self.prevs.len(), empty, iterations);
} else if self.settings.print_millions && (iterations % 1_000_000 == 0) {
eprintln!("Iteration: {}mill", iterations / 1_000_000);
}
break;
} else {
let mut undo = false;
while let Some((old_pos, old_val, simple)) = prevs.pop() {
state.set(old_pos, old_val);
undo = true;
if !simple {break}
}
if !undo {
return None;
}
}
}
} else {
let empty = empty.unwrap();
let v = possible.pop().unwrap();
prevs.push((empty, state.get(empty), false));
state.set(empty, v);
choice.push((empty, possible));
if self.settings.debug {
eprintln!("Guess {:?}, {:?} depth ch: {} prev: {} it: {}",
empty, v, self.choice.len(), self.prevs.len(), iterations);
} else if self.settings.print_millions && (iterations % 1_000_000 == 0) {
eprintln!("Iteration: {}mill", iterations / 1_000_000);
}
}
}
}
}
}
pub fn combine<T>(lists: Vec<Vec<T>>) -> Vec<T>
where T: Clone + ::std::hash::Hash + Eq
{
let mut priority: fnv::FnvHashMap<T, usize> = fnv::FnvHashMap::default();
for list in &lists {
for (i, ch) in list.iter().enumerate() {
if priority.contains_key(ch) {
let old = priority[ch];
priority.insert(ch.clone(), old + i);
} else {
priority.insert(ch.clone(), i);
}
}
}
let keys: Vec<&T> = priority.keys().collect();
let mut inds: Vec<usize> = (0..keys.len()).collect();
inds.sort_by_key(|&ind| priority[keys[ind]]);
let mut res = Vec::with_capacity(keys.len());
for &ind in &inds {
res.push(keys[ind].clone());
}
res
}
pub struct EntropySolveSettings {
pub attempts: u64,
pub noise: f64,
pub final_attempt: Option<Option<u64>>,
}
impl EntropySolveSettings {
pub fn new() -> EntropySolveSettings {
EntropySolveSettings {
attempts: 1,
noise: 0.0,
final_attempt: None,
}
}
pub fn set_attempts(&mut self, val: u64) {
self.attempts = val;
}
pub fn attempts(mut self, val: u64) -> Self {
self.set_attempts(val);
self
}
pub fn set_noise(&mut self, val: f64) {
self.noise = val;
}
pub fn noise(mut self, val: f64) -> Self {
self.set_noise(val);
self
}
pub fn set_final_attempt(&mut self, val: Option<Option<u64>>) {
self.final_attempt = val;
}
pub fn final_attempt(mut self, val: Option<Option<u64>>) -> Self {
self.set_final_attempt(val);
self
}
}
pub struct EntropyBackTrackSolver<T> where T: Puzzle {
pub original: T,
pub state: T,
pub prevs: Vec<(T::Pos, T::Val, bool)>,
pub choice: Vec<(T::Pos, Vec<T::Val>)>,
pub start_choice: Vec<(T::Pos, Vec<T::Val>)>,
pub weights: Vec<Vec<f64>>,
pub settings: SolveSettings,
pub entropy_settings: EntropySolveSettings,
}
impl<T> EntropyBackTrackSolver<T> where T: Puzzle {
pub fn new(
puzzle: T,
start_choice: Vec<(T::Pos, Vec<T::Val>)>,
entropy_settings: EntropySolveSettings,
settings: SolveSettings
) -> Self {
let weights = start_choice.iter().map(|n| vec![1.0; n.1.len()]).collect();
EntropyBackTrackSolver {
original: puzzle.clone(),
prevs: vec![],
state: puzzle,
choice: vec![],
start_choice,
weights,
entropy_settings,
settings,
}
}
pub fn entropy(&self, i: usize) -> f64 {
let sum: f64 = self.weights[i].iter().sum();
self.weights[i].iter().map(|&w| {
let p: f64 = w / sum;
-(p * p.ln())
}).sum()
}
pub fn min_entropy<G>(&self, g: &mut G) -> Option<(usize, T::Pos)>
where G: FnMut(&T, T::Pos) -> Vec<T::Val>
{
let mut min: Option<(usize, f64)> = None;
for i in 0..self.weights.len() {
if self.weights.len() == 0 {continue};
if g(&self.state, self.start_choice[i].0).len() == 0 {continue};
let e = self.entropy(i);
if min.is_none() || min.unwrap().1 > e {
min = Some((i, e));
}
}
min.map(|(i, _)| (i, self.start_choice[i].0))
}
pub fn observe(&mut self, pos: T::Pos, new_val: T::Val)
where T::Pos: PartialEq,
{
for (i, ch) in self.start_choice.iter().enumerate() {
if ch.0 == pos {
for (j, val) in self.start_choice[i].1.iter().enumerate() {
if *val == new_val {
self.weights[i][j] += 1.0;
return;
}
}
}
}
}
pub fn solve<G>(&mut self, g: G) -> (u64, Option<Solution<T>>)
where G: Copy + FnMut(&T, T::Pos) -> Vec<T::Val>,
T::Pos: PartialEq
{
let mut solution = None;
let mut i = 0;
if self.settings.max_iterations.is_some() {
loop {
if i >= self.entropy_settings.attempts {break};
if solution.is_none() {
solution = self.solve_single_attempt(g);
} else {
break;
}
i += 1;
}
}
if solution.is_none() {
if let Some(new_max_iter) = self.entropy_settings.final_attempt {
let max_iter = self.settings.max_iterations;
let noise = self.entropy_settings.noise;
self.entropy_settings.noise = 0.0;
self.settings.max_iterations = new_max_iter;
solution = self.solve_single_attempt(g);
self.settings.max_iterations = max_iter;
self.entropy_settings.noise = noise;
}
}
(i, solution)
}
pub fn solve_single_attempt<G>(&mut self, mut g: G) -> Option<Solution<T>>
where G: FnMut(&T, T::Pos) -> Vec<T::Val>,
T::Pos: PartialEq
{
use std::thread::sleep;
use std::time::Duration;
let mut rng = rand::thread_rng();
let mut iterations: u64 = 0;
loop {
if self.settings.debug {
if let Some(ms) = self.settings.sleep_ms {
sleep(Duration::from_millis(ms));
}
}
if self.settings.solve_simple {
let ref mut prevs = self.prevs;
self.state.solve_simple(|state, pos, val| {
prevs.push((pos, state.get(pos), true));
state.set(pos, val);
});
}
if self.settings.debug {
self.state.print();
}
iterations += 1;
if let Some(max_iterations) = self.settings.max_iterations {
if iterations > max_iterations {
return None;
}
}
if self.state.is_solved() {
if self.settings.debug {
eprintln!("Solved! Iterations: {}", iterations);
}
if self.settings.difference {
self.state.remove(&self.original);
}
return Some(Solution { puzzle: self.state.clone(), iterations: iterations, strategy: None });
}
let empty = self.min_entropy(&mut g);
let mut possible = match empty {
None => vec![],
Some((ind, x)) => {
use rand::Rng;
let mut possible = g(&self.state, x);
if rng.gen::<f64>() < self.entropy_settings.noise {
use rand::seq::SliceRandom;
possible.shuffle(&mut rng);
possible
} else {
let mut keys = vec![];
for (j, p) in possible.iter().enumerate() {
for i in 0..self.start_choice[ind].1.len() {
if self.start_choice[ind].1[i] == *p {
keys.push((j, self.weights[ind][i]));
break;
}
}
}
keys.sort_by(|&(_, a), &(_, b)| a.partial_cmp(&b).unwrap());
let new_possible = keys.iter().map(|&(i, _)| possible[i]).collect::<Vec<T::Val>>();
new_possible
}
}
};
if possible.len() == 0 {
loop {
if self.choice.len() == 0 {
if self.settings.debug {
eprintln!("No more possible choices");
}
return None;
}
let (pos, mut possible) = self.choice.pop().unwrap();
if let Some(new_val) = possible.pop() {
while let Some((old_pos, old_val, simple)) = self.prevs.pop() {
self.state.set(old_pos, old_val);
if !simple {break}
}
self.prevs.push((pos, self.state.get(pos), false));
self.state.set(pos, new_val);
self.observe(pos, new_val);
self.choice.push((pos, possible));
if self.settings.debug {
eprintln!("Try {:?}, {:?} depth ch: {} prev: {} (failed at {:?}) it: {}",
pos, new_val, self.choice.len(), self.prevs.len(), empty, iterations);
} else if self.settings.print_millions && (iterations % 1_000_000 == 0) {
eprintln!("Iteration: {}mill", iterations / 1_000_000);
}
break;
} else {
let mut undo = false;
while let Some((old_pos, old_val, simple)) = self.prevs.pop() {
self.state.set(old_pos, old_val);
undo = true;
if !simple {break}
}
if !undo {
return None;
}
}
}
} else {
let empty = empty.unwrap().1;
let v = possible.pop().unwrap();
self.prevs.push((empty, self.state.get(empty), false));
self.state.set(empty, v);
self.observe(empty, v);
self.choice.push((empty, possible));
if self.settings.debug {
eprintln!("Guess {:?}, {:?} depth ch: {} prev: {} it: {}",
empty, v, self.choice.len(), self.prevs.len(), iterations);
} else if self.settings.print_millions && (iterations % 1_000_000 == 0) {
eprintln!("Iteration: {}mill", iterations / 1_000_000);
}
}
}
}
}