open_hypergraphs/strict/
eval.rs1use crate::array::*;
4use crate::finite_function::*;
5use crate::indexed_coproduct::*;
6use crate::semifinite::*;
7
8use crate::strict::graph::converse;
9use crate::strict::layer::layer;
10use crate::strict::open_hypergraph::*;
11
12use num_traits::Zero;
13use std::default::Default;
14
15fn layer_function_to_layers<K: ArrayKind>(f: FiniteFunction<K>) -> Vec<FiniteFunction<K>>
20where
21 K::Type<K::I>: NaturalArray<K>,
22 K::I: Into<usize> + From<usize>,
23{
24 let c = converse(&IndexedCoproduct::elements(f));
25 c.into_iter().collect()
26}
27
28pub fn eval<K: ArrayKind, O, A, T: Default>(
32 f: &OpenHypergraph<K, O, A>,
33 s: K::Type<T>,
34 apply: impl Fn(
35 SemifiniteFunction<K, A>,
36 IndexedCoproduct<K, SemifiniteFunction<K, T>>,
37 ) -> IndexedCoproduct<K, SemifiniteFunction<K, T>>,
38) -> Option<K::Type<T>>
39where
40 K::I: Into<usize> + From<usize>,
41 K::Type<K::I>: NaturalArray<K>,
42 K::Type<T>: Array<K, T>,
43 K::Type<O>: Array<K, O>,
44 K::Type<A>: Array<K, A>,
45{
46 let (order, unvisited) = layer(f);
47 let layering = layer_function_to_layers(order);
48
49 if unvisited.max().unwrap_or(K::I::zero()) == K::I::zero() {
52 let (_, outputs) = eval_order(f, s, layering, apply);
53 Some(outputs)
54 } else {
55 None
56 }
57}
58
59fn eval_order<K: ArrayKind, O, A, T: Default>(
61 f: &OpenHypergraph<K, O, A>,
63 s: K::Type<T>,
65 order: Vec<FiniteFunction<K>>,
69 apply: impl Fn(
70 SemifiniteFunction<K, A>,
71 IndexedCoproduct<K, SemifiniteFunction<K, T>>,
72 ) -> IndexedCoproduct<K, SemifiniteFunction<K, T>>,
73) -> (K::Type<T>, K::Type<T>)
74where
75 K::Type<K::I>: NaturalArray<K>,
76 K::Type<T>: Array<K, T>,
77 K::Type<O>: Array<K, O>,
78 K::Type<A>: Array<K, A>,
79{
80 let mut mem: SemifiniteFunction<K, T> =
82 SemifiniteFunction::new(K::Type::<T>::fill(T::default(), f.h.w.len()));
83
84 mem.0.scatter_assign(&f.s.table, s);
86
87 for op_ix in order {
88 let op_labels = (&op_ix >> &f.h.x).unwrap();
90
91 let input_indexes = f.h.s.map_indexes(&op_ix).unwrap();
93 let input_values = input_indexes.map_semifinite(&mem).unwrap();
94
95 let outputs = apply(op_labels, input_values);
97
98 let output_indexes = f.h.t.map_indexes(&op_ix).unwrap();
99
100 mem.0
102 .scatter_assign(&output_indexes.values.table, outputs.values.0);
103
104 }
106 let outputs = mem.0.gather(f.t.table.get_range(..));
107 (mem.0, outputs)
108}