rustsat_tools/encodings/pb/
knapsack.rs1use rustsat::{
4 instances::fio::opb,
5 lit,
6 types::{constraints::PbConstraint, Lit},
7};
8
9use crate::encodings::knapsack::Knapsack;
10
11#[derive(Default)]
12enum Line {
13 #[default]
15 Hint,
16 Description,
18 Objective(usize),
20 Capacity,
22}
23
24pub struct Encoding {
25 data: Knapsack,
26 next_line: Option<Line>,
27}
28
29impl Encoding {
30 pub fn new(data: Knapsack) -> Self {
31 Self {
32 data,
33 next_line: Some(Line::default()),
34 }
35 }
36}
37
38impl Iterator for Encoding {
39 type Item = opb::FileLine<<Vec<(Lit, usize)> as IntoIterator>::IntoIter>;
40
41 fn next(&mut self) -> Option<Self::Item> {
42 match self.next_line.take() {
43 Some(line) => Some(match line {
44 Line::Hint => {
45 self.next_line = Some(Line::Description);
46 opb::FileLine::Comment(format!(
47 "#variable= {} #constraint= 1",
48 self.data.items.len()
49 ))
50 }
51 Line::Description => {
52 self.next_line = Some(Line::Objective(0));
53 opb::FileLine::Comment("MO Knapsack instance generated by RustSAT".to_string())
54 }
55 Line::Objective(oidx) => {
56 let obj: Vec<_> = self
57 .data
58 .items
59 .iter()
60 .enumerate()
61 .map(|(iidx, item)| (!lit![iidx as u32], item.values[oidx]))
62 .collect();
63 self.next_line = Some(if oidx + 1 < self.data.items[0].values.len() {
64 Line::Objective(oidx + 1)
65 } else {
66 Line::Capacity
67 });
68 opb::FileLine::Objective(obj.into_iter())
69 }
70 Line::Capacity => {
71 self.next_line = None;
72 let cap_constr = PbConstraint::new_ub(
73 self.data
74 .items
75 .iter()
76 .enumerate()
77 .map(|(idx, item)| (lit![idx as u32], item.weight as isize)),
78 self.data.capacity as isize,
79 );
80 opb::FileLine::Pb(cap_constr)
81 }
82 }),
83 None => None,
84 }
85 }
86}