pub fn canonize(element: &mut Vec<usize>) -> bool {
let mut negate = false;
for _ in 0..element.len() {
for i in 1..element.len() {
if element[i - 1] > element[i] {
element.swap(i - 1, i);
negate ^= true;
}
}
}
for _ in 0..element.len() {
for i in 1..element.len() {
if element[i - 1] == element[i] {
element.remove(i);
element.remove(i - 1);
negate ^= true;
break;
}
}
}
negate
}
pub fn wedge_product(a: &[usize], b: &[usize]) -> Vec<usize> {
a.iter().chain(b.iter()).cloned().collect()
}
pub fn generate_elements(dimension: usize) -> Vec<Vec<usize>> {
let mut elements: Vec<Vec<usize>> = vec![vec![]];
for d in 0..dimension {
elements.push(vec![d]);
loop {
let mut new = Vec::new();
for a in &elements {
for b in &elements {
let mut c = wedge_product(a, b);
canonize(&mut c);
if !elements.contains(&c) && !new.contains(&c) {
new.push(c);
}
}
}
if new.is_empty() {
break;
}
elements.extend(new.into_iter());
}
}
elements
}
pub fn generate_product_sums(elements: &[Vec<usize>]) -> Vec<Vec<(bool, usize, usize)>> {
let mut sums: Vec<Vec<(bool, usize, usize)>> = vec![vec![]; elements.len()];
for (a_i, a) in elements.iter().enumerate() {
for (b_i, b) in elements.iter().enumerate() {
let mut c = wedge_product(a, b);
let negate = canonize(&mut c);
let c_i = elements.iter().position(|s| *s == c).unwrap();
sums[c_i].push((negate, a_i, b_i));
}
}
sums
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn canonization() {
let mut e = vec![];
assert!(!canonize(&mut e));
assert_eq!(e, vec![]);
let mut e = vec![0, 0];
assert!(canonize(&mut e));
assert_eq!(e, vec![]);
let mut e = vec![1, 0];
assert!(canonize(&mut e));
assert_eq!(e, vec![0, 1]);
let mut e = vec![2, 1, 0];
assert!(canonize(&mut e));
assert_eq!(e, vec![0, 1, 2]);
let mut e = vec![0, 2, 0];
assert!(!canonize(&mut e));
assert_eq!(e, vec![2]);
}
#[test]
fn element_generation() {
assert_eq!(
generate_elements(3),
vec![
vec![],
vec![0],
vec![1],
vec![0, 1],
vec![2],
vec![0, 2],
vec![1, 2],
vec![0, 1, 2],
]
)
}
#[test]
fn product_sum_generation() {
let elements = generate_elements(2);
assert_eq!(
generate_product_sums(&elements),
vec![
vec![
(false, 00, 00),
(true, 01, 01),
(true, 02, 02),
(true, 03, 03)
],
vec![
(false, 00, 01),
(false, 01, 00),
(false, 02, 03),
(true, 03, 02)
],
vec![
(false, 00, 02),
(true, 01, 03),
(false, 02, 00),
(false, 03, 01)
],
vec![
(false, 00, 03),
(false, 01, 02),
(true, 02, 01),
(false, 03, 00)
],
]
);
}
}