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 F: FnMut(&mut Prospect<V>, &mut CPT<V>) -> (),
99 {
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 }
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 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 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 F: FnMut(&mut MyOpinions<V>, &mut Decision<V>),
199 {
201 self.clear();
202 f(&mut self.ops, &mut self.decision);
203 }
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 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}