Skip to content

Commit 206361d

Browse files
committed
move graph::converse to new relation module...
... and make public. This is a generic method on IndexedCoproducts thought of as encoding relations, and was used in some downstream projects.
1 parent dcde743 commit 206361d

5 files changed

Lines changed: 48 additions & 41 deletions

File tree

src/strict/eval.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ use crate::finite_function::*;
55
use crate::indexed_coproduct::*;
66
use crate::semifinite::*;
77

8-
use crate::strict::graph::converse;
98
use crate::strict::layer::layer;
109
use crate::strict::open_hypergraph::*;
10+
use crate::strict::relation::converse;
1111

1212
use num_traits::Zero;
1313
use std::default::Default;

src/strict/graph.rs

Lines changed: 2 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,11 @@
1-
use crate::array::{Array, ArrayKind, NaturalArray, OrdArray};
1+
use super::relation::converse;
2+
use crate::array::{Array, ArrayKind, NaturalArray};
23
use crate::category::Arrow;
34
use crate::finite_function::FiniteFunction;
4-
use crate::indexed_coproduct::HasLen;
55
use crate::indexed_coproduct::IndexedCoproduct;
66
use crate::strict::hypergraph::Hypergraph;
77
use num_traits::{One, Zero};
88

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-
469
/// Return the adjacency map for a [`Hypergraph`] `h`.
4710
///
4811
/// If `X` is the finite set of operations in `h`, then `operation_adjacency(h)` computes the

src/strict/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pub mod eval;
1010
pub mod functor;
1111
pub mod graph;
1212
pub mod layer;
13+
pub mod relation;
1314

1415
pub use crate::array::*;
1516
pub use crate::category::*;

src/strict/relation.rs

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

src/strict/tests/layer.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ use crate::array::vec::*;
22
use crate::finite_function::*;
33
use crate::indexed_coproduct::*;
44
use crate::semifinite::*;
5-
use crate::strict::graph::{converse, indegree, operation_adjacency};
5+
use crate::strict::graph::{indegree, operation_adjacency};
66
use crate::strict::layer::layer;
77
use crate::strict::open_hypergraph::*;
8+
use crate::strict::relation::converse;
89

910
#[derive(Clone, PartialEq, Debug)]
1011
pub enum Arr {

0 commit comments

Comments
 (0)