qualia_core_db/modalities/argumentation/
vaf.rs1use super::ArgumentationFramework;
8use std::collections::{HashMap, HashSet};
9
10#[derive(Debug, Clone)]
12pub struct ValueArgumentationFramework {
13 pub af: ArgumentationFramework,
14 pub value_of: HashMap<u64, u64>,
16 pub value_rank: HashMap<u64, u32>,
18}
19
20impl ValueArgumentationFramework {
21 pub fn new(af: ArgumentationFramework) -> Self {
22 Self {
23 af,
24 value_of: HashMap::new(),
25 value_rank: HashMap::new(),
26 }
27 }
28
29 pub fn set_value(&mut self, arg: u64, value: u64) {
31 self.value_of.insert(arg, value);
32 }
33
34 pub fn set_rank(&mut self, value: u64, rank: u32) {
36 self.value_rank.insert(value, rank);
37 }
38
39 fn rank_of_arg(&self, arg: u64) -> u32 {
40 self.value_of
41 .get(&arg)
42 .and_then(|v| self.value_rank.get(v))
43 .copied()
44 .unwrap_or(0)
45 }
46
47 pub fn defeats(&self, attacker: u64, target: u64) -> bool {
51 self.rank_of_arg(attacker) >= self.rank_of_arg(target)
52 }
53
54 pub fn defeat_framework(&self) -> ArgumentationFramework {
56 let mut out = ArgumentationFramework::new();
57 for arg in self.af.arguments.values() {
58 out.add_argument(arg.clone());
59 }
60 for atk in &self.af.attacks {
61 if self.defeats(atk.attacker, atk.target) {
62 out.add_attack(atk.clone());
63 }
64 }
65 out
66 }
67
68 pub fn grounded_extension(&self) -> HashSet<u64> {
70 self.defeat_framework().grounded_extension()
71 }
72
73 pub fn preferred_extensions(&self) -> Vec<HashSet<u64>> {
75 self.defeat_framework().preferred_extensions()
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::super::{Argument, Attack, AttackType};
82 use super::*;
83 use crate::NQuin;
84
85 fn arg(id: u64) -> Argument {
86 Argument::new(id, String::new(), Vec::new(), NQuin::default())
87 }
88 fn atk(a: u64, b: u64) -> Attack {
89 Attack {
90 attacker: a,
91 target: b,
92 attack_type: AttackType::Rebuttal,
93 strength: 1.0,
94 }
95 }
96
97 #[test]
98 fn higher_value_argument_survives_a_mutual_attack() {
99 let mut af = ArgumentationFramework::new();
101 af.add_argument(arg(1));
102 af.add_argument(arg(2));
103 af.add_attack(atk(1, 2));
104 af.add_attack(atk(2, 1));
105 assert!(
106 af.grounded_extension().is_empty(),
107 "plain AF: mutual attack → no acceptance"
108 );
109
110 let mut vaf = ValueArgumentationFramework::new(af);
112 let rights = crate::q_hash("value:nonDerogableRight");
113 let convenience = crate::q_hash("value:convenience");
114 vaf.set_value(1, rights);
115 vaf.set_value(2, convenience);
116 vaf.set_rank(rights, 10);
117 vaf.set_rank(convenience, 1);
118
119 assert!(vaf.defeats(1, 2));
121 assert!(!vaf.defeats(2, 1));
122 let g = vaf.grounded_extension();
123 assert!(
124 g.contains(&1) && !g.contains(&2),
125 "the rights-grounded argument prevails"
126 );
127 }
128}