argumentation_values/
acceptance.rs1use crate::error::Error;
15use crate::framework::ValueBasedFramework;
16use crate::types::{Audience, Value};
17use std::hash::Hash;
18
19pub const ENUMERATION_LIMIT: usize = 6;
22
23pub fn subjectively_accepted<A>(
30 vaf: &ValueBasedFramework<A>,
31 arg: &A,
32) -> Result<bool, Error>
33where
34 A: Clone + Eq + Hash + Ord + std::fmt::Debug,
35{
36 let values: Vec<Value> = vaf
37 .value_assignment()
38 .distinct_values()
39 .into_iter()
40 .cloned()
41 .collect();
42
43 if values.len() > ENUMERATION_LIMIT {
44 return Err(Error::AudienceTooLarge {
45 values: values.len(),
46 limit: ENUMERATION_LIMIT,
47 });
48 }
49
50 for perm in permutations(&values) {
51 let audience = Audience::total(perm);
52 if vaf.accepted_for(&audience, arg)? {
53 return Ok(true);
54 }
55 }
56 Ok(false)
57}
58
59pub fn objectively_accepted<A>(
62 vaf: &ValueBasedFramework<A>,
63 arg: &A,
64) -> Result<bool, Error>
65where
66 A: Clone + Eq + Hash + Ord + std::fmt::Debug,
67{
68 let values: Vec<Value> = vaf
69 .value_assignment()
70 .distinct_values()
71 .into_iter()
72 .cloned()
73 .collect();
74
75 if values.len() > ENUMERATION_LIMIT {
76 return Err(Error::AudienceTooLarge {
77 values: values.len(),
78 limit: ENUMERATION_LIMIT,
79 });
80 }
81
82 for perm in permutations(&values) {
83 let audience = Audience::total(perm);
84 if !vaf.accepted_for(&audience, arg)? {
85 return Ok(false);
86 }
87 }
88 Ok(true)
89}
90
91fn permutations<T: Clone>(items: &[T]) -> Vec<Vec<T>> {
94 let mut result = Vec::new();
95 let mut working: Vec<T> = items.to_vec();
96 permute_recursive(&mut working, 0, &mut result);
97 result
98}
99
100fn permute_recursive<T: Clone>(items: &mut [T], start: usize, out: &mut Vec<Vec<T>>) {
101 if start == items.len() {
102 out.push(items.to_vec());
103 return;
104 }
105 for i in start..items.len() {
106 items.swap(start, i);
107 permute_recursive(items, start + 1, out);
108 items.swap(start, i);
109 }
110}
111
112#[cfg(test)]
113mod tests {
114 use super::*;
115 use crate::types::ValueAssignment;
116 use argumentation::ArgumentationFramework;
117
118 fn hal_carla() -> ValueBasedFramework<&'static str> {
119 let mut base = ArgumentationFramework::new();
120 for arg in ["h1", "c1", "h2", "c2"] {
121 base.add_argument(arg);
122 }
123 base.add_attack(&"h1", &"c1").unwrap();
124 base.add_attack(&"c1", &"h1").unwrap();
125 base.add_attack(&"c2", &"h2").unwrap();
126 base.add_attack(&"h2", &"c1").unwrap();
127
128 let mut values = ValueAssignment::new();
129 values.promote("h1", Value::new("life"));
130 values.promote("c1", Value::new("property"));
131 values.promote("h2", Value::new("fairness"));
132 values.promote("c2", Value::new("life"));
133
134 ValueBasedFramework::new(base, values)
135 }
136
137 #[test]
138 fn c2_objectively_accepted() {
139 let vaf = hal_carla();
140 assert!(objectively_accepted(&vaf, &"c2").unwrap());
142 }
143
144 #[test]
145 fn h1_subjectively_but_not_objectively_accepted() {
146 let vaf = hal_carla();
147 assert!(subjectively_accepted(&vaf, &"h1").unwrap());
150 assert!(!objectively_accepted(&vaf, &"h1").unwrap());
151 }
152
153 #[test]
154 fn c1_subjectively_but_not_objectively_accepted() {
155 let vaf = hal_carla();
156 assert!(subjectively_accepted(&vaf, &"c1").unwrap());
158 assert!(!objectively_accepted(&vaf, &"c1").unwrap());
159 }
160
161 #[test]
162 fn audience_too_large_returns_error() {
163 let mut base = ArgumentationFramework::new();
165 for arg in ["a", "b", "c", "d", "e", "f", "g"] {
166 base.add_argument(arg);
167 }
168 let mut values = ValueAssignment::new();
169 for (i, name) in ["v1", "v2", "v3", "v4", "v5", "v6", "v7"].iter().enumerate() {
170 let arg = ["a", "b", "c", "d", "e", "f", "g"][i];
171 values.promote(arg, Value::new(*name));
172 }
173 let vaf = ValueBasedFramework::new(base, values);
174 let result = subjectively_accepted(&vaf, &"a");
175 assert!(matches!(
176 result,
177 Err(Error::AudienceTooLarge { values: 7, limit: 6 })
178 ));
179 }
180
181 #[test]
182 fn permutations_of_three_yields_six() {
183 let perms = permutations(&[1, 2, 3]);
184 assert_eq!(perms.len(), 6);
185 }
186
187 #[test]
188 fn permutations_of_zero_yields_one_empty() {
189 let perms: Vec<Vec<i32>> = permutations(&[]);
190 assert_eq!(perms.len(), 1);
191 assert!(perms[0].is_empty());
192 }
193}