use crate::{graph::*, iter::*, traits::*};
use rand::seq::SliceRandom;
use std::borrow::Borrow;
use std::convert::AsRef;
use std::io::Write;
#[cfg(feature = "serde_support")]
use serde::{Serialize, Deserialize};
#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
pub struct ErStepM{
pub(crate) removed: (usize, usize),
pub(crate) i_removed: usize,
pub(crate) inserted: (usize, usize),
pub(crate) i_inserted: usize,
}
impl ErStepM{
#[allow(unused)]
fn invert(&mut self){
std::mem::swap(
&mut self.removed,
&mut self.inserted
);
}
fn inverted(&self) -> Self{
Self{
removed: self.inserted,
inserted: self.removed,
i_inserted: self.i_inserted,
i_removed: self.i_removed,
}
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
pub struct ErEnsembleM<T: Node, R>
{
graph: Graph<T>,
m: usize,
rng: R,
all_edges: Vec<(usize, usize)>,
possible_edges: Vec<(usize, usize)>,
current_edges: Vec<(usize, usize)>,
}
impl<T, R> AsRef<Graph<T>> for ErEnsembleM<T, R>
where T: Node,
R: rand::Rng
{
#[inline]
fn as_ref(&self) -> &Graph<T>{
&self.graph
}
}
impl<T, R> Borrow<Graph<T>> for ErEnsembleM<T, R>
where T: Node,
R: rand::Rng
{
#[inline]
fn borrow(&self) -> &Graph<T> {
&self.graph
}
}
impl<T, R> HasRng<R> for ErEnsembleM<T, R>
where T: Node,
R: rand::Rng,
{
fn rng(&mut self) -> &mut R {
&mut self.rng
}
fn swap_rng(&mut self, rng: &mut R) {
std::mem::swap(&mut self.rng, rng);
}
}
impl<T, R> SimpleSample for ErEnsembleM<T, R>
where T: Node + SerdeStateConform,
R: rand::Rng,
{
fn randomize(&mut self){
self.graph.clear_edges();
self.shuffle_all_edges();
self.current_edges
.copy_from_slice(&self.all_edges[..self.m]);
for edge in self.current_edges.iter()
{
self.graph
.add_edge(edge.0, edge.1)
.unwrap();
}
self.possible_edges
.copy_from_slice(&self.all_edges[self.m..]);
}
}
impl <T, R> MarkovChain<ErStepM, ErStepM> for ErEnsembleM<T, R>
where T: Node + SerdeStateConform,
R: rand::Rng,
{
fn undo_step(&mut self, step: &ErStepM) -> ErStepM {
let step = step.inverted();
self.step(&step);
step
}
fn undo_step_quiet(&mut self, step: &ErStepM) {
let step = step.inverted();
self.step(&step);
}
fn m_step(&mut self) -> ErStepM{
let index_current = self.rng.gen_range(0..self.current_edges.len());
let index_possible = self.rng.gen_range(0..self.possible_edges.len());
let step = ErStepM{
removed: self.current_edges[index_current],
i_removed: index_current,
inserted: self.possible_edges[index_possible],
i_inserted: index_possible
};
self.step(&step);
step
}
}
impl<T, R> ErEnsembleM<T, R>
where T: Node + SerdeStateConform,
R: rand::Rng
{
fn step(&mut self, step: &ErStepM){
self.graph
.remove_edge(step.removed.0, step.removed.1)
.unwrap();
self.graph
.add_edge(step.inserted.0, step.inserted.1)
.unwrap();
std::mem::swap(
&mut self.current_edges[step.i_removed],
&mut self.possible_edges[step.i_inserted]
);
}
pub fn new(n: usize, m: usize, rng: R) -> Self {
let graph: Graph<T> = Graph::new(n);
let p_edges = (n * (n - 1)) / 2;
assert!(
m <= p_edges,
"A complete graph with {} vertices has {} edges. \
You requested {} edges, i.e., to many. Panic at function `new` of struct {}",
n,
p_edges,
m,
std::any::type_name::<Self>()
);
let mut vec = Vec::with_capacity(p_edges);
for i in 0..n {
for j in i+1..n {
vec.push((i, j));
}
}
let mut e = ErEnsembleM {
graph,
m,
rng,
all_edges: vec,
possible_edges: vec![(0, 0); p_edges - m], current_edges: vec![(0, 0); m], };
e.randomize();
e
}
fn graph_mut(&mut self) -> &mut Graph<T> {
&mut self.graph
}
pub fn get_m(&self) -> usize {
self.m
}
fn shuffle_all_edges(&mut self) {
self.all_edges
.shuffle(&mut self.rng);
}
}
impl<T, R> GraphIteratorsMut<T, Graph<T>, NodeContainer<T>> for ErEnsembleM<T, R>
where T: Node + SerdeStateConform,
R: rand::Rng
{
fn contained_iter_neighbors_mut(&mut self, index: usize) ->
NContainedIterMut<T, NodeContainer<T>>
{
self.graph.contained_iter_neighbors_mut(index)
}
fn contained_iter_neighbors_mut_with_index(&mut self, index: usize)
-> INContainedIterMut<'_, T, NodeContainer<T>>
{
self.graph.contained_iter_neighbors_mut_with_index(index)
}
fn contained_iter_mut(&mut self) -> ContainedIterMut<T, NodeContainer<T>> {
self.graph.contained_iter_mut()
}
}
impl<T, R> WithGraph<T, Graph<T>> for ErEnsembleM<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) -> &Graph<T> {
self.borrow()
}
fn sort_adj(&mut self) {
self.graph_mut().sort_adj();
}
}
impl<T, R> Dot for ErEnsembleM<T, R>
where T: Node
{
fn dot_from_indices<F, W, S1, S2>(&self, writer: W, dot_options: S1, f: F)
-> Result<(), std::io::Error>
where
S1: AsRef<str>,
S2: AsRef<str>,
W: Write,
F: FnMut(usize) -> S2 {
self.graph
.dot_from_indices(writer, dot_options, f)
}
fn dot<S, W>(&self, writer: W, dot_options: S) -> Result<(), std::io::Error>
where
S: AsRef<str>,
W: Write {
self.graph
.dot(writer, dot_options)
}
fn dot_string<S>(&self, dot_options: S) -> String
where
S: AsRef<str> {
self.graph.dot_string(dot_options)
}
fn dot_string_from_indices<F, S1, S2>(&self, dot_options: S1, f: F) -> String
where
S1: AsRef<str>,
S2: AsRef<str>,
F: FnMut(usize) -> S2 {
self.graph
.dot_string_from_indices(dot_options, f)
}
fn dot_string_with_indices<S>(&self, dot_options: S) -> String
where
S: AsRef<str> {
self.graph
.dot_string_with_indices(dot_options)
}
fn dot_with_indices<S, W>(
&self, writer: W,
dot_options: S
) -> Result<(), std::io::Error>
where
S: AsRef<str>,
W: Write {
self.graph
.dot_with_indices(writer, dot_options)
}
}
impl<T, R> Contained<T> for ErEnsembleM<T, R>
where T: Node
{
fn get_contained(&self, index: usize) -> Option<&T> {
self.graph.get_contained(index)
}
fn get_contained_mut(&mut self, index: usize) -> Option<&mut T> {
self.graph.get_contained_mut(index)
}
unsafe fn get_contained_unchecked(&self, index: usize) -> &T {
self.graph.get_contained_unchecked(index)
}
unsafe fn get_contained_unchecked_mut(&mut self, index: usize) -> &mut T {
self.graph.get_contained_unchecked_mut(index)
}
}