#[allow(unused_imports)]
use crate::mwpf::shim::prelude::*;
use crate::mwpf::invalid_subgraph::*;
use crate::mwpf::num_traits::Zero;
use crate::mwpf::relaxer::*;
use crate::mwpf::util::*;
use num_traits::Signed;
use std::sync::Arc;
pub type RelaxerVec = Vec<Relaxer>;
pub struct RelaxerForest {
tight_edges: FastIterSet<EdgeIndex>,
shrinkable_subgraphs: FastIterSet<Arc<InvalidSubgraph>>,
edge_untightener: FastIterMap<EdgeIndex, (Arc<Relaxer>, Rational)>,
expanded_relaxers: FastIterMap<Arc<Relaxer>, Relaxer>,
}
pub const FOREST_ERR_MSG_GROW_TIGHT_EDGE: &str = "invalid relaxer: try to grow a tight edge";
pub const FOREST_ERR_MSG_UNSHRINKABLE: &str = "invalid relaxer: try to shrink a unshrinkable subgraph";
impl RelaxerForest {
pub fn new<IterEdge, IterSubgraph>(tight_edges: IterEdge, shrinkable_subgraphs: IterSubgraph) -> Self
where
IterEdge: Iterator<Item = EdgeIndex>,
IterSubgraph: Iterator<Item = Arc<InvalidSubgraph>>,
{
Self {
tight_edges: FastIterSet::from_iter(tight_edges),
shrinkable_subgraphs: FastIterSet::from_iter(shrinkable_subgraphs),
edge_untightener: FastIterMap::new(),
expanded_relaxers: FastIterMap::new(),
}
}
pub fn validate(&self, relaxer: &Relaxer) -> Result<(), String> {
relaxer.sanity_check()?;
for (edge_index, _) in relaxer.get_growing_edges().iter() {
if self.tight_edges.contains(edge_index) && !self.edge_untightener.contains_key(edge_index) {
return Err(format!("{FOREST_ERR_MSG_GROW_TIGHT_EDGE}: {edge_index}"));
}
}
for (invalid_subgraph, grow_ratio) in relaxer.get_direction().iter() {
if grow_ratio.is_negative() && !self.shrinkable_subgraphs.contains(invalid_subgraph) {
return Err(format!("{FOREST_ERR_MSG_UNSHRINKABLE}: {invalid_subgraph:?}"));
}
}
Ok(())
}
pub fn add(&mut self, relaxer: Arc<Relaxer>) {
debug_assert_eq!(self.validate(&relaxer), Ok(()));
for (edge_index, speed) in relaxer.get_untighten_edges().iter() {
debug_assert!(speed.is_negative());
if !self.edge_untightener.contains_key(edge_index) {
self.edge_untightener.insert(*edge_index, (relaxer.clone(), -speed.recip()));
}
}
}
fn compute_expanded(&mut self, relaxer: &Arc<Relaxer>) {
if self.expanded_relaxers.contains_key(relaxer) {
return;
}
let mut untightened_edges: FastIterMap<EdgeIndex, Rational> = FastIterMap::new();
let mut directions: FastIterMap<Arc<InvalidSubgraph>, Rational> = relaxer.get_direction().clone();
for (edge_index, speed) in relaxer.get_growing_edges().iter() {
debug_assert!(speed.is_positive());
if self.tight_edges.contains(edge_index) {
debug_assert!(
self.edge_untightener.contains_key(edge_index),
"edge {} is tight but no untightener presents, thus new relaxer cannot grow on it",
edge_index
);
let require_speed = if let Some(mut existing_speed) = untightened_edges.get_mut(edge_index) {
if *existing_speed >= *speed {
*existing_speed -= speed;
Rational::zero()
} else {
let required_speed = speed - &*existing_speed;
existing_speed.set_zero();
required_speed
}
} else {
speed.clone()
};
if require_speed.is_positive() {
let edge_relaxer = self.edge_untightener.get(edge_index).unwrap().0.clone();
self.compute_expanded(&edge_relaxer);
let (edge_relaxer, speed_ratio) = self.edge_untightener.get(edge_index).unwrap();
debug_assert!(speed_ratio.is_positive());
let expanded_edge_relaxer = self.expanded_relaxers.get(edge_relaxer).unwrap();
for (subgraph, original_speed) in expanded_edge_relaxer.get_direction().iter() {
let new_speed = original_speed * speed_ratio * require_speed.clone();
if let Some(mut speed) = directions.get_mut(subgraph) {
*speed += new_speed;
continue;
}
directions.insert(subgraph.clone(), new_speed);
}
for (edge_index, original_speed) in expanded_edge_relaxer.get_untighten_edges().iter() {
debug_assert!(original_speed.is_negative());
let new_speed = -original_speed * speed_ratio * require_speed.clone();
if let Some(mut speed) = untightened_edges.get_mut(edge_index) {
*speed += new_speed;
continue;
}
untightened_edges.insert(*edge_index, new_speed);
}
debug_assert_eq!(untightened_edges.get(edge_index), Some(&require_speed));
*untightened_edges.get_mut(edge_index).unwrap() -= require_speed;
}
}
}
let expanded = Relaxer::new(directions);
debug_assert!(expanded
.get_growing_edges()
.iter()
.all(|(edge_index, _)| !self.tight_edges.contains(edge_index)));
self.expanded_relaxers.insert(relaxer.clone(), expanded);
}
pub fn expand(&mut self, relaxer: &Arc<Relaxer>) -> Relaxer {
debug_assert_eq!(self.validate(relaxer), Ok(()));
self.compute_expanded(relaxer);
self.expanded_relaxers.get(relaxer).unwrap().clone()
}
}
#[cfg(test)]
pub mod tests {
use super::*;
use num_traits::{FromPrimitive, One};
#[test]
fn relaxer_forest_example() {
let tight_edges = [0, 1, 2, 3, 4, 5, 6];
let shrinkable_subgraphs = [
Arc::new(InvalidSubgraph::new_raw([].into(), [].into(), [1, 2, 3].into())),
Arc::new(InvalidSubgraph::new_raw([].into(), [].into(), [4, 5].into())),
];
let mut relaxer_forest = RelaxerForest::new(tight_edges.into_iter(), shrinkable_subgraphs.iter().cloned());
let invalid_subgraph_1 = Arc::new(InvalidSubgraph::new_raw([].into(), [].into(), [7, 8, 9].into()));
let relaxer_1 = Arc::new(Relaxer::new_raw(
[
(invalid_subgraph_1.clone(), Rational::one()),
(shrinkable_subgraphs[0].clone(), -Rational::one()),
]
.into(),
));
let expanded_1 = relaxer_forest.expand(&relaxer_1);
assert_eq!(expanded_1, *relaxer_1);
relaxer_forest.add(relaxer_1);
let invalid_subgraph_2 = Arc::new(InvalidSubgraph::new_raw([].into(), [].into(), [1, 2, 7].into()));
let relaxer_2 = Arc::new(Relaxer::new_raw([(invalid_subgraph_2.clone(), Rational::one())].into()));
let expanded_2 = relaxer_forest.expand(&relaxer_2);
let expected_relaxer = Relaxer::new(
[
(invalid_subgraph_1, Rational::one()),
(shrinkable_subgraphs[0].clone(), -Rational::one()),
(invalid_subgraph_2, Rational::one()),
]
.into(),
);
assert_eq!(expanded_2, expected_relaxer);
}
#[test]
fn relaxer_forest_require_multiple() {
let tight_edges = [0, 1, 2, 3, 4, 5, 6];
let shrinkable_subgraphs = [
Arc::new(InvalidSubgraph::new_raw([].into(), [].into(), [1, 2].into())),
Arc::new(InvalidSubgraph::new_raw([].into(), [].into(), [3].into())),
];
let mut relaxer_forest = RelaxerForest::new(tight_edges.into_iter(), shrinkable_subgraphs.iter().cloned());
let invalid_subgraph_1 = Arc::new(InvalidSubgraph::new_raw([].into(), [].into(), [7, 8, 9].into()));
let relaxer_1 = Arc::new(Relaxer::new_raw(
[
(invalid_subgraph_1.clone(), Rational::one()),
(shrinkable_subgraphs[0].clone(), -Rational::one()),
]
.into(),
));
relaxer_forest.add(relaxer_1);
let invalid_subgraph_2 = Arc::new(InvalidSubgraph::new_raw([].into(), [].into(), [1, 2, 7].into()));
let invalid_subgraph_3 = Arc::new(InvalidSubgraph::new_raw([].into(), [].into(), [2].into()));
let relaxer_2 = Arc::new(Relaxer::new_raw(
[
(invalid_subgraph_2.clone(), Rational::one()),
(invalid_subgraph_3.clone(), Rational::one()),
]
.into(),
));
let expanded_2 = relaxer_forest.expand(&relaxer_2);
assert_eq!(
expanded_2,
Relaxer::new(
[
(invalid_subgraph_2, Rational::one()),
(invalid_subgraph_3, Rational::one()),
(invalid_subgraph_1, Rational::from_usize(2).unwrap()),
(shrinkable_subgraphs[0].clone(), -Rational::from_usize(2).unwrap()),
]
.into()
)
);
}
#[test]
fn relaxer_forest_relaxing_same_edge() {
let tight_edges = [0, 1, 2, 3, 4, 5, 6];
let shrinkable_subgraphs = [
Arc::new(InvalidSubgraph::new_raw([].into(), [].into(), [1, 2].into())),
Arc::new(InvalidSubgraph::new_raw([].into(), [].into(), [2, 3].into())),
];
let mut relaxer_forest = RelaxerForest::new(tight_edges.into_iter(), shrinkable_subgraphs.iter().cloned());
let invalid_subgraph_1 = Arc::new(InvalidSubgraph::new_raw([].into(), [].into(), [7, 8, 9].into()));
let relaxer_1 = Arc::new(Relaxer::new_raw(
[
(invalid_subgraph_1.clone(), Rational::one()),
(shrinkable_subgraphs[0].clone(), -Rational::one()),
]
.into(),
));
relaxer_forest.add(relaxer_1);
let invalid_subgraph_2 = Arc::new(InvalidSubgraph::new_raw([].into(), [].into(), [10, 11].into()));
let relaxer_2 = Arc::new(Relaxer::new_raw(
[
(invalid_subgraph_2.clone(), Rational::one()),
(shrinkable_subgraphs[1].clone(), -Rational::one()),
]
.into(),
));
relaxer_forest.add(relaxer_2);
}
#[test]
fn relaxer_forest_validate() {
let tight_edges = [0, 1, 2, 3, 4, 5, 6];
let shrinkable_subgraphs = [
Arc::new(InvalidSubgraph::new_raw([1].into(), [].into(), [1, 2].into())),
Arc::new(InvalidSubgraph::new_raw([].into(), [].into(), [].into())),
];
let relaxer_forest = RelaxerForest::new(tight_edges.into_iter(), shrinkable_subgraphs.iter().cloned());
println!("relaxer_forest: {:?}", relaxer_forest.shrinkable_subgraphs);
let invalid_relaxer = Relaxer::new_raw(
[(
Arc::new(InvalidSubgraph::new_raw([].into(), [].into(), [].into())),
-Rational::one(),
)]
.into(),
);
let error_message = relaxer_forest.validate(&invalid_relaxer).expect_err("should panic");
assert_eq!(
&error_message[..RELAXER_ERR_MSG_NEGATIVE_SUMMATION.len()],
RELAXER_ERR_MSG_NEGATIVE_SUMMATION
);
let relaxer = Relaxer::new_raw(
[(
Arc::new(InvalidSubgraph::new_raw([].into(), [].into(), [1].into())),
Rational::one(),
)]
.into(),
);
let error_message = relaxer_forest.validate(&relaxer).expect_err("should panic");
assert_eq!(
&error_message[..FOREST_ERR_MSG_GROW_TIGHT_EDGE.len()],
FOREST_ERR_MSG_GROW_TIGHT_EDGE
);
let relaxer = Relaxer::new_raw(
[
(
Arc::new(InvalidSubgraph::new_raw([].into(), [].into(), [9].into())),
Rational::one(),
),
(
Arc::new(InvalidSubgraph::new_raw([].into(), [].into(), [2, 3].into())),
-Rational::one(),
),
]
.into(),
);
let error_message = relaxer_forest.validate(&relaxer).expect_err("should panic");
assert_eq!(
&error_message[..FOREST_ERR_MSG_UNSHRINKABLE.len()],
FOREST_ERR_MSG_UNSHRINKABLE
);
let relaxer = Relaxer::new_raw(
[(
Arc::new(InvalidSubgraph::new_raw([].into(), [].into(), [9].into())),
Rational::one(),
)]
.into(),
);
relaxer_forest.validate(&relaxer).unwrap();
}
}