|
1 | | -use crate::array::{Array, ArrayKind, NaturalArray, OrdArray}; |
| 1 | +use super::relation::converse; |
| 2 | +use crate::array::{Array, ArrayKind, NaturalArray}; |
2 | 3 | use crate::category::Arrow; |
3 | 4 | use crate::finite_function::FiniteFunction; |
4 | | -use crate::indexed_coproduct::HasLen; |
5 | 5 | use crate::indexed_coproduct::IndexedCoproduct; |
6 | 6 | use crate::strict::hypergraph::Hypergraph; |
7 | 7 | use num_traits::{One, Zero}; |
8 | 8 |
|
9 | | -/// Compute the *converse* of an [`IndexedCoproduct`] thought of as a "multirelation". |
10 | | -/// |
11 | | -/// An [`IndexedCoproduct`] `c : Σ_{x ∈ X} s(x) → Q` can equivalently be thought of as `c : X → |
12 | | -/// Q*`, i.e. a mapping from X to finite lists of elements in Q. |
13 | | -/// |
14 | | -/// Such a list defines a (multi-)relation as the multiset of pairs |
15 | | -/// |
16 | | -/// `R = { ( x, f(x)_i ) | x ∈ X, i ∈ len(f(x)) }` |
17 | | -/// |
18 | | -/// This function computes the *converse* of that relation as an indexed coproduct |
19 | | -/// `converse(c) : Q → X*`, or more precisely |
20 | | -/// `converse(c) : Σ_{q ∈ Q} s(q) → X`. |
21 | | -/// |
22 | | -/// NOTE: An indexed coproduct does not uniquely represent a 'multirelation', since *order* of the |
23 | | -/// elements matters. |
24 | | -/// The result of this function is only unique up to permutation of the sublists. |
25 | | -pub(crate) fn converse<K: ArrayKind>( |
26 | | - r: &IndexedCoproduct<K, FiniteFunction<K>>, |
27 | | -) -> IndexedCoproduct<K, FiniteFunction<K>> |
28 | | -where |
29 | | - K::Type<K::I>: NaturalArray<K>, |
30 | | -{ |
31 | | - let values_table = { |
32 | | - let arange = K::Index::arange(&K::I::zero(), &r.sources.len()); |
33 | | - let unsorted_values = r.sources.table.repeat(arange.get_range(..)); |
34 | | - unsorted_values.sort_by(&r.values.table) |
35 | | - }; |
36 | | - |
37 | | - let sources_table = |
38 | | - (r.values.table.as_ref() as &K::Type<K::I>).bincount(r.values.target.clone()); |
39 | | - |
40 | | - let sources = FiniteFunction::new(sources_table, r.values.table.len() + K::I::one()).unwrap(); |
41 | | - let values = FiniteFunction::new(values_table, r.len()).unwrap(); |
42 | | - |
43 | | - IndexedCoproduct::new(sources, values).unwrap() |
44 | | -} |
45 | | - |
46 | 9 | /// Return the adjacency map for a [`Hypergraph`] `h`. |
47 | 10 | /// |
48 | 11 | /// If `X` is the finite set of operations in `h`, then `operation_adjacency(h)` computes the |
|
0 commit comments