use crate::field::Field;
use crate::groebner::CriticalPair;
use crate::polynomial::Polynomial;
use std::collections::HashSet;
pub fn filter_gm_pairs<F: Field>(
basis: &[Polynomial<F>],
pairs: Vec<CriticalPair>,
) -> Vec<CriticalPair> {
let mut to_remove = vec![false; pairs.len()];
for idx in 0..pairs.len() {
let pair = &pairs[idx];
for k in 0..basis.len() {
if k == pair.j || k == pair.i {
continue;
}
if let (Some(lm_i), Some(lm_k)) = (
basis[pair.i].leading_monomial(),
basis[k].leading_monomial(),
) {
let lcm_ik = lm_i.lcm(lm_k);
if lcm_ik != pair.lcm && pair.lcm.divides(&lcm_ik) {
to_remove[idx] = true;
break;
}
}
}
}
for idx in 0..pairs.len() {
if to_remove[idx] {
continue;
}
let pair = &pairs[idx];
for kidx in 0..pairs.len() {
if idx == kidx || to_remove[kidx] {
continue;
}
let other = &pairs[kidx];
if pair.i == other.i && other.lcm.divides(&pair.lcm) && other.lcm != pair.lcm {
to_remove[idx] = true;
break;
}
}
}
let mut seen = HashSet::new();
for idx in 0..pairs.len() {
if to_remove[idx] {
continue;
}
let lcm = &pairs[idx].lcm;
if !seen.insert(lcm.clone()) {
to_remove[idx] = true;
}
}
pairs
.into_iter()
.enumerate()
.filter(|(idx, _)| !to_remove[*idx])
.map(|(_, p)| p)
.collect()
}