plonky2/waksman/src/bimap.rs
Daniel Lubarov c126641c5d
Split into crates (#406)
* Split into crates

I kept other changes to a minimum, so 95% of this is just moving things. One complication that came up is that since `PrimeField` is now outside the plonky2 crate, these two impls now conflict:
```
impl<F: PrimeField> From<HashOut<F>> for Vec<u8> { ... }
impl<F: PrimeField> From<HashOut<F>> for Vec<F> { ... }
```
with this note:
```
note: upstream crates may add a new impl of trait `plonky2_field::field_types::PrimeField` for type `u8` in future versions
```
I worked around this by adding a `GenericHashOut` trait with methods like `to_bytes()` instead of overloading `From`/`Into`. Personally I prefer the explicitness anyway.

* Move out permutation network stuff also

* Fix imports

* Fix import

* Also move out insertion

* Comment

* fmt

* PR feedback
2021-12-28 11:51:13 -08:00

76 lines
2.1 KiB
Rust

use std::collections::HashMap;
use std::hash::Hash;
use bimap::BiMap;
/// Given two lists which are permutations of one another, creates a BiMap which maps an index in
/// one list to an index in the other list with the same associated value.
///
/// If the lists contain duplicates, then multiple permutations with this property exist, and an
/// arbitrary one of them will be returned.
pub fn bimap_from_lists<T: Eq + Hash>(a: Vec<T>, b: Vec<T>) -> BiMap<usize, usize> {
assert_eq!(a.len(), b.len(), "Vectors differ in length");
let mut b_values_to_indices = HashMap::new();
for (i, value) in b.iter().enumerate() {
b_values_to_indices
.entry(value)
.or_insert_with(Vec::new)
.push(i);
}
let mut bimap = BiMap::new();
for (i, value) in a.iter().enumerate() {
if let Some(j) = b_values_to_indices.get_mut(&value).and_then(Vec::pop) {
bimap.insert(i, j);
} else {
panic!("Value in first list not found in second list");
}
}
bimap
}
#[cfg(test)]
mod tests {
use crate::bimap::bimap_from_lists;
#[test]
fn empty_lists() {
let empty: Vec<char> = Vec::new();
let bimap = bimap_from_lists(empty.clone(), empty);
assert!(bimap.is_empty());
}
#[test]
fn without_duplicates() {
let bimap = bimap_from_lists(vec!['a', 'b', 'c'], vec!['b', 'c', 'a']);
assert_eq!(bimap.get_by_left(&0), Some(&2));
assert_eq!(bimap.get_by_left(&1), Some(&0));
assert_eq!(bimap.get_by_left(&2), Some(&1));
}
#[test]
fn with_duplicates() {
let first = vec!['a', 'a', 'b'];
let second = vec!['a', 'b', 'a'];
let bimap = bimap_from_lists(first.clone(), second.clone());
for i in 0..3 {
let j = *bimap.get_by_left(&i).unwrap();
assert_eq!(first[i], second[j]);
}
}
#[test]
#[should_panic]
fn lengths_differ() {
bimap_from_lists(vec!['a', 'a', 'b'], vec!['a', 'b']);
}
#[test]
#[should_panic]
fn not_a_permutation() {
bimap_from_lists(vec!['a', 'a', 'b'], vec!['a', 'b', 'b']);
}
}