argumentation_bipolar/
flatten.rs1use crate::derived::closed_attacks;
16use crate::framework::BipolarFramework;
17use argumentation::ArgumentationFramework;
18use std::fmt::Debug;
19use std::hash::Hash;
20
21pub fn flatten<A>(
30 framework: &BipolarFramework<A>,
31) -> Result<ArgumentationFramework<A>, argumentation::Error>
32where
33 A: Clone + Eq + Hash + Debug,
34{
35 let mut af = ArgumentationFramework::new();
36 for arg in framework.arguments() {
37 af.add_argument(arg.clone());
38 }
39 for (attacker, target) in closed_attacks(framework) {
40 af.add_attack(&attacker, &target)?;
41 }
42 Ok(af)
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48
49 #[test]
50 fn empty_bipolar_flattens_to_empty_dung() {
51 let bf: BipolarFramework<&str> = BipolarFramework::new();
52 let af = flatten(&bf).unwrap();
53 assert_eq!(af.len(), 0);
54 }
55
56 #[test]
57 fn direct_attack_survives_flattening() {
58 let mut bf = BipolarFramework::new();
59 bf.add_attack("a", "b");
60 let af = flatten(&bf).unwrap();
61 assert_eq!(af.len(), 2);
62 assert_eq!(af.attackers(&"b").len(), 1);
63 }
64
65 #[test]
66 fn supported_attack_becomes_direct_in_flat_framework() {
67 let mut bf = BipolarFramework::new();
69 bf.add_support("a", "x").unwrap();
70 bf.add_attack("x", "b");
71 let af = flatten(&bf).unwrap();
72 let attackers_of_b: Vec<&&str> = af.attackers(&"b").into_iter().collect();
73 assert_eq!(attackers_of_b.len(), 2);
74 assert!(attackers_of_b.contains(&&"a"));
75 assert!(attackers_of_b.contains(&&"x"));
76 }
77
78 #[test]
79 fn unrelated_arguments_appear_in_flattened_framework() {
80 let mut bf = BipolarFramework::new();
82 bf.add_argument("a");
83 bf.add_argument("b");
84 let af = flatten(&bf).unwrap();
85 assert_eq!(af.len(), 2);
86 assert!(af.attackers(&"a").is_empty());
87 assert!(af.attackers(&"b").is_empty());
88 }
89}