prepona/graph/edge/
flow_edge.rs

1use magnitude::Magnitude;
2
3use crate::graph::edge::Edge;
4
5/// Represent a flow edge with weight, flow and capacity.
6#[derive(Debug, Copy, Clone)]
7pub struct FlowEdge<W> {
8    id: usize,
9    weight: Magnitude<W>,
10    capacity: usize,
11    flow: isize,
12}
13
14impl<W> FlowEdge<W> {
15    /// # Arguments
16    /// * `weight`: Weight of the edge.
17    /// * `capacity`: Capacity of the edge.
18    /// * `flow`: Flow of the edge.
19    ///
20    /// # Returns
21    /// Initialized edge with specified `weight`, `capacity` and `flow`.
22    ///
23    /// # Panics
24    /// If `flow` > `capacity`.
25    pub fn init_with(weight: Magnitude<W>, capacity: usize, flow: isize) -> Self {
26        if flow > capacity as isize {
27            panic!(
28                "Flow of the edge can not be greater than the capacity: {} > {}",
29                flow, capacity
30            );
31        }
32
33        FlowEdge {
34            id: 0,
35            weight,
36            capacity,
37            flow,
38        }
39    }
40
41    /// # Returns
42    /// Flow of the edge.
43    pub fn get_flow(&self) -> isize {
44        self.flow
45    }
46
47    /// # Returns
48    /// Capacity of the edge.
49    pub fn get_capacity(&self) -> usize {
50        self.capacity
51    }
52
53    /// # Arguments
54    /// `flow`: New flow of the edge.
55    ///
56    /// # Panics
57    /// If `flow` > *current capacity*.
58    pub fn set_flow(&mut self, flow: isize) {
59        if flow > self.get_capacity() as isize {
60            panic!("Flow of the edge can not be greater than the current capacity of the edge: {} > {}", flow, self.get_capacity());
61        }
62
63        self.flow = flow;
64    }
65
66    /// # Arguments
67    /// `capacity`: New capacity of the edge.
68    ///
69    /// # Panics
70    /// If `capacity` < *current flow*
71    pub fn set_capacity(&mut self, capacity: usize) {
72        if (capacity as isize) < self.get_flow() {
73            panic!("Capacity of the edge can not be smaller than the current flow of the edge: {} < {}", capacity, self.get_flow());
74        }
75        self.capacity = capacity
76    }
77}
78
79/// For documentation about each function checkout [`Edge`](crate::graph::Edge) trait.
80impl<W> Edge<W> for FlowEdge<W> {
81    fn init(weight: Magnitude<W>) -> Self {
82        FlowEdge::init_with(weight, 0, 0)
83    }
84
85    fn get_weight(&self) -> &Magnitude<W> {
86        &self.weight
87    }
88
89    fn set_weight(&mut self, weight: Magnitude<W>) {
90        self.weight = weight
91    }
92
93    fn set_id(&mut self, id: usize) {
94        self.id = id
95    }
96
97    fn get_id(&self) -> usize {
98        self.id
99    }
100}
101
102use std::any::Any;
103use std::convert::{From, TryFrom};
104impl<W: Any> From<W> for FlowEdge<W> {
105    /// Constructs a `FlowEdge` with specified `weight` and flow and capacity of 0.
106    fn from(weight: W) -> Self {
107        FlowEdge::init(weight.into())
108    }
109}
110
111impl<W: Any> TryFrom<(W, usize, isize)> for FlowEdge<W> {
112    type Error = String;
113
114    /// # Returns
115    /// * `Ok`: Containing a `FlowEdge` with specified `weight`, `capacity` and `flow`.
116    /// * `Err`: If `flow` > `capacity`.
117    fn try_from((weight, capacity, flow): (W, usize, isize)) -> Result<Self, Self::Error> {
118        if flow > capacity as isize {
119            Err(format!(
120                "Flow of the edge can not be greater than the capacity: {} > {}",
121                flow, capacity
122            ))
123        } else {
124            Ok(FlowEdge::init_with(weight.into(), capacity, flow))
125        }
126    }
127}
128
129impl<W: PartialEq> PartialEq for FlowEdge<W> {
130    fn eq(&self, other: &Self) -> bool {
131        self.weight == other.weight
132            && self.id == other.id
133            && self.flow == other.flow
134            && self.capacity == other.capacity
135    }
136}
137
138#[cfg(test)]
139mod tests {
140    use super::*;
141    use std::convert::TryInto;
142
143    #[test]
144    fn init() {
145        let edge = FlowEdge::init(2.into());
146
147        assert_eq!(edge.get_weight(), &2.into());
148        assert_eq!(edge.get_capacity(), 0);
149        assert_eq!(edge.get_flow(), 0);
150    }
151
152    #[test]
153    fn init_with() {
154        let edge = FlowEdge::init_with(2.into(), 4, 3);
155
156        assert_eq!(edge.get_weight(), &2.into());
157        assert_eq!(edge.get_capacity(), 4);
158        assert_eq!(edge.get_flow(), 3);
159    }
160
161    #[test]
162    fn set_weight() {
163        let mut edge = FlowEdge::init(2.into());
164
165        edge.set_weight(3.into());
166
167        assert_eq!(edge.get_weight(), &3.into());
168    }
169
170    #[test]
171    fn set_capacity() {
172        let mut edge = FlowEdge::init(2.into());
173
174        edge.set_capacity(5);
175
176        assert_eq!(edge.get_capacity(), 5);
177    }
178
179    #[test]
180    fn set_flow() {
181        let mut edge = FlowEdge::init(2.into());
182        edge.set_capacity(5);
183
184        edge.set_flow(4);
185
186        assert_eq!(edge.get_flow(), 4);
187    }
188
189    #[test]
190    fn from_triplet() {
191        let edge: FlowEdge<usize> = 2.into();
192
193        assert_eq!(edge.get_weight(), &2.into());
194        assert_eq!(edge.get_capacity(), 0);
195        assert_eq!(edge.get_flow(), 0);
196    }
197
198    #[test]
199    fn from_quintuplet() {
200        let edge: FlowEdge<usize> = (2, 4, 3).try_into().unwrap();
201
202        assert_eq!(edge.get_weight(), &2.into());
203        assert_eq!(edge.get_capacity(), 4);
204        assert_eq!(edge.get_flow(), 3);
205    }
206
207    #[test]
208    #[should_panic(expected = "Flow of the edge can not be greater than the capacity: 4 > 3")]
209    fn init_with_flow_larger_than_capacity() {
210        let _ = FlowEdge::init_with(2.into(), 3, 4);
211    }
212
213    #[test]
214    #[should_panic(
215        expected = "Flow of the edge can not be greater than the current capacity of the edge: 4 > 0"
216    )]
217    fn set_flow_larger_than_capacity() {
218        let mut edge = FlowEdge::init(2.into());
219
220        edge.set_flow(4);
221    }
222
223    #[test]
224    #[should_panic(
225        expected = "Capacity of the edge can not be smaller than the current flow of the edge: 0 < 4"
226    )]
227    fn set_capacity_smaller_than_flow() {
228        let mut edge = FlowEdge::init_with(2.into(), 5, 4);
229
230        edge.set_capacity(0);
231    }
232
233    #[test]
234    fn from_quintuplet_with_flow_larger_than_capacity() {
235        let edge_res: Result<FlowEdge<usize>, String> = (2, 0, 4).try_into();
236
237        assert!(edge_res.is_err());
238        assert_eq!(
239            edge_res.unwrap_err(),
240            "Flow of the edge can not be greater than the capacity: 4 > 0".to_string()
241        )
242    }
243}