rustsat_tools/encodings/pb/
assignment.rsuse rustsat::{
instances::fio::opb,
lit,
types::{constraints::CardConstraint, Lit},
};
use crate::encodings::assignment::Assignment;
#[derive(Default)]
enum Line {
#[default]
Hint,
Description,
Objective(usize),
OneTask(usize),
OneAgent(usize),
}
pub struct Encoding {
data: Assignment,
next_line: Option<Line>,
}
impl Encoding {
pub fn new(data: Assignment) -> Self {
Self {
data,
next_line: Some(Line::default()),
}
}
}
impl Iterator for Encoding {
type Item = opb::FileLine<<Vec<(Lit, usize)> as IntoIterator>::IntoIter>;
fn next(&mut self) -> Option<Self::Item> {
let selector = |task: usize, agent: usize| lit![(self.data.n_tasks * task + agent) as u32];
match self.next_line.take() {
Some(line) => Some(match line {
Line::Hint => {
self.next_line = Some(Line::Description);
opb::FileLine::Comment(format!(
"#variable= {} #constraint= {}",
self.data.n_tasks * self.data.n_tasks,
2 * self.data.n_tasks
))
}
Line::Description => {
self.next_line = Some(Line::Objective(0));
opb::FileLine::Comment(
"MO Assignment instance generated by RustSAT".to_string(),
)
}
Line::Objective(objidx) => {
let data = &self.data;
let obj: Vec<_> = (0..self.data.n_tasks)
.flat_map(|task| {
(0..self.data.n_tasks).map(move |agent| {
(selector(task, agent), data.cost(task, agent, objidx))
})
})
.collect();
self.next_line = Some(if objidx + 1 < self.data.n_objs {
Line::Objective(objidx + 1)
} else {
Line::OneTask(0)
});
opb::FileLine::Objective(obj.into_iter())
}
Line::OneTask(agent) => {
let constr = CardConstraint::new_eq(
(0..self.data.n_tasks).map(|task| selector(task, agent)),
1,
);
self.next_line = Some(if agent + 1 < self.data.n_tasks {
Line::OneTask(agent + 1)
} else {
Line::OneAgent(0)
});
opb::FileLine::Card(constr)
}
Line::OneAgent(task) => {
let constr = CardConstraint::new_eq(
(0..self.data.n_tasks).map(|agent| selector(task, agent)),
1,
);
self.next_line = if task + 1 < self.data.n_tasks {
Some(Line::OneAgent(task + 1))
} else {
None
};
opb::FileLine::Card(constr)
}
}),
None => None,
}
}
}