v2/
config.rs

1use std::{
2    fmt::Debug,
3    fs::File,
4    path::{Path, PathBuf},
5};
6
7use anyhow::{bail, ensure, Context};
8use base::opinion::{MyFloat, Phi, Psi, B, H};
9use graph_lib::prelude::{Graph, GraphB};
10use input::format::DataFormat;
11use itertools::Itertools;
12use rand_distr::{Distribution, Open01};
13use serde::Deserialize;
14use subjective_logic::{
15    domain::{Domain, Keys},
16    errors::{check_unit_interval, InvalidValueError},
17    iter::FromFn,
18    marr_d1, marr_d2,
19    mul::labeled::{OpinionD1, SimplexD1},
20    multi_array::labeled::{MArrD1, MArrD2},
21};
22
23use crate::{
24    exec::Exec,
25    io::{read_csv, MyPath},
26    parameter::{
27        ConditionSampler, ConditionSamples, CptRecord, CptSamples, InformationSamples,
28        InformingParams, InitialStates, OpinionSamples, ProbabilitySamples, ProspectRecord,
29        ProspectSamples, SamplerOption, SharerTrustSamples, SimplexContainer, SimplexIndexed,
30        SupportLevelTable, UncertaintySamples,
31    },
32};
33
34pub struct Config<V>
35where
36    V: MyFloat,
37    Open01: Distribution<V>,
38{
39    agent: MyPath<AgentConfig<V>>,
40    strategy: MyPath<StrategyConfig<V>>,
41    network: MyPath<NetworkConfig<V>>,
42}
43
44impl<V> Config<V>
45where
46    V: MyFloat + for<'a> Deserialize<'a>,
47    Open01: Distribution<V>,
48{
49    pub fn try_new<P: AsRef<Path>>(network: P, agent: P, strategy: P) -> anyhow::Result<Self> {
50        Ok(Self {
51            agent: agent.as_ref().into(),
52            strategy: strategy.as_ref().into(),
53            network: network.as_ref().into(),
54        })
55    }
56
57    pub fn into_exec(self, enable_inhibition: bool, delay_selfish: u32) -> anyhow::Result<Exec<V>>
58    where
59        V: MyFloat + for<'a> Deserialize<'a>,
60        Open01: Distribution<V>,
61    {
62        let Self {
63            agent,
64            strategy,
65            network,
66        } = self;
67
68        let DeNetworkConfig {
69            graph,
70            fnum_agents,
71            mean_degree,
72            community_psi1,
73        } = network.de("")?;
74
75        let DeAgentConfig {
76            probabilities,
77            sharer_trust,
78            prospect,
79            cpt,
80            opinion,
81        } = agent.de("")?;
82
83        let DeStrategyConfig {
84            informing,
85            information,
86        } = strategy.de("")?;
87
88        Ok(Exec {
89            enable_inhibition,
90            delay_selfish,
91            graph,
92            fnum_agents,
93            mean_degree,
94            sharer_trust,
95            opinion,
96            information,
97            informing,
98            community_psi1,
99            probabilities,
100            prospect,
101            cpt,
102        })
103    }
104}
105
106trait DeserializeAt<T> {
107    fn de<P: AsRef<Path>>(self, at: P) -> anyhow::Result<T>;
108}
109
110#[derive(Deserialize)]
111#[serde(bound(deserialize = "V: serde::Deserialize<'de>"))]
112pub struct AgentConfig<V>
113where
114    V: MyFloat,
115    Open01: Distribution<V>,
116{
117    probabilities: MyPath<ProbabilitySamples<V>>,
118    sharer_trust: MyPath<SharerTrustSamples<V>>,
119    prospect: MyPath<Vec<ProspectRecord<V>>>,
120    cpt: MyPath<Vec<CptRecord<V>>>,
121    initial_states: MyPath<InitialStates<V>>,
122    condition: MyPath<ConditionConfig<V>>,
123    uncertainty: MyPath<UncertaintyConfig<V>>,
124}
125
126struct DeAgentConfig<V>
127where
128    V: MyFloat,
129    Open01: Distribution<V>,
130{
131    probabilities: ProbabilitySamples<V>,
132    sharer_trust: SharerTrustSamples<V>,
133    prospect: ProspectSamples<V>,
134    cpt: CptSamples<V>,
135    opinion: OpinionSamples<V>,
136}
137
138impl<V> DeserializeAt<DeAgentConfig<V>> for MyPath<AgentConfig<V>>
139where
140    V: MyFloat + for<'a> Deserialize<'a>,
141    Open01: Distribution<V>,
142{
143    fn de<P: AsRef<Path>>(self, parent: P) -> anyhow::Result<DeAgentConfig<V>> {
144        let child = self.verified_child(&parent)?;
145        let agent = self.parse_at(&parent, DataFormat::de)?;
146
147        let initial_states = agent.initial_states.parse_at(&child, DataFormat::de)?;
148        Ok(DeAgentConfig {
149            probabilities: agent.probabilities.parse_at(&child, DataFormat::de)?,
150            sharer_trust: agent.sharer_trust.parse_at(&child, DataFormat::de)?,
151            prospect: ProspectSamples(agent.prospect.parse_at(&child, read_csv)?),
152            cpt: CptSamples(agent.cpt.parse_at(&child, read_csv)?),
153            opinion: OpinionSamples {
154                initial_opinions: initial_states.initial_opinions,
155                initial_base_rates: initial_states.initial_base_rates,
156                condition: agent.condition.de(&child)?,
157                uncertainty: agent.uncertainty.de(&child)?,
158            },
159        })
160    }
161}
162
163#[derive(Debug, Deserialize)]
164struct StrategyConfig<V>
165where
166    V: MyFloat,
167    Open01: Distribution<V>,
168{
169    informing: MyPath<InformingParams<V>>,
170    information: InformationConfig<V>,
171}
172
173struct DeStrategyConfig<V> {
174    informing: InformingParams<V>,
175    information: InformationSamples<V>,
176}
177
178impl<V> DeserializeAt<DeStrategyConfig<V>> for MyPath<StrategyConfig<V>>
179where
180    V: MyFloat + for<'a> Deserialize<'a>,
181    Open01: Distribution<V>,
182{
183    fn de<P: AsRef<Path>>(self, parent: P) -> anyhow::Result<DeStrategyConfig<V>> {
184        let child = self.verified_child(&parent)?;
185        let strategy = self.parse_at(&parent, DataFormat::de)?;
186
187        Ok(DeStrategyConfig {
188            informing: strategy.informing.parse_at(&child, DataFormat::de)?,
189            information: strategy.information.de(&child)?,
190        })
191    }
192}
193
194#[derive(Debug, Deserialize)]
195struct InformationConfig<V>
196where
197    V: MyFloat,
198    Open01: Distribution<V>,
199{
200    /// also used for $M$ in correction
201    misinfo: MyPath<Vec<OpinionRecord<V>>>,
202    correction: MyPath<Vec<OpinionRecord<V>>>,
203    observation: MyPath<Vec<OpinionRecord<V>>>,
204    inhibition: MyPath<Vec<InhibitionRecord<V>>>,
205}
206
207impl<V> DeserializeAt<InformationSamples<V>> for InformationConfig<V>
208where
209    V: MyFloat + for<'a> Deserialize<'a>,
210    Open01: Distribution<V>,
211{
212    fn de<P: AsRef<Path>>(self, at: P) -> anyhow::Result<InformationSamples<V>> {
213        Ok(InformationSamples {
214            misinfo: self
215                .misinfo
216                .parse_at(&at, read_csv)?
217                .into_iter()
218                .map(OpinionRecord::try_into)
219                .try_collect()?,
220            correction: self
221                .correction
222                .parse_at(&at, read_csv)?
223                .into_iter()
224                .map(OpinionRecord::try_into)
225                .try_collect()?,
226            observation: self
227                .observation
228                .parse_at(&at, read_csv)?
229                .into_iter()
230                .map(OpinionRecord::try_into)
231                .try_collect()?,
232            inhibition: self
233                .inhibition
234                .parse_at(&at, read_csv)?
235                .into_iter()
236                .map(InhibitionRecord::try_into)
237                .try_collect()?,
238        })
239    }
240}
241
242#[derive(Debug, Deserialize)]
243pub struct NetworkConfig<V> {
244    path: PathBuf,
245    graph: MyPath<GraphB>,
246    directed: bool,
247    transposed: bool,
248    community: MyPath<Vec<SupportLevelRecord<V>>>,
249}
250
251struct DeNetworkConfig<V> {
252    graph: GraphB,
253    fnum_agents: V,
254    mean_degree: V,
255    community_psi1: SupportLevelTable<V>,
256}
257
258impl<V> DeserializeAt<DeNetworkConfig<V>> for MyPath<NetworkConfig<V>>
259where
260    V: MyFloat + for<'a> Deserialize<'a>,
261{
262    fn de<P: AsRef<Path>>(self, at: P) -> anyhow::Result<DeNetworkConfig<V>> {
263        let child = self.verified_child(&at)?;
264        let network = self.parse_at(&at, DataFormat::de)?;
265        let child = child.join(network.path);
266
267        let graph = network.graph.parse_at(&child, |p| {
268            let builder = graph_lib::io::ParseBuilder::new(
269                File::open(p)?,
270                graph_lib::io::DataFormat::EdgeList,
271            );
272            if network.directed {
273                if network.transposed {
274                    Ok(GraphB::Di(builder.transpose().parse()?))
275                } else {
276                    Ok(GraphB::Di(builder.parse()?))
277                }
278            } else {
279                Ok(GraphB::Ud(builder.parse()?))
280            }
281        })?;
282        let fnum_agents = V::from_usize(graph.node_count()).unwrap();
283        let mean_degree = V::from_usize(graph.edge_count()).unwrap() / fnum_agents;
284        let records = network.community.parse_at(&child, read_csv)?;
285        let community =
286            SupportLevelTable::from_vec(records.into_iter().map(|r| r.level).collect_vec());
287        Ok(DeNetworkConfig {
288            graph,
289            fnum_agents,
290            mean_degree,
291            community_psi1: community,
292        })
293    }
294}
295
296#[derive(Debug, serde::Deserialize)]
297pub struct SupportLevelRecord<V> {
298    level: V,
299}
300
301#[derive(Debug, serde::Deserialize)]
302#[serde(rename_all = "lowercase")]
303enum ConditionOption<V> {
304    Import(MyPath<Vec<ConditionRecord<V>>>),
305    Generate(Vec<Vec<SimplexOption<V>>>),
306}
307
308#[derive(Debug, serde::Deserialize)]
309#[serde(rename_all = "lowercase")]
310enum SimplexOption<V> {
311    B(usize, SamplerOption<V>),
312    U(SamplerOption<V>),
313}
314
315impl<V, D0, D1> DeserializeAt<ConditionSampler<D0, D1, V>> for ConditionOption<V>
316where
317    V: MyFloat + for<'a> Deserialize<'a>,
318    Open01: Distribution<V>,
319    D0: Domain<Idx: Debug> + Keys<D0::Idx>,
320    D1: Domain<Idx: Debug + From<usize> + Copy> + Keys<D1::Idx>,
321{
322    fn de<P>(self, at: P) -> anyhow::Result<ConditionSampler<D0, D1, V>>
323    where
324        P: AsRef<Path>,
325    {
326        match self {
327            ConditionOption::Import(c) => Ok(ConditionSampler::Array(
328                c.parse_at(at, read_csv)?
329                    .into_iter()
330                    .map(ConditionRecord::try_into)
331                    .try_collect()?,
332            )),
333            ConditionOption::Generate(pss) => {
334                ensure!(D0::LEN == pss.len(), "few conditional opinion(s)");
335                let containers = pss.into_iter().map(|ps| {
336                    let mut b_check = MArrD1::<D1, bool>::from_fn(|_| false);
337                    let mut u_check = false;
338                    let mut sampler = None;
339                    let mut fixed = Vec::new();
340                    for p in ps {
341                        match p {
342                            SimplexOption::B(i, so) => {
343                                ensure!(!b_check[i.into()], "b({i}) is duplicated");
344                                b_check[i.into()] = true;
345                                match so {
346                                    SamplerOption::Single(v) => fixed.push(SimplexIndexed::B(i.into(), v)),
347                                    _ => {
348                                        ensure!(sampler.is_none(), "at most one sampler is avilable");
349                                        sampler = Some(SimplexIndexed::B(i.into(), so.into()));
350                                    },
351                                }
352                            }
353                            SimplexOption::U(so) => {
354                                ensure!(!u_check, "u is duplicated");
355                                u_check = true;
356                                match so {
357                                    SamplerOption::Single(v) => fixed.push(SimplexIndexed::U(v)),
358                                    _ => {
359                                        ensure!(sampler.is_none(), "at most one sampler is avilable");
360                                        sampler = Some(SimplexIndexed::U(so.into()));
361                                    },
362                                }
363                            }
364                        }
365                    }
366                    let b_remain = D1::keys()
367                        .filter_map(|i| if b_check[i] { None } else { Some(i) })
368                        .collect_vec();
369                    let auto = match b_remain.len() {
370                        0 => {
371                            ensure!(!u_check, "one belief or uncertainty should be unset");
372                            SimplexIndexed::U(())
373                        }
374                        1 => {
375                            ensure!(u_check, "uncertainty should be set");
376                            SimplexIndexed::B(b_remain[0], ())
377                        }
378                        _ => {
379                            if u_check {
380                                bail!(
381                                    "{} belief(s) of indexes {:?} should be set",
382                                    b_remain.len() - 1,
383                                    b_remain
384                                );
385                            } else {
386                                bail!("{} belief(s) or {} belief(s) and uncertainty should be set from indexes {:?}",
387                                b_remain.len(), b_remain.len() - 1, b_remain);
388                            }
389                        }
390                    };
391                    Ok(SimplexContainer { sampler, fixed, auto })
392                }).zip(D0::keys())
393                .map(|(c, d0)| c.with_context(|| format!("at domain {d0:?}")))
394                .try_collect::<_, Vec<_>, _>()?;
395
396                Ok(ConditionSampler::Random(MArrD1::from_iter(containers)))
397            }
398        }
399    }
400}
401
402#[derive(Debug, Deserialize)]
403struct ConditionConfig<V> {
404    h_psi_if_phi0: ConditionOption<V>,
405    h_b_if_phi0: ConditionOption<V>,
406    o_b: ConditionOption<V>,
407    a_fh: ConditionOption<V>,
408    b_kh: ConditionOption<V>,
409    theta_h: ConditionOption<V>,
410    thetad_h: ConditionOption<V>,
411}
412
413impl<V> DeserializeAt<ConditionSamples<V>> for MyPath<ConditionConfig<V>>
414where
415    V: MyFloat + for<'a> Deserialize<'a>,
416    Open01: Distribution<V>,
417{
418    fn de<P: AsRef<Path>>(self, parent: P) -> anyhow::Result<ConditionSamples<V>> {
419        let child = self.verified_child(&parent)?;
420        let ConditionConfig {
421            h_psi_if_phi0,
422            h_b_if_phi0,
423            o_b,
424            a_fh,
425            b_kh,
426            theta_h,
427            thetad_h,
428        } = self.parse_at(&parent, DataFormat::de)?;
429
430        Ok(ConditionSamples {
431            h_psi_if_phi0: h_psi_if_phi0.de(&child).context("h_psi_if_phi0")?,
432            h_b_if_phi0: h_b_if_phi0.de(&child).context("h_b_if_phi0")?,
433            o_b: o_b.de(&child).context("o_b")?,
434            a_fh: a_fh.de(&child).context("a_fh")?,
435            b_kh: b_kh.de(&child).context("b_kh")?,
436            theta_h: theta_h.de(&child).context("theta_h")?,
437            thetad_h: thetad_h.de(&child).context("thetad_h")?,
438        })
439    }
440}
441
442#[derive(Debug, Deserialize)]
443struct UncertaintyConfig<V> {
444    fh_fpsi_if_fphi0: MyPath<Vec<UncertaintyD1Record<V>>>,
445    kh_kpsi_if_kphi0: MyPath<Vec<UncertaintyD1Record<V>>>,
446    fh_fphi_fo: MyPath<Vec<UncertaintyD2Record<V>>>,
447    kh_kphi_ko: MyPath<Vec<UncertaintyD2Record<V>>>,
448}
449
450impl<V> DeserializeAt<UncertaintySamples<V>> for MyPath<UncertaintyConfig<V>>
451where
452    V: MyFloat + for<'a> Deserialize<'a>,
453{
454    fn de<P: AsRef<Path>>(self, parent: P) -> anyhow::Result<UncertaintySamples<V>> {
455        let child = self.verified_child(&parent)?;
456        let UncertaintyConfig {
457            fh_fpsi_if_fphi0,
458            kh_kpsi_if_kphi0,
459            fh_fphi_fo,
460            kh_kphi_ko,
461        } = self.parse_at(&parent, DataFormat::de)?;
462
463        Ok(UncertaintySamples {
464            fh_fpsi_if_fphi0: fh_fpsi_if_fphi0
465                .parse_at(&child, read_csv)?
466                .into_iter()
467                .map(UncertaintyD1Record::try_into)
468                .try_collect()?,
469            kh_kpsi_if_kphi0: kh_kpsi_if_kphi0
470                .parse_at(&child, read_csv)?
471                .into_iter()
472                .map(UncertaintyD1Record::try_into)
473                .try_collect()?,
474            fh_fphi_fo: fh_fphi_fo
475                .parse_at(&child, read_csv)?
476                .into_iter()
477                .map(UncertaintyD2Record::try_into)
478                .try_collect()?,
479            kh_kphi_ko: kh_kphi_ko
480                .parse_at(&child, read_csv)?
481                .into_iter()
482                .map(UncertaintyD2Record::try_into)
483                .try_collect()?,
484        })
485    }
486}
487
488#[derive(Debug, serde::Deserialize)]
489struct ConditionRecord<V> {
490    b00: V,
491    b01: V,
492    u0: V,
493    b10: V,
494    b11: V,
495    u1: V,
496}
497
498impl<V, D1, D2> TryFrom<ConditionRecord<V>> for MArrD1<D1, SimplexD1<D2, V>>
499where
500    V: MyFloat,
501    D1: Domain<Idx: Debug>,
502    D2: Domain<Idx: Debug>,
503{
504    type Error = InvalidValueError;
505    fn try_from(value: ConditionRecord<V>) -> Result<Self, Self::Error> {
506        Ok(marr_d1![
507            SimplexD1::try_new(marr_d1![value.b00, value.b01], value.u0)?,
508            SimplexD1::try_new(marr_d1![value.b10, value.b11], value.u1)?,
509        ])
510    }
511}
512
513#[derive(Debug, Deserialize)]
514struct UncertaintyD1Record<V> {
515    u0: V,
516    u1: V,
517}
518
519impl<V: MyFloat, D1: Domain> TryFrom<UncertaintyD1Record<V>> for MArrD1<D1, V> {
520    type Error = InvalidValueError;
521    fn try_from(value: UncertaintyD1Record<V>) -> Result<Self, Self::Error> {
522        check_unit_interval(value.u0, "u0")?;
523        check_unit_interval(value.u1, "u1")?;
524        Ok(marr_d1![value.u0, value.u1])
525    }
526}
527
528#[derive(Debug, Deserialize)]
529struct UncertaintyD2Record<V> {
530    u00: V,
531    u01: V,
532    u10: V,
533    u11: V,
534}
535
536impl<V: MyFloat, D1: Domain, D2: Domain> TryFrom<UncertaintyD2Record<V>> for MArrD2<D1, D2, V> {
537    type Error = InvalidValueError;
538    fn try_from(value: UncertaintyD2Record<V>) -> Result<Self, Self::Error> {
539        check_unit_interval(value.u00, "u00")?;
540        check_unit_interval(value.u01, "u01")?;
541        check_unit_interval(value.u10, "u10")?;
542        check_unit_interval(value.u11, "u11")?;
543        Ok(marr_d2![[value.u00, value.u01], [value.u10, value.u11],])
544    }
545}
546
547#[derive(Debug, Deserialize)]
548struct OpinionRecord<V> {
549    b0: V,
550    b1: V,
551    u: V,
552    a0: V,
553    a1: V,
554}
555
556impl<V: MyFloat, D1> TryFrom<OpinionRecord<V>> for OpinionD1<D1, V>
557where
558    D1: Domain<Idx: Debug>,
559{
560    type Error = InvalidValueError;
561    fn try_from(value: OpinionRecord<V>) -> Result<Self, Self::Error> {
562        Ok(OpinionD1::try_new(
563            marr_d1![value.b0, value.b1],
564            value.u,
565            marr_d1![value.a0, value.a1],
566        )?)
567    }
568}
569
570#[derive(Debug, Deserialize)]
571struct InhibitionRecord<V> {
572    phi_b0: V,
573    phi_b1: V,
574    phi_u: V,
575    phi_a0: V,
576    phi_a1: V,
577    psi0_b0: V,
578    psi0_b1: V,
579    psi0_u: V,
580    psi1_b0: V,
581    psi1_b1: V,
582    psi1_u: V,
583    b0_b0: V,
584    b0_b1: V,
585    b0_u: V,
586    b1_b0: V,
587    b1_b1: V,
588    b1_u: V,
589}
590
591impl<V: MyFloat> TryFrom<InhibitionRecord<V>>
592    for (
593        OpinionD1<Phi, V>,
594        MArrD1<Psi, SimplexD1<H, V>>,
595        MArrD1<B, SimplexD1<H, V>>,
596    )
597{
598    type Error = InvalidValueError;
599    fn try_from(value: InhibitionRecord<V>) -> Result<Self, Self::Error> {
600        Ok((
601            OpinionD1::try_new(
602                marr_d1![value.phi_b0, value.phi_b1],
603                value.phi_u,
604                marr_d1![value.phi_a0, value.phi_a1],
605            )?,
606            marr_d1![
607                SimplexD1::try_new(marr_d1![value.psi0_b0, value.psi0_b1], value.psi0_u)?,
608                SimplexD1::try_new(marr_d1![value.psi1_b0, value.psi1_b1], value.psi1_u)?,
609            ],
610            marr_d1![
611                SimplexD1::try_new(marr_d1![value.b0_b0, value.b0_b1], value.b0_u)?,
612                SimplexD1::try_new(marr_d1![value.b1_b0, value.b1_b1], value.b1_u)?,
613            ],
614        ))
615    }
616}
617
618#[cfg(test)]
619mod tests {
620    use std::path::Path;
621
622    use base::opinion::{Phi, H};
623    use rand::{rngs::SmallRng, thread_rng, SeedableRng};
624    use serde::Deserialize;
625    use subjective_logic::{
626        marr_d1, marr_d2,
627        mul::labeled::{OpinionD1, SimplexD1},
628    };
629    use toml::toml;
630
631    use super::{ConditionOption, ConditionSampler};
632    use crate::{
633        config::{
634            AgentConfig, DeAgentConfig, DeNetworkConfig, DeStrategyConfig, DeserializeAt,
635            NetworkConfig, StrategyConfig,
636        },
637        io::MyPath,
638        parameter::Sampler,
639    };
640
641    #[test]
642    fn test_path() {
643        let d0 = Path::new("/hoge");
644        let d1 = Path::new("./fuga");
645        let d2 = d0.join(d1);
646        assert!(!d1.is_absolute());
647        assert_ne!(d1, Path::new("fuga"));
648        println!("{d2:?}");
649        assert_eq!(d2, Path::new("/hoge/fuga"));
650    }
651
652    #[test]
653    fn test_agent_config() -> anyhow::Result<()> {
654        let config: MyPath<AgentConfig<f32>> = "./test/agent_config.toml".into();
655        let agent: DeAgentConfig<f32> = config.de("")?;
656
657        let mut rng = SmallRng::seed_from_u64(0);
658
659        assert!(
660            matches!(&agent.opinion.condition.o_b, ConditionSampler::Array(arr) if arr.len() == 7)
661        );
662        assert!(matches!(
663            &agent.opinion.condition.o_b, ConditionSampler::Array(arr) if arr[3] == marr_d1![
664            SimplexD1::new(marr_d1![1.0, 0.00], 0.00),
665            SimplexD1::new(marr_d1![0.0, 0.75], 0.25)
666            ]
667        ));
668        assert_eq!(
669            agent.opinion.uncertainty.fh_fpsi_if_fphi0[0],
670            marr_d1![0.1, 0.1]
671        );
672        assert_eq!(
673            agent.opinion.uncertainty.kh_kphi_ko[0],
674            marr_d2![[0.1, 0.1], [0.1, 0.1]]
675        );
676
677        assert!(matches!(
678            agent.probabilities.plural_ignore_social,
679            Sampler::Beta(_)
680        ));
681        let mut p = 0.0;
682        for _ in 0..10 {
683            p += agent.probabilities.plural_ignore_social.choose(&mut rng);
684        }
685        p /= 10.0;
686        assert!((p - 0.1).abs() < 0.05);
687
688        for _ in 0..10 {
689            assert!(agent.sharer_trust.misinfo.choose(&mut rng) < 0.5);
690        }
691        Ok(())
692    }
693
694    #[test]
695    fn test_network_config() -> anyhow::Result<()> {
696        let config: MyPath<NetworkConfig<f32>> = "./test/network_config.toml".into();
697        let network: DeNetworkConfig<f32> = config.de("")?;
698        assert_eq!(network.community_psi1.levels.len(), 100);
699        assert!(
700            network.community_psi1.levels[network.community_psi1.indexes_by_level[10]]
701                > network.community_psi1.levels[network.community_psi1.indexes_by_level[90]]
702        );
703        Ok(())
704    }
705
706    #[test]
707    fn test_strategy_config() -> anyhow::Result<()> {
708        let config: MyPath<StrategyConfig<f32>> = "./test/strategy_config.toml".into();
709        let strategy: DeStrategyConfig<f32> = config.de("")?;
710        assert_eq!(
711            strategy.information.inhibition[0].0,
712            OpinionD1::new(marr_d1![0.0, 1.0], 0.0, marr_d1![0.05, 0.95])
713        );
714        assert_eq!(
715            strategy.information.inhibition[0].1,
716            marr_d1![
717                SimplexD1::new(marr_d1![0.5, 0.0], 0.5),
718                SimplexD1::new(marr_d1![0.1, 0.7], 0.2),
719            ]
720        );
721        assert_eq!(
722            strategy.information.inhibition[0].2,
723            marr_d1![
724                SimplexD1::new(marr_d1![0.5, 0.0], 0.5),
725                SimplexD1::new(marr_d1![0.1, 0.6], 0.3),
726            ]
727        );
728        Ok(())
729    }
730
731    #[derive(Debug, Deserialize)]
732    struct TestCondParam<V> {
733        hoge: ConditionOption<V>,
734    }
735
736    #[test]
737    fn test_cond_param() -> anyhow::Result<()> {
738        let param: TestCondParam<f32> = toml! {
739            hoge = { generate = [
740                [{b = [0,{single = 0.95}]},{b = [0,{single = 0.95}]},{u = {single = 0.05}}],
741                [{b = [0,{single = 0.95}]}, {u = {single = 0.05}}],
742            ] }
743        }
744        .try_into()?;
745        let r = DeserializeAt::<ConditionSampler<Phi, H, _>>::de(param.hoge, "");
746        assert!(r.is_err());
747        println!("{:#?}", r.err());
748
749        let param: TestCondParam<f32> = toml! {
750            hoge = { generate = [
751                [{b = [0,{single = 0.95}]},{u = {single = 0.95}},{u = {single = 0.05}}],
752                [{b = [0,{single = 0.95}]}, {u = {single = 0.05}}],
753            ] }
754        }
755        .try_into()?;
756        let r = DeserializeAt::<ConditionSampler<Phi, H, _>>::de(param.hoge, "");
757        assert!(r.is_err());
758        println!("{:#?}", r.err());
759
760        let param: TestCondParam<f32> = toml! {
761            hoge = { generate = [
762                [{b = [0,{single = 0.95}]},{b = [1,{single = 0.95}]},{u = {single = 0.05}}],
763                [{b = [0,{single = 0.95}]}, {u = {single = 0.05}}],
764            ] }
765        }
766        .try_into()?;
767        let r = DeserializeAt::<ConditionSampler<Phi, H, _>>::de(param.hoge, "");
768        assert!(r.is_err());
769        println!("{:#?}", r.err());
770
771        let param: TestCondParam<f32> = toml! {
772            hoge = { generate = [
773                [{b = [0,{single = 0.95}]}, {u = {single = 0.05}}],
774                [{b = [0,{array = [0.0,0.1]}]}, {b = [1,{uniform = [0.80,0.90]}]}],
775            ] }
776        }
777        .try_into()?;
778        let r = DeserializeAt::<ConditionSampler<Phi, H, _>>::de(param.hoge, "");
779        assert!(r.is_err());
780        println!("{:#?}", r.err());
781
782        let param: TestCondParam<f32> = toml! {
783            hoge = { generate = [
784                [{u = {single = 0.05}},{b = [0,{single = 0.95}]}],
785                [{b = [1,{single = 0.85}]},{b = [0,{single = 0.0}]}],
786            ] }
787        }
788        .try_into()?;
789        let s: ConditionSampler<Phi, H, f32> = param.hoge.de("")?;
790        let c = s.sample(&mut thread_rng());
791        assert_eq!(c[Phi(0)].b()[H(0)], 0.95);
792        assert_eq!(c[Phi(0)].u(), &0.05);
793        assert_eq!(c[Phi(1)].b()[H(0)], 0.0);
794        assert_eq!(c[Phi(1)].b()[H(1)], 0.85);
795
796        let param: TestCondParam<f32> = toml! {
797            hoge = { generate = [
798                [{b = [0,{single = 0.95}]}, {u = {single = 0.05}}],
799                [{b = [0,{single = 0.0}]}, {b = [1,{uniform = [0.80,0.90]}]}],
800            ] }
801        }
802        .try_into()?;
803        let s: ConditionSampler<Phi, H, f32> = param.hoge.de("")?;
804        for _ in 0..20 {
805            let c = s.sample(&mut thread_rng());
806            assert_eq!(c[Phi(0)].b()[H(0)], 0.95);
807            assert_eq!(c[Phi(0)].u(), &0.05);
808            assert_eq!(c[Phi(1)].b()[H(0)], 0.0);
809            assert_eq!(c[Phi(1)].u() + c[Phi(1)].b()[H(1)], 1.0);
810            assert!(c[Phi(1)].b()[H(1)] >= 0.80);
811            assert!(c[Phi(1)].b()[H(1)] < 0.90);
812        }
813        Ok(())
814    }
815}