use crate::graph::Graph;
use crate::GraphErrors;
use crate::Node;
use crate::traits::*;
use crate::iter::{INContainedIterMut, NContainedIterMut, ContainedIterMut};
use crate::graph::NodeContainer;
use std::borrow::Borrow;
use std::convert::AsRef;
#[cfg(feature = "serde_support")]
use serde::{Serialize, Deserialize};
#[derive(Debug, Clone)]
pub enum ErStepC {
Nothing,
AddedEdge((u32, u32)),
RemovedEdge((u32, u32)),
GError(GraphErrors),
}
impl ErStepC {
pub fn is_valid(&self) -> bool {
match self {
Self::GError(_) => false,
_ => true,
}
}
pub fn valid_or_panic(&self) {
if let Self::GError(error) = self {
panic!("ErStepC - invalid - {}", error)
}
}
pub fn valid_or_panic_msg(&self, msg: &str) {
if let Self::GError(error) = self {
panic!("ErStepC - invalid {}- {}", msg, error)
}
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
pub struct ErEnsembleC<T, R>
where T: Node,
R: rand::Rng
{
graph: Graph<T>,
prob: f64,
c_target: f64,
rng: R,
}
impl<T, R> AsRef<Graph<T>> for ErEnsembleC<T, R>
where T: Node,
R: rand::Rng
{
#[inline]
fn as_ref(&self) -> &Graph<T>{
&self.graph
}
}
impl<T, R> Borrow<Graph<T>> for ErEnsembleC<T, R>
where T: Node,
R: rand::Rng
{
#[inline]
fn borrow(&self) -> &Graph<T> {
&self.graph
}
}
impl<T, R> HasRng<R> for ErEnsembleC<T, R>
where T: Node,
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 ErEnsembleC<T, R>
where T: Node + SerdeStateConform,
R: rand::Rng,
{
fn randomize(&mut self) {
self.graph.clear_edges();
for i in 0..self.graph.vertex_count() {
for j in i+1..self.graph.vertex_count() {
if self.rng.gen::<f64>() <= self.prob {
self.graph.add_edge(i, j).unwrap();
}
}
}
}
}
impl<T, R> MarkovChain<ErStepC, ErStepC> for ErEnsembleC<T, R>
where T: Node + SerdeStateConform,
R: rand::Rng,
{
fn m_step(&mut self) -> ErStepC {
let edge = draw_two_from_range(&mut self.rng, self.graph.vertex_count());
if self.rng.gen::<f64>() <= self.prob {
let success = self.graph.add_edge(edge.0, edge.1);
match success {
Ok(_) => ErStepC::AddedEdge(edge),
Err(_) => ErStepC::Nothing,
}
} else {
let success = self.graph.remove_edge(edge.0, edge.1);
match success {
Ok(_) => ErStepC::RemovedEdge(edge),
Err(_) => ErStepC::Nothing,
}
}
}
fn undo_step(&mut self, step: ErStepC) -> ErStepC {
match step {
ErStepC::AddedEdge(edge) => {
let res = self.graph.remove_edge(edge.0, edge.1);
match res {
Err(err) => ErStepC::GError(err),
Ok(_) => ErStepC::RemovedEdge(edge),
}
},
ErStepC::RemovedEdge(edge) => {
let res = self.graph.add_edge(edge.0, edge.1);
match res {
Err(err) => ErStepC::GError(err),
Ok(_) => ErStepC::AddedEdge(edge),
}
},
ErStepC::Nothing |
ErStepC::GError(_) => step,
}
}
fn undo_step_quiet(&mut self, step: ErStepC) {
match step {
ErStepC::AddedEdge(edge) => {
let res = self.graph.remove_edge(edge.0, edge.1);
if res.is_err() {
panic!("ErEnsembleC - undo_step - panic {:?}", res.unwrap_err());
}
},
ErStepC::RemovedEdge(edge) => {
let res = self.graph.add_edge(edge.0, edge.1);
if res.is_err() {
panic!("ErEnsembleC - undo_step - panic {:?}", res.unwrap_err());
}
},
_ => step.valid_or_panic_msg("ErEnsembleC - quiet")
}
}
}
impl<T, R> ErEnsembleC<T, R>
where T: Node + SerdeStateConform,
R: rand::Rng
{
pub fn new(n: u32, c_target: f64, rng: R) -> Self {
let prob = c_target / (n - 1) as f64;
let graph: Graph<T> = Graph::new(n);
let mut e = ErEnsembleC {
graph,
c_target,
prob,
rng,
};
e.randomize();
e
}
pub fn target_connectivity(&self) -> f64 {
self.c_target
}
pub fn set_target_connectivity(&mut self, c_target: f64) {
let prob = c_target / (self.graph().vertex_count() - 1) as f64;
self.prob = prob;
self.c_target = c_target;
}
fn graph_mut(&mut self) -> &mut Graph<T> {
&mut self.graph
}
pub fn sort_adj(&mut self) {
self.graph_mut().sort_adj();
}
}
impl<T, R> GraphIteratorsMut<T, Graph<T>, NodeContainer<T>> for ErEnsembleC<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 ErEnsembleC<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 draw_two_from_range<T: rand::Rng>(rng: &mut T, high: u32) -> (u32, u32){
let first = rng.gen_range(0, high);
let second = rng.gen_range(0, high - 1);
if second < first {
(first, second)
} else {
(first, second + 1)
}
}
#[cfg(test)]
mod testing {
use super::*;
use rand_pcg::Pcg64;
use crate::EmptyNode;
use rand::SeedableRng;
#[test]
fn test_edge_count() {
let rng = Pcg64::seed_from_u64(12);
let mut e = ErEnsembleC::<EmptyNode, Pcg64>::new(100, 0.0, rng);
let ec = e.graph().edge_count();
assert_eq!(0, ec);
assert!(
!e.graph()
.is_connected()
.expect("test_edge_count error 1")
);
e.graph_mut()
.add_edge(0, 1)
.unwrap();
let ec_1 = e.graph().edge_count();
assert_eq!(1, ec_1);
let mut res = e.graph_mut()
.add_edge(0, 1);
assert!(res.is_err());
e.graph_mut()
.remove_edge(0, 1)
.unwrap();
let ec_0 = e.graph().edge_count();
assert_eq!(0, ec_0);
res = e.graph_mut()
.remove_edge(0, 1);
assert!(res.is_err());
}
#[test]
fn draw_2(){
let mut rng = Pcg64::seed_from_u64(762132);
for _i in 0..100 {
let (first, second) = draw_two_from_range(&mut rng, 2);
assert!(first != second);
}
for i in 2..100 {
let (first, second) = draw_two_from_range(&mut rng, i);
assert!(first != second);
}
}
}