use crate::cnf::{Reduced, ShowSet};
use crate::decompose::{SelectionCtx, SelectionObjective, TraceLevel};
use crate::tests::common::parse;
#[test]
fn for_show_masks_the_set_and_maps_absence_to_plain() {
let set = ShowSet::<Reduced>::from_dimacs_ids(&[1, 4]).expect("valid ids");
let projected = SelectionCtx::for_show(Some(&set), 5);
assert_eq!(
projected.objective.show_mask().map(|m| m.as_slice()),
Some(&[true, false, false, true, false][..]),
);
let plain = SelectionCtx::for_show(None::<&ShowSet<Reduced>>, 5);
assert!(matches!(plain.objective, SelectionObjective::ClauseBalance));
let empty = SelectionCtx::for_show(Some(&ShowSet::<Reduced>::empty()), 3);
assert_eq!(
empty.objective.show_mask().map(|m| m.as_slice()),
Some(&[false, false, false][..]),
);
}
const RESEARCH_KNOBS: &[&str] = &[
"VITRI_PORTFOLIO_SEED",
"VITRI_PORTFOLIO_TRACE",
"VITRI_PMC_FLOWCUTTER_CAP_MS",
"VITRI_GOATD_REFINE_BUDGET_MS",
"VITRI_GOATD_CANDIDATES",
];
#[test]
fn env_defaults_on_an_unset_environment_are_the_plain_defaults() {
if RESEARCH_KNOBS.iter().any(|k| std::env::var_os(k).is_some()) {
return;
}
let plain = SelectionCtx::plain();
let filled = SelectionCtx::plain()
.with_env_defaults()
.expect("no knob is set, so nothing can be malformed");
assert_eq!(filled.portfolio, plain.portfolio);
assert_eq!(filled.goatd, plain.goatd);
}
#[test]
fn env_defaults_keep_the_knobs_the_caller_set() {
if RESEARCH_KNOBS.iter().any(|k| std::env::var_os(k).is_some()) {
return;
}
let mut ctx = SelectionCtx::plain();
ctx.portfolio.seed = 7;
ctx.portfolio.trace = TraceLevel::All;
ctx.portfolio.flowcutter_cap_ms = Some(250);
ctx.goatd.refine_budget_ms = Some(1_500);
ctx.goatd.candidates = 3;
let filled = ctx
.with_env_defaults()
.expect("no knob is set, so nothing can be malformed");
assert_eq!(filled.portfolio.seed, 7);
assert_eq!(filled.portfolio.trace, TraceLevel::All);
assert_eq!(filled.portfolio.flowcutter_cap_ms, Some(250));
assert_eq!(filled.goatd.refine_budget_ms, Some(1_500));
assert_eq!(filled.goatd.candidates, 3);
}
#[test]
fn env_defaults_leave_the_selection_mode_alone() {
let mut ctx = SelectionCtx::for_show(
Some(&ShowSet::<Reduced>::from_dimacs_ids(&[2]).expect("valid ids")),
4,
);
ctx.portfolio.peak_tolerance = 0.25;
let filled = match ctx.with_env_defaults() {
Ok(c) => c,
Err(_) => return,
};
assert_eq!(
filled.objective.show_mask().map(|m| m.as_slice()),
Some(&[false, true, false, false][..]),
);
assert_eq!(filled.portfolio.peak_tolerance, 0.25);
}
#[test]
fn for_show_from_a_parsed_show_line_matches_the_hand_built_mask() {
let dimacs = "c t pmc\n\
p cnf 5 2\n\
c p show 1 4 0\n\
1 2 0\n\
-3 4 5 0\n";
let (formula, meta) = parse(dimacs);
let parsed = meta
.declared_show_vars()
.expect("the fixture declares a show set");
let from_file = SelectionCtx::for_show(Some(parsed), formula.num_vars);
let by_hand = SelectionCtx::for_show(
Some(&ShowSet::<Reduced>::from_dimacs_ids(&[1, 4]).expect("valid ids")),
5,
);
assert_eq!(
from_file.objective.show_mask().map(|m| m.as_slice()),
by_hand.objective.show_mask().map(|m| m.as_slice()),
);
assert_eq!(
from_file.objective.show_mask().map(|m| m.as_slice()),
Some(&[true, false, false, true, false][..]),
);
let (_, plain_meta) = parse("p cnf 5 1\n1 2 0\n");
let plain = SelectionCtx::for_show(plain_meta.declared_show_vars(), 5);
assert!(matches!(plain.objective, SelectionObjective::ClauseBalance));
}