Guest User

Untitled

a guest
Jun 25th, 2018
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.15 KB | None | 0 0
  1. use std::cmp;
  2. use std::collections::{BTreeSet, HashMap, HashSet};
  3.  
  4. type Float = f64;
  5.  
  6. #[derive(Debug, Clone, Copy)]
  7. struct Probability(Float);
  8.  
  9. #[derive(Debug, PartialEq, Eq)]
  10. enum ProbabilityError {
  11. Malformed,
  12. OutOfRange,
  13. }
  14.  
  15. impl Probability {
  16. fn try_new(inner: Float) -> Result<Self, ProbabilityError> {
  17. use ProbabilityError::*;
  18.  
  19. if inner.is_nan() || inner.is_infinite() {
  20. return Err(Malformed);
  21. }
  22.  
  23. if inner < 0.0 || inner > 1.0 {
  24. return Err(OutOfRange);
  25. }
  26.  
  27. Ok(Probability(inner))
  28. }
  29. }
  30.  
  31. impl cmp::PartialEq for Probability {
  32. fn eq(&self, other: &Self) -> bool {
  33. self.0 == other.0
  34. }
  35. }
  36.  
  37. impl cmp::Eq for Probability {}
  38.  
  39. impl cmp::Ord for Probability {
  40. fn cmp(&self, other: &Self) -> cmp::Ordering {
  41. self.0.partial_cmp(&other.0).unwrap()
  42. }
  43. }
  44.  
  45. impl cmp::PartialOrd for Probability {
  46. fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
  47. Some(self.cmp(&other))
  48. }
  49. }
  50.  
  51. impl std::ops::Mul for Probability {
  52. type Output = Self;
  53. fn mul(self, rhs: Self) -> Self {
  54. Probability(self.0 * rhs.0)
  55. }
  56. }
  57.  
  58. type Idx = usize;
  59.  
  60. fn min_max((a, b): (Idx, Idx)) -> (Idx, Idx) {
  61. if a < b {
  62. (a, b)
  63. } else {
  64. (b, a)
  65. }
  66. }
  67.  
  68. #[derive(Default, Debug)]
  69. struct ProbGraph {
  70. edges: HashMap<(Idx, Idx), Probability>,
  71. neighbors_set: HashMap<Idx, HashSet<Idx>>,
  72. }
  73.  
  74. impl ProbGraph {
  75. fn insert_edge(&mut self, edge: (Idx, Idx, Probability)) {
  76. let no_neighbors = || HashSet::new();
  77.  
  78. let (idx1, idx2, prob) = edge;
  79. let idx_pair = min_max((idx1, idx2));
  80.  
  81. self.edges.insert(idx_pair, prob);
  82. self.neighbors_set
  83. .entry(idx1)
  84. .or_insert_with(no_neighbors)
  85. .insert(idx2);
  86. self.neighbors_set
  87. .entry(idx2)
  88. .or_insert_with(no_neighbors)
  89. .insert(idx1);
  90. }
  91.  
  92. fn get_probability(&self, edge: (Idx, Idx)) -> Option<Probability> {
  93. self.edges.get(&min_max(edge)).cloned()
  94. }
  95.  
  96. fn get_neighbors(&self, vertex: Idx) -> Option<&HashSet<Idx>> {
  97. self.neighbors_set.get(&vertex)
  98. }
  99.  
  100. fn visit(&mut self, vertex: Idx) {
  101. if let Some(neighbors) = self.neighbors_set.remove(&vertex) {
  102. for neighbor in neighbors {
  103. self.neighbors_set.entry(neighbor).and_modify(|set| {set.remove(&vertex);});
  104. }
  105. }
  106. }
  107. }
  108.  
  109. #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
  110. struct ProbabilityTo(Probability, Idx);
  111.  
  112. type ProbabilityHeap = BTreeSet<ProbabilityTo>;
  113.  
  114. trait FetchMax {
  115. type Item;
  116. fn get_max(&self) -> Option<&Self::Item>;
  117. fn fetch_max(&mut self) -> Option<Self::Item>;
  118. }
  119.  
  120. impl FetchMax for ProbabilityHeap {
  121. type Item = ProbabilityTo;
  122.  
  123. fn get_max(&self) -> Option<&Self::Item> {
  124. self.range(..).rev().next()
  125. }
  126.  
  127. fn fetch_max(&mut self) -> Option<Self::Item> {
  128. self.get_max().cloned().map(|max| {
  129. self.remove(&max);
  130. max
  131. })
  132. }
  133. }
  134.  
  135. fn max_survivability(edges: &[(Idx, Idx, Float)]) -> Probability {
  136. if edges.is_empty() {
  137. panic!("max_survivability: input is empty");
  138. }
  139.  
  140. let never = Probability::try_new(0.0).unwrap();
  141. let always = Probability::try_new(1.0).unwrap();
  142.  
  143. let mut start = Idx::max_value();
  144. let mut end = Idx::min_value();
  145. let mut graph = ProbGraph::default();
  146. let mut candidates = ProbabilityHeap::new();
  147. let mut probabilities = HashMap::new();
  148.  
  149. for (i, &(from, to, float)) in edges.iter().enumerate() {
  150. if from == to {
  151. panic!("max_survivability: found loop at {}: both indices are {}",
  152. i,
  153. from);
  154. }
  155.  
  156. let prob = Probability::try_new(float)
  157. .unwrap_or_else(|err| {
  158. panic!("max_survivability: failed to convert {} at {} into probability: {:?}",
  159. float,
  160. i,
  161. err)
  162. });
  163.  
  164. graph.insert_edge((from, to, prob));
  165. candidates.insert(ProbabilityTo(never, from));
  166. candidates.insert(ProbabilityTo(never, to));
  167.  
  168. start = start.min(from);
  169. end = end.max(to);
  170.  
  171. probabilities.insert(from, never);
  172. probabilities.insert(to, never);
  173. }
  174.  
  175. probabilities.insert(start, always);
  176. candidates.remove(&ProbabilityTo(never, start));
  177. candidates.insert(ProbabilityTo(always, start));
  178.  
  179. while let Some(ProbabilityTo(prob, idx)) = candidates.fetch_max() {
  180. for &neighbor in graph.get_neighbors(idx).unwrap() {
  181. let new = graph.get_probability((idx, neighbor)).unwrap() * prob;
  182. let old = probabilities[&neighbor];
  183. if new > old {
  184. candidates.remove(&ProbabilityTo(old, neighbor));
  185. candidates.insert(ProbabilityTo(new, neighbor));
  186. *probabilities.get_mut(&neighbor).unwrap() = new;
  187. }
  188. }
  189.  
  190. graph.visit(idx);
  191. println!();
  192. }
  193.  
  194. probabilities[&end]
  195. }
  196.  
  197. fn main() {
  198. println!("{}", max_survivability(&[(0, 1, 0.5), (1, 2, 0.5)]).0); //0.25
  199. println!("{}", max_survivability(&[(0, 1, 0.5), (1, 2, 0.5), (0, 2, 0.7)]).0); //0.7
  200. }
Add Comment
Please, Sign In to add comment