base/
agent.rs

1use num_traits::Float;
2use rand_distr::{Distribution, Exp1, Open01, StandardNormal};
3use std::{
4    array,
5    collections::{BTreeMap, BTreeSet},
6    fmt::Debug,
7};
8use tracing::*;
9
10use crate::{
11    decision::{Prospect, CPT},
12    info::Info,
13    opinion::{DeducedOpinions, MyFloat, MyOpinions, MyOpinionsUpd, Trusts},
14};
15
16#[derive(Debug)]
17pub struct BehaviorByInfo {
18    pub sharing: bool,
19    pub first_access: bool,
20}
21
22#[derive(Debug, Default)]
23pub struct Agent<V> {
24    ops: MyOpinions<V>,
25    infos_accessed: BTreeSet<usize>,
26    decision: Decision<V>,
27}
28
29#[derive(Debug, Default)]
30pub struct Decision<V> {
31    cpt: CPT<V>,
32    prospect: Prospect<V>,
33    selfish_status: DelayActionStatus,
34    sharing_statuses: BTreeMap<usize, ActionStatus>,
35    delay_selfish: u32,
36}
37
38impl<V> Decision<V> {
39    fn values_selfish(&self, ded: &DeducedOpinions<V>) -> [V; 2]
40    where
41        V: MyFloat,
42    {
43        let p_theta = ded.p_theta();
44        info!(target: "    TH", P = ?p_theta);
45        let values: [V; 2] =
46            array::from_fn(|i| self.cpt.valuate(&self.prospect.selfish[i], &p_theta));
47        info!(target: "     X", V = ?values);
48        values
49    }
50
51    fn try_decide_selfish(&mut self, upd: &MyOpinionsUpd<V>)
52    where
53        V: MyFloat,
54    {
55        if !self.selfish_status.is_done() {
56            upd.decide1(|ded| {
57                self.selfish_status
58                    .decide(self.values_selfish(ded), self.delay_selfish);
59                info!(target: "selfsh", status = ?self.selfish_status);
60            });
61        }
62    }
63
64    fn predict(&self, upd: &mut MyOpinionsUpd<V>)
65    where
66        V: MyFloat,
67    {
68        upd.decide2(|_, _| true);
69    }
70
71    fn try_decide_sharing(&mut self, upd: &mut MyOpinionsUpd<V>, info_idx: usize) -> bool
72    where
73        V: MyFloat,
74    {
75        let sharing_status = self.sharing_statuses.entry(info_idx).or_default();
76        if sharing_status.is_done() {
77            false
78        } else {
79            upd.decide2(|p_a_thetad, pred_p_a_thetad| {
80                info!(target: "   THd", P = ?p_a_thetad);
81                info!(target: "  ~THd", P = ?pred_p_a_thetad);
82
83                let values = [
84                    self.cpt.valuate(&self.prospect.sharing[0], p_a_thetad),
85                    self.cpt.valuate(&self.prospect.sharing[1], pred_p_a_thetad),
86                ];
87                info!(target: "     Y", V = ?values);
88                sharing_status.decide(values);
89                info!(target: "sharng", status = ?sharing_status);
90                sharing_status.is_done()
91            })
92        }
93    }
94
95    pub fn reset<F>(&mut self, delay_selfish: u32, mut f: F)
96    where
97        // V: Debug + Float,
98        F: FnMut(&mut Prospect<V>, &mut CPT<V>) -> (),
99        //     Open01: Distribution<V>,
100        //     Standard: Distribution<V>,
101        //     StandardNormal: Distribution<V>,
102        //     Exp1: Distribution<V>,
103    {
104        self.selfish_status.reset();
105        self.sharing_statuses.clear();
106        self.delay_selfish = delay_selfish;
107        f(&mut self.prospect, &mut self.cpt);
108        // self.prospect.reset(x0, x1, y);
109        // self.cpt.reset()
110        // param.reset(self, rng);
111    }
112}
113
114#[derive(Default, Debug)]
115enum ActionStatus {
116    #[default]
117    NotYet,
118    Done,
119}
120
121impl ActionStatus {
122    fn is_done(&self) -> bool {
123        matches!(self, Self::Done)
124    }
125
126    /// Index 0 of `values` indicates 'do not perform this action', and index 1 indicates 'perform this action.'
127    fn decide<V: Float>(&mut self, values: [V; 2]) {
128        if values[0] < values[1] {
129            *self = Self::Done;
130        }
131    }
132}
133
134#[derive(Default, Debug)]
135enum DelayActionStatus {
136    #[default]
137    NotYet,
138    Willing(u32),
139    Done,
140}
141
142impl DelayActionStatus {
143    fn reset(&mut self) {
144        *self = Self::NotYet;
145    }
146
147    #[inline]
148    fn is_willing(&self) -> bool {
149        matches!(self, Self::Willing(_))
150    }
151
152    #[inline]
153    fn is_done(&self) -> bool {
154        matches!(self, Self::Done)
155    }
156
157    /// Index 0 of `values` indicates 'do not perform this action', and index 1 indicates 'perform this action.'
158    fn decide<V: Float>(&mut self, values: [V; 2], delay: u32) {
159        let perform = values[0] < values[1];
160        match self {
161            Self::NotYet if perform => {
162                *self = Self::Willing(delay);
163            }
164            Self::Willing(_) if !perform => {
165                *self = Self::NotYet;
166            }
167            _ => {}
168        }
169    }
170
171    fn progress(&mut self) -> bool {
172        match self {
173            Self::Willing(0) => {
174                *self = Self::Done;
175                true
176            }
177            Self::Willing(r) => {
178                *r -= 1;
179                false
180            }
181            _ => false,
182        }
183    }
184}
185
186impl<V> Agent<V> {
187    pub fn ops(&self) -> &MyOpinions<V> {
188        &self.ops
189    }
190
191    fn clear(&mut self) {
192        self.infos_accessed.clear();
193    }
194
195    pub fn reset<F>(&mut self, mut f: F)
196    where
197        // V: Float + Debug, // P: Reset<Self>,
198        F: FnMut(&mut MyOpinions<V>, &mut Decision<V>),
199        // F2: FnMut(&mut Decision<V>),
200    {
201        self.clear();
202        f(&mut self.ops, &mut self.decision);
203        // self.ops.reset();
204        // self.decision.reset(delay_selfish, x0, x1, y)
205        // param.reset(self, rng);
206        // f(self);
207    }
208
209    pub fn is_willing_selfish(&self) -> bool {
210        self.decision.selfish_status.is_willing()
211    }
212
213    pub fn progress_selfish_status(&mut self) -> bool {
214        let p = self.decision.selfish_status.progress();
215        info!(target: "selfsh", status = ?self.decision.selfish_status);
216        p
217    }
218
219    pub fn read_info(&mut self, info: &Info<V>, trusts: Trusts<V>) -> BehaviorByInfo
220    where
221        V: MyFloat,
222        StandardNormal: Distribution<V>,
223        Exp1: Distribution<V>,
224        Open01: Distribution<V>,
225    {
226        let first_access = self.infos_accessed.insert(info.idx);
227
228        // compute values of prospects
229        let mut upd = self.ops.receive(info.content(), trusts);
230        self.decision.try_decide_selfish(&upd);
231        let sharing = self.decision.try_decide_sharing(&mut upd, info.idx);
232
233        BehaviorByInfo {
234            sharing,
235            first_access,
236        }
237    }
238
239    pub fn set_info_opinions(&mut self, info: &Info<V>, trusts: Trusts<V>)
240    where
241        V: MyFloat,
242        StandardNormal: Distribution<V>,
243        Exp1: Distribution<V>,
244        Open01: Distribution<V>,
245    {
246        let mut upd = self.ops.receive(info.content(), trusts);
247        self.decision.try_decide_selfish(&upd);
248        self.decision.predict(&mut upd);
249    }
250}
251
252#[cfg(test)]
253mod tests {
254    use super::{ActionStatus, DelayActionStatus};
255
256    #[test]
257    fn test_action_status() {
258        let mut s = ActionStatus::default();
259        assert!(matches!(s, ActionStatus::NotYet));
260        s.decide([1.0, 0.0]);
261        assert!(matches!(s, ActionStatus::NotYet));
262        s.decide([0.0, 1.0]);
263        assert!(s.is_done());
264
265        let mut s = DelayActionStatus::default();
266        assert!(matches!(s, DelayActionStatus::NotYet));
267        s.decide([0.0, 1.0], 1);
268        assert!(matches!(s, DelayActionStatus::Willing(1)));
269        s.decide([0.0, 1.0], 1);
270        assert!(matches!(s, DelayActionStatus::Willing(1)));
271        s.progress();
272        assert!(matches!(s, DelayActionStatus::Willing(0)));
273        s.progress();
274        assert!(s.is_done());
275
276        s.reset();
277        assert!(matches!(s, DelayActionStatus::NotYet));
278        s.decide([0.0, 1.0], 2);
279        s.progress();
280        assert!(matches!(s, DelayActionStatus::Willing(1)));
281        s.progress();
282        assert!(matches!(s, DelayActionStatus::Willing(0)));
283        s.decide([1.0, 0.0], 2);
284        s.progress();
285        assert!(matches!(s, DelayActionStatus::NotYet));
286        s.reset();
287        s.decide([1.0, 0.0], 1);
288        s.progress();
289        assert!(matches!(s, DelayActionStatus::NotYet));
290        s.decide([0.0, 1.0], 1);
291        s.progress();
292        assert!(matches!(s, DelayActionStatus::Willing(0)));
293        s.decide([0.0, 1.0], 1);
294        assert!(matches!(s, DelayActionStatus::Willing(0)));
295        s.progress();
296        assert!(s.is_done());
297    }
298}