use crate::traits::*;
use crate::SwGraph;
use crate::GraphErrors;
use crate::iter::{NContainedIterMut, ContainedIterMut};
use crate::sw_graph::SwContainer;
#[cfg(feature = "serde_support")]
use serde::{Serialize, Deserialize};
const ROOT_EDGES_PER_VERTEX: u32 = 2;
#[derive(Debug)]
pub enum SwChangeState {
InvalidAdjecency,
BlockedByExistingEdge,
Nothing,
Rewire(u32, u32, u32),
Reset(u32, u32, u32),
GError(GraphErrors),
}
impl SwChangeState {
pub fn is_nothing(&self) -> bool {
if let SwChangeState::Nothing = self {
true
}else{
false
}
}
pub fn is_nothing_or_blocked(&self) -> bool {
match self {
SwChangeState::Nothing |
SwChangeState::BlockedByExistingEdge => true,
_ => false
}
}
pub fn not_nothing_or_blocked(&self) -> bool {
match self {
SwChangeState::Nothing |
SwChangeState::BlockedByExistingEdge => false,
_ => true
}
}
pub fn is_valid(&self) -> bool {
match self {
SwChangeState::Rewire(..) |
SwChangeState::Reset(..) |
SwChangeState::Nothing |
SwChangeState::BlockedByExistingEdge => true,
SwChangeState::InvalidAdjecency |
SwChangeState::GError(..) => false,
}
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
pub struct SwEnsemble<T: Node, R: rand::Rng>
where T: Node,
R: rand::Rng
{
graph: SwGraph<T>,
r_prob: f64,
rng: R,
}
impl <T, R> SwEnsemble<T, R>
where T: Node + SerdeStateConform,
R: rand::Rng,
{
pub fn new(n: u32, r_prob: f64, rng: R) -> Self {
let mut graph = SwGraph::new(n);
graph.init_ring_2();
let mut result =
SwEnsemble {
graph,
r_prob,
rng,
};
result.randomize();
result
}
fn draw_remaining(&mut self, index: u32, high: u32) -> u32 {
let num = self.rng.gen_range(0, high);
if num < index {
num
} else {
num + 1
}
}
fn randomize_edge(&mut self, index0: u32, index1: u32) -> SwChangeState {
let vertex_count = self.graph.vertex_count();
if self.rng.gen::<f64>() <= self.r_prob {
let rewire_index = self.
draw_remaining(index0, vertex_count - 1);
self.graph.rewire_edge(index0, index1, rewire_index)
}else {
self.graph.reset_edge(index0, index1)
}
}
fn debug_error_check(state: SwChangeState) -> bool {
match state {
SwChangeState::GError(_) => panic!("GError"),
SwChangeState::InvalidAdjecency => panic!("InvalidAdjecency"),
_ => true
}
}
pub fn draw_edge(&mut self) -> (u32, u32) {
let rng_num = self.rng.gen_range(0, self.graph.edge_count());
let v_index = rng_num / ROOT_EDGES_PER_VERTEX;
let e_index = rng_num % ROOT_EDGES_PER_VERTEX;
let mut iter = self.graph
.container(v_index as usize)
.iter_raw_edges()
.filter(|x| x.is_root());
let &to = iter
.nth(e_index as usize)
.unwrap()
.to();
(v_index, to)
}
pub fn sort_adj(&mut self) {
self.graph.sort_adj();
}
pub fn r_prob(&self) -> f64 {
self.r_prob
}
pub fn set_r_prob(&mut self, r_prob: f64) {
self.r_prob = r_prob;
}
pub fn contained_iter_neighbors_mut(&mut self, index: usize) -> NContainedIterMut<T, SwContainer<T>>
{
self.graph.contained_iter_neighbors_mut(index)
}
}
impl<'a, T, R> GraphIteratorsMut<'a, T, SwGraph<T>, SwContainer<T>> for SwEnsemble<T, R>
where T: Node + SerdeStateConform,
R: rand::Rng
{
fn contained_iter_neighbors_mut(&'a mut self, index: usize) ->
NContainedIterMut<'a, T, SwContainer<T>>
{
self.graph.contained_iter_neighbors_mut(index)
}
fn contained_iter_mut(&'a mut self) -> ContainedIterMut<'a, T, SwContainer<T>> {
self.graph.contained_iter_mut()
}
}
impl<T, R> WithGraph<T, SwGraph<T>> for SwEnsemble<T, R>
where T: Node + SerdeStateConform,
R: rand::Rng
{
fn at(&self, index: usize) -> &T {
self.graph.at(index)
}
fn at_mut(&mut self, index: usize) -> &mut T{
self.graph.at_mut(index)
}
fn graph(&self) -> &SwGraph<T> {
&self.graph
}
}
impl<T, R> HasRng<R> for SwEnsemble<T, R>
where T: Node + SerdeStateConform,
R: rand::Rng
{
fn rng(&mut self) -> &mut R {
&mut self.rng
}
fn swap_rng(&mut self, mut rng: R) -> R {
std::mem::swap(&mut self.rng, &mut rng);
rng
}
}
impl<T, R> SimpleSample for SwEnsemble<T, R>
where T: Node + SerdeStateConform,
R: rand::Rng
{
fn randomize(&mut self){
let count = self.graph
.vertex_count();
for i in 0..count {
let vertex = self.graph
.get_mut_unchecked(i as usize);
let mut root_iter = vertex
.iter_raw_edges()
.filter(|edge| edge.is_root())
.map(|edge| edge.to());
debug_assert_eq!(ROOT_EDGES_PER_VERTEX, 2);
let first = *root_iter.next().unwrap();
let second = *root_iter.next().unwrap();
debug_assert!(root_iter.next().is_none());
let state = self.randomize_edge(i, first);
debug_assert!(Self::debug_error_check(state));
let state = self.randomize_edge(i, second);
debug_assert!(Self::debug_error_check(state));
}
}
}
impl<T, R> MarkovChain<SwChangeState, SwChangeState> for SwEnsemble<T, R>
where T: Node + SerdeStateConform,
R: rand::Rng
{
fn m_step(&mut self) -> SwChangeState {
let edge = self.draw_edge();
self.randomize_edge(edge.0, edge.1)
}
fn undo_step(&mut self, step: SwChangeState) -> SwChangeState {
match step {
SwChangeState::Rewire(root, old_to, new_to) |
SwChangeState::Reset (root, old_to, new_to) => self.graph.rewire_edge(root, new_to, old_to), SwChangeState::Nothing |
SwChangeState::BlockedByExistingEdge |
SwChangeState::InvalidAdjecency |
SwChangeState::GError(_) => step
}
}
fn undo_step_quiet(&mut self, step: SwChangeState) -> () {
match step {
SwChangeState::Rewire(root, old_to, new_to) |
SwChangeState::Reset (root, old_to, new_to) => {
let state = self.graph.rewire_edge(root, new_to, old_to);
if state.is_valid() {
()
} else {
panic!("undo step - rewire error: {:?}", state);
}
},
SwChangeState::Nothing |
SwChangeState::BlockedByExistingEdge => (),
SwChangeState::InvalidAdjecency => panic!("undo_step - {:?} - corrupt step?", step),
SwChangeState::GError(error) => panic!(format!("undo_step - GError {} - corrupt step?", error))
}
}
}