use csp_solver::constraint::{Revision, VarId};
use csp_solver::domain::bitset::BitsetDomain;
use csp_solver::domain::Domain;
use csp_solver::solver::gac_alldiff::propagate_gac_alldiff;
use csp_solver::variable::Variable;
fn run_gac(
domains: &[Vec<u32>],
) -> (Revision, Vec<Vec<u32>>) {
let scope: Vec<VarId> = (0..domains.len() as u32).collect();
let mut variables: Vec<Variable<BitsetDomain>> = domains
.iter()
.map(|vals| Variable::new(BitsetDomain::new(vals.iter().copied())))
.collect();
let rev = propagate_gac_alldiff(&scope, &mut variables, 0);
let result_domains: Vec<Vec<u32>> = variables
.iter()
.map(|v| v.domain.values())
.collect();
(rev, result_domains)
}
#[test]
fn test_no_pruning_needed() {
let (rev, doms) = run_gac(&[vec![1], vec![2], vec![3]]);
assert_eq!(rev, Revision::Unchanged);
assert_eq!(doms, vec![vec![1], vec![2], vec![3]]);
}
#[test]
fn test_simple_pruning() {
let (rev, _doms) = run_gac(&[vec![1], vec![1, 2], vec![1, 2, 3]]);
assert_eq!(rev, Revision::Unchanged);
}
#[test]
fn test_gac_three_vars() {
let (rev, doms) = run_gac(&[vec![1, 2], vec![1, 2], vec![1, 2, 3]]);
assert_eq!(rev, Revision::Changed);
assert_eq!(doms[0], vec![1, 2]);
assert_eq!(doms[1], vec![1, 2]);
assert_eq!(doms[2], vec![3]);
}
#[test]
fn test_unsatisfiable() {
let (rev, _doms) = run_gac(&[vec![1, 2], vec![1, 2], vec![1, 2]]);
assert_eq!(rev, Revision::Unsatisfiable);
}
#[test]
fn test_hall_set_four_vars() {
let (rev, doms) = run_gac(&[
vec![1, 2],
vec![1, 2],
vec![1, 2, 3, 4],
vec![1, 2, 3, 4],
]);
assert_eq!(rev, Revision::Changed);
assert_eq!(doms[0], vec![1, 2]);
assert_eq!(doms[1], vec![1, 2]);
assert_eq!(doms[2], vec![3, 4]);
assert_eq!(doms[3], vec![3, 4]);
}
#[test]
fn test_no_change_already_consistent() {
let (rev, doms) = run_gac(&[vec![1, 2], vec![3, 4], vec![5, 6]]);
assert_eq!(rev, Revision::Unchanged);
assert_eq!(doms[0], vec![1, 2]);
assert_eq!(doms[1], vec![3, 4]);
assert_eq!(doms[2], vec![5, 6]);
}
#[test]
fn test_mixed_singleton_and_multi() {
let (rev, _doms) = run_gac(&[vec![1], vec![1, 2, 3], vec![1, 2, 3], vec![1, 2, 3]]);
assert_eq!(rev, Revision::Unsatisfiable);
}
#[test]
fn gac_compiles_without_value_index() {
use csp_solver::domain::finite::FiniteDomain;
type GacFn = fn(&[VarId], &mut [Variable<FiniteDomain<String>>], usize) -> Revision;
let _: GacFn = propagate_gac_alldiff::<FiniteDomain<String>>;
}