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 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}