digraph_rs/analyzer/
min_weight.rs1use std::cmp::Ordering;
2use std::ops::Add;
3use Score::{Inf, Value, Zero};
4
5#[derive(Debug, Clone)]
6pub enum Score<ScoreValue> {
7 Inf,
8 Zero,
9 Value(ScoreValue),
10}
11
12impl<ScoreValue> Add for Score<ScoreValue>
13where
14 ScoreValue: Add<Output = ScoreValue> + Clone,
15{
16 type Output = Score<ScoreValue>;
17
18 fn add(self, rhs: Self) -> Self::Output {
19 match (self,rhs) {
20 (Inf,_) | (_,Inf) => Inf,
21 (Zero,res)|(res,Zero) => res,
22 (Value(lhs),Value(rhs)) => Value(lhs + rhs),
23 }
24 }
25
26}
27
28impl<ScoreValue:ToString> ToString for Score<ScoreValue> {
29 fn to_string(&self) -> String {
30 match self{
31 Inf => "inf".to_string(),
32 Zero => "zero".to_string(),
33 Value(v) => v.to_string(),
34 }
35 }
36}
37
38
39
40
41
42impl<ScoreValue> Score<ScoreValue>
43where
44 ScoreValue: Add<Output = ScoreValue> + Clone,
45{
46 pub fn add_score_v(&self, score: ScoreValue) -> Score<ScoreValue> {
47 match &self {
48 Inf => Inf,
49 Zero => Value(score),
50 Value(left) => Value(left.clone() + score),
51 }
52 }
53}
54
55impl<'a, ScoreValue: Eq> Eq for Score<ScoreValue> {}
56impl<'a, ScoreValue: Eq> PartialEq for Score<ScoreValue> {
57 fn eq(&self, other: &Self) -> bool {
58 match (self, other) {
59 (Inf, Inf) | (Zero, Zero) => true,
60 (Value(lhs), Value(rhs)) => lhs.eq(rhs),
61 _ => false,
62 }
63 }
64}
65impl<ScoreValue: Ord> PartialOrd for Score<ScoreValue> {
66 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
67 if self == other {
68 Some(Ordering::Equal)
69 } else {
70 match (self, other) {
71 (Inf, _) => Some(Ordering::Greater),
72 (Value(_), Inf) => Some(Ordering::Less),
73 (Zero, _) => Some(Ordering::Less),
74 (Value(lhs), Value(rhs)) => Some(lhs.cmp(rhs)),
75 _ => None,
76 }
77 }
78 }
79}
80
81#[derive(Debug, Clone)]
82pub struct MinWeight<'a, Id, ScoreValue>(pub &'a Id, pub Score<ScoreValue>);
83
84impl<'a, Id, ScoreValue: Ord> Eq for MinWeight<'a, Id, ScoreValue> {}
85impl<'a, Id, ScoreValue: Ord> PartialEq<Self> for MinWeight<'a, Id, ScoreValue> {
86 fn eq(&self, other: &Self) -> bool {
87 match (&self.1, &other.1) {
88 (Inf, Inf) | (Zero, Zero) => true,
89 (Value(l), Value(r)) => l.cmp(r) == Ordering::Equal,
90 _ => false,
91 }
92 }
93}
94
95impl<'a, Id, ScoreValue: Ord> PartialOrd<Self> for MinWeight<'a, Id, ScoreValue> {
96 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
97 Some(self.cmp(other))
98 }
99}
100
101impl<'a, Id, ScoreValue: Ord> Ord for MinWeight<'a, Id, ScoreValue> {
102 fn cmp(&self, other: &Self) -> Ordering {
103 if self.eq(other) {
104 Ordering::Equal
105 } else {
106 match (&self.1, &other.1) {
107 (Inf, _) | (_, Zero) => Ordering::Less,
108 (Zero, _) | (_, Inf) => Ordering::Greater,
109 (Value(lhs), Value(rhs)) => {
110 if lhs < rhs {
111 Ordering::Greater
112 } else if lhs > rhs {
113 Ordering::Less
114 } else if lhs.ne(lhs) && rhs.ne(rhs) {
115 Ordering::Equal
116 } else if lhs.ne(lhs) {
117 Ordering::Less
118 } else {
119 Ordering::Greater
120 }
121 }
122 }
123 }
124 }
125}