1#![doc(alias = "out_degree")]
26
27use crate::Vertices;
28
29pub trait Outdegree {
31 #[doc(alias = "out_degree")]
59 #[must_use]
60 fn outdegree(&self, u: usize) -> usize;
61
62 #[must_use]
91 fn is_sink(&self, u: usize) -> bool {
92 self.outdegree(u) == 0
93 }
94
95 #[must_use]
125 fn max_outdegree(&self) -> usize
126 where
127 Self: Vertices,
128 {
129 self.vertices()
130 .map(|u| self.outdegree(u))
131 .max()
132 .unwrap_or(0)
133 }
134
135 #[must_use]
165 fn min_outdegree(&self) -> usize
166 where
167 Self: Vertices,
168 {
169 self.vertices()
170 .map(|u| self.outdegree(u))
171 .min()
172 .unwrap_or(0)
173 }
174}
175
176#[macro_export]
178macro_rules! test_outdegree {
179 ($type:ty, $fixture:path) => {
180 use $fixture::{
181 bang_jensen_34,
182 bang_jensen_94,
183 bang_jensen_196,
184 kattis_builddeps,
185 kattis_cantinaofbabel_1,
186 kattis_cantinaofbabel_2,
187 kattis_escapewallmaria_1,
188 kattis_escapewallmaria_2,
189 kattis_escapewallmaria_3,
190 };
191
192 #[test]
193 #[should_panic(expected = "u = 1 isn't in the digraph")]
194 fn is_sink_out_of_bounds() {
195 let _ = <$type>::trivial().is_sink(1);
196 }
197
198 #[test]
199 fn max_outdegree_bang_jensen_196() {
200 assert_eq!(bang_jensen_196().max_outdegree(), 3);
201 }
202
203 #[test]
204 fn max_outdegree_bang_jensen_34() {
205 assert_eq!(bang_jensen_34().max_outdegree(), 3);
206 }
207
208 #[test]
209 fn max_outdegree_bang_jensen_94() {
210 assert_eq!(bang_jensen_94().max_outdegree(), 4);
211 }
212
213 #[test]
214 fn max_outdegree_kattis_builddeps() {
215 assert_eq!(kattis_builddeps().max_outdegree(), 3);
216 }
217
218 #[test]
219 fn max_outdegree_kattis_cantinaofbabel_1() {
220 assert_eq!(kattis_cantinaofbabel_1().max_outdegree(), 6);
221 }
222
223 #[test]
224 fn max_outdegree_kattis_cantinaofbabel_2() {
225 assert_eq!(kattis_cantinaofbabel_2().max_outdegree(), 3);
226 }
227
228 #[test]
229 fn max_outdegree_kattis_escapewallmaria_1() {
230 assert_eq!(kattis_escapewallmaria_1().max_outdegree(), 2);
231 }
232
233 #[test]
234 fn max_outdegree_kattis_escapewallmaria_2() {
235 assert_eq!(kattis_escapewallmaria_2().max_outdegree(), 2);
236 }
237
238 #[test]
239 fn max_outdegree_kattis_escapewallmaria_3() {
240 assert_eq!(kattis_escapewallmaria_3().max_outdegree(), 3);
241 }
242
243 #[test]
244 fn min_outdegree_bang_jensen_196() {
245 assert_eq!(bang_jensen_196().min_outdegree(), 1);
246 }
247
248 #[test]
249 fn min_outdegree_bang_jensen_34() {
250 assert_eq!(bang_jensen_34().min_outdegree(), 0);
251 }
252
253 #[test]
254 fn min_outdegree_bang_jensen_94() {
255 assert_eq!(bang_jensen_94().min_outdegree(), 0);
256 }
257
258 #[test]
259 fn min_outdegree_kattis_builddeps() {
260 assert_eq!(kattis_builddeps().min_outdegree(), 0);
261 }
262
263 #[test]
264 fn min_outdegree_kattis_cantinaofbabel_1() {
265 assert_eq!(kattis_cantinaofbabel_1().min_outdegree(), 1);
266 }
267
268 #[test]
269 fn min_outdegree_kattis_cantinaofbabel_2() {
270 assert_eq!(kattis_cantinaofbabel_2().min_outdegree(), 1);
271 }
272
273 #[test]
274 fn min_outdegree_kattis_escapewallmaria_1() {
275 assert_eq!(kattis_escapewallmaria_1().min_outdegree(), 0);
276 }
277
278 #[test]
279 fn min_outdegree_kattis_escapewallmaria_2() {
280 assert_eq!(kattis_escapewallmaria_2().min_outdegree(), 0);
281 }
282
283 #[test]
284 fn min_outdegree_kattis_escapewallmaria_3() {
285 assert_eq!(kattis_escapewallmaria_3().min_outdegree(), 0);
286 }
287
288 #[test]
289 fn outdegree_bang_jensen_196() {
290 let digraph = bang_jensen_196();
291
292 assert_eq!(digraph.outdegree(0), 3);
293 assert_eq!(digraph.outdegree(1), 3);
294 assert_eq!(digraph.outdegree(2), 1);
295 assert_eq!(digraph.outdegree(3), 2);
296 assert_eq!(digraph.outdegree(4), 1);
297 assert_eq!(digraph.outdegree(5), 1);
298 assert_eq!(digraph.outdegree(6), 1);
299 assert_eq!(digraph.outdegree(7), 1);
300 }
301
302 #[test]
303 fn outdegree_bang_jensen_34() {
304 let digraph = bang_jensen_34();
305
306 assert_eq!(digraph.outdegree(0), 1);
307 assert_eq!(digraph.outdegree(1), 1);
308 assert_eq!(digraph.outdegree(2), 3);
309 assert_eq!(digraph.outdegree(3), 0);
310 assert_eq!(digraph.outdegree(4), 0);
311 assert_eq!(digraph.outdegree(5), 1);
312 }
313
314 #[test]
315 fn outdegree_bang_jensen_94() {
316 let digraph = bang_jensen_94();
317
318 assert_eq!(digraph.outdegree(0), 2);
319 assert_eq!(digraph.outdegree(1), 1);
320 assert_eq!(digraph.outdegree(2), 4);
321 assert_eq!(digraph.outdegree(3), 1);
322 assert_eq!(digraph.outdegree(4), 1);
323 assert_eq!(digraph.outdegree(5), 0);
324 assert_eq!(digraph.outdegree(6), 0);
325 }
326
327 #[test]
328 fn outdegree_kattis_builddeps() {
329 let digraph = kattis_builddeps();
330
331 assert_eq!(digraph.outdegree(0), 2);
332 assert_eq!(digraph.outdegree(1), 0);
333 assert_eq!(digraph.outdegree(2), 3);
334 assert_eq!(digraph.outdegree(3), 1);
335 assert_eq!(digraph.outdegree(4), 1);
336 assert_eq!(digraph.outdegree(5), 1);
337 }
338
339 #[test]
340 fn outdegree_kattis_cantinaofbabel_1() {
341 let digraph = kattis_cantinaofbabel_1();
342
343 assert_eq!(digraph.outdegree(0), 1);
344 assert_eq!(digraph.outdegree(1), 3);
345 assert_eq!(digraph.outdegree(2), 1);
346 assert_eq!(digraph.outdegree(3), 6);
347 assert_eq!(digraph.outdegree(4), 1);
348 assert_eq!(digraph.outdegree(5), 1);
349 assert_eq!(digraph.outdegree(6), 2);
350 assert_eq!(digraph.outdegree(7), 1);
351 assert_eq!(digraph.outdegree(8), 2);
352 assert_eq!(digraph.outdegree(9), 2);
353 assert_eq!(digraph.outdegree(10), 1);
354 assert_eq!(digraph.outdegree(11), 1);
355 }
356
357 #[test]
358 fn outdegree_kattis_cantinaofbabel_2() {
359 let digraph = kattis_cantinaofbabel_2();
360
361 assert_eq!(digraph.outdegree(0), 1);
362 assert_eq!(digraph.outdegree(1), 2);
363 assert_eq!(digraph.outdegree(2), 3);
364 assert_eq!(digraph.outdegree(3), 1);
365 assert_eq!(digraph.outdegree(4), 1);
366 assert_eq!(digraph.outdegree(5), 2);
367 assert_eq!(digraph.outdegree(6), 1);
368 assert_eq!(digraph.outdegree(7), 1);
369 assert_eq!(digraph.outdegree(8), 3);
370 assert_eq!(digraph.outdegree(9), 1);
371 assert_eq!(digraph.outdegree(10), 2);
372 assert_eq!(digraph.outdegree(11), 1);
373 }
374
375 #[test]
376 fn outdegree_kattis_escapewallmaria_1() {
377 let digraph = kattis_escapewallmaria_1();
378
379 assert_eq!(digraph.outdegree(0), 0);
380 assert_eq!(digraph.outdegree(1), 0);
381 assert_eq!(digraph.outdegree(2), 0);
382 assert_eq!(digraph.outdegree(3), 0);
383 assert_eq!(digraph.outdegree(4), 0);
384 assert_eq!(digraph.outdegree(5), 2);
385 assert_eq!(digraph.outdegree(6), 1);
386 assert_eq!(digraph.outdegree(7), 0);
387 assert_eq!(digraph.outdegree(8), 0);
388 assert_eq!(digraph.outdegree(9), 2);
389 assert_eq!(digraph.outdegree(10), 0);
390 assert_eq!(digraph.outdegree(11), 0);
391 assert_eq!(digraph.outdegree(12), 0);
392 assert_eq!(digraph.outdegree(13), 2);
393 assert_eq!(digraph.outdegree(14), 0);
394 assert_eq!(digraph.outdegree(15), 0);
395 }
396
397 #[test]
398 fn outdegree_kattis_escapewallmaria_2() {
399 let digraph = kattis_escapewallmaria_2();
400
401 assert_eq!(digraph.outdegree(0), 0);
402 assert_eq!(digraph.outdegree(1), 0);
403 assert_eq!(digraph.outdegree(2), 0);
404 assert_eq!(digraph.outdegree(3), 0);
405 assert_eq!(digraph.outdegree(4), 0);
406 assert_eq!(digraph.outdegree(5), 2);
407 assert_eq!(digraph.outdegree(6), 1);
408 assert_eq!(digraph.outdegree(7), 0);
409 assert_eq!(digraph.outdegree(8), 0);
410 assert_eq!(digraph.outdegree(9), 1);
411 assert_eq!(digraph.outdegree(10), 0);
412 assert_eq!(digraph.outdegree(11), 0);
413 assert_eq!(digraph.outdegree(12), 1);
414 assert_eq!(digraph.outdegree(13), 2);
415 assert_eq!(digraph.outdegree(14), 0);
416 assert_eq!(digraph.outdegree(15), 0);
417 }
418
419 #[test]
420 fn outdegree_kattis_escapewallmaria_3() {
421 let digraph = kattis_escapewallmaria_3();
422
423 assert_eq!(digraph.outdegree(0), 0);
424 assert_eq!(digraph.outdegree(1), 2);
425 assert_eq!(digraph.outdegree(2), 2);
426 assert_eq!(digraph.outdegree(3), 0);
427 assert_eq!(digraph.outdegree(4), 0);
428 assert_eq!(digraph.outdegree(5), 3);
429 assert_eq!(digraph.outdegree(6), 2);
430 assert_eq!(digraph.outdegree(7), 0);
431 assert_eq!(digraph.outdegree(8), 0);
432 assert_eq!(digraph.outdegree(9), 2);
433 assert_eq!(digraph.outdegree(10), 0);
434 assert_eq!(digraph.outdegree(11), 0);
435 assert_eq!(digraph.outdegree(12), 1);
436 assert_eq!(digraph.outdegree(13), 2);
437 assert_eq!(digraph.outdegree(14), 0);
438 assert_eq!(digraph.outdegree(15), 0);
439 }
440
441 #[test]
442 #[should_panic(expected = "u = 1 isn't in the digraph")]
443 fn outdegree_out_of_bounds() {
444 let _ = <$type>::trivial().outdegree(1);
445 }
446 };
447}
448
449#[cfg(test)]
450mod tests {
451 use {
452 super::*,
453 std::collections::BTreeSet,
454 };
455
456 #[test]
457 fn is_sink() {
458 struct AdjacencyList {
459 arcs: Vec<BTreeSet<usize>>,
460 }
461
462 impl Outdegree for AdjacencyList {
463 fn outdegree(&self, u: usize) -> usize {
464 self.arcs.get(u).map_or(0, BTreeSet::len)
465 }
466 }
467
468 let digraph = AdjacencyList {
469 arcs: vec![
470 BTreeSet::from([1, 2]),
471 BTreeSet::new(),
472 BTreeSet::new(),
473 BTreeSet::from([0]),
474 ],
475 };
476
477 assert!(!digraph.is_sink(0));
478 assert!(digraph.is_sink(1));
479 assert!(digraph.is_sink(2));
480 assert!(!digraph.is_sink(3));
481 }
482}