argumentation/semantics/
ideal.rs1use super::subset_enum::subset_from_bits;
5use crate::framework::ArgumentationFramework;
6use std::collections::HashSet;
7use std::hash::Hash;
8
9impl<A: Clone + Eq + Hash + Ord> ArgumentationFramework<A> {
10 pub fn ideal_extension(&self) -> Result<HashSet<A>, crate::Error> {
18 let preferred = self.preferred_extensions()?;
19 if preferred.is_empty() {
20 return Ok(HashSet::new());
21 }
22 let mut intersection: HashSet<A> = preferred[0].clone();
23 for ext in &preferred[1..] {
24 intersection = intersection.intersection(ext).cloned().collect();
25 }
26 let mut args: Vec<A> = intersection.into_iter().collect();
30 args.sort();
31 let n = args.len();
32 let mut best: HashSet<A> = HashSet::new();
33 for bits in 0u64..(1u64 << n) {
34 let s = subset_from_bits(&args, bits);
35 if s.len() <= best.len() {
36 continue;
37 }
38 if self.is_admissible(&s) {
39 best = s;
40 }
41 }
42 Ok(best)
43 }
44}
45
46#[cfg(test)]
47mod tests {
48 use super::*;
49
50 #[test]
51 fn ideal_of_figure_1_is_ac() {
52 let mut af = ArgumentationFramework::new();
53 af.add_argument("a");
54 af.add_argument("b");
55 af.add_argument("c");
56 af.add_attack(&"a", &"b").unwrap();
57 af.add_attack(&"b", &"c").unwrap();
58 let ideal = af.ideal_extension().unwrap();
59 let expected: HashSet<&str> = ["a", "c"].into_iter().collect();
60 assert_eq!(ideal, expected);
61 }
62
63 #[test]
64 fn ideal_of_mutual_attack_is_empty() {
65 let mut af = ArgumentationFramework::new();
66 af.add_argument("a");
67 af.add_argument("b");
68 af.add_attack(&"a", &"b").unwrap();
69 af.add_attack(&"b", &"a").unwrap();
70 assert!(af.ideal_extension().unwrap().is_empty());
71 }
72}