digraph_rs/analyzer/
min_weight.rs

1use 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}