use rustsat::{
encodings::{card, pb},
instances::{Cnf, ManageVars, MultiOptInstance, Objective, SatInstance},
types::constraints::{CardConstraint, PbConstraint},
};
use crate::PreproClauses;
pub trait PreproMultiOpt: PreproClauses {
fn new_with_encoders<VM, CardEnc, PBEnc>(
inst: MultiOptInstance<VM>,
card_encoder: CardEnc,
pb_encoder: PBEnc,
inprocessing: bool,
) -> Self
where
VM: ManageVars,
CardEnc: FnMut(CardConstraint, &mut Cnf, &mut dyn ManageVars),
PBEnc: FnMut(PbConstraint, &mut Cnf, &mut dyn ManageVars),
Self: Sized,
{
let (constrs, objs) = inst.decompose();
let (cnf, _) = constrs.into_cnf_with_encoders(card_encoder, pb_encoder);
let softs: Vec<(_, isize)> = objs.into_iter().map(|o| o.into_soft_cls()).collect();
<Self as PreproClauses>::new(cnf, softs, inprocessing)
}
fn new<VM>(inst: MultiOptInstance<VM>, inprocessing: bool) -> Self
where
VM: ManageVars,
Self: Sized,
{
Self::new_with_encoders(
inst,
|constr, cnf, vm| {
card::default_encode_cardinality_constraint(constr, cnf, vm)
.expect("cardinality encoding ran out of memory")
},
|constr, cnf, vm| {
pb::default_encode_pb_constraint(constr, cnf, vm)
.expect("pb encoding ran out of memory")
},
inprocessing,
)
}
fn prepro_instance(&mut self) -> MultiOptInstance {
let (cnf, objs) = <Self as PreproClauses>::prepro_instance(self);
let constrs = SatInstance::from(cnf);
let objs = objs
.into_iter()
.map(|(softs, offset)| {
let mut obj = Objective::from_iter(softs);
obj.set_offset(offset);
obj
})
.collect();
MultiOptInstance::compose(constrs, objs)
}
}
impl<PP: PreproClauses> PreproMultiOpt for PP {}