rustsat/encodings/am1/
bimander.rs1use std::marker::PhantomData;
9
10use super::Encode;
11use crate::{
12 encodings::{atomics, CollectClauses, EncodeStats, IterInputs},
13 instances::ManageVars,
14 types::Lit,
15 utils,
16};
17
18#[derive(Default, Debug)]
30#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
31pub struct Bimander<const N: usize = 4, Sub = super::Pairwise> {
32 in_lits: Vec<Lit>,
34 n_clauses: usize,
36 n_vars: u32,
38 _phantom: PhantomData<Sub>,
39}
40
41impl<const N: usize, Sub> Encode for Bimander<N, Sub>
42where
43 Sub: Encode + FromIterator<Lit> + From<Vec<Lit>>,
44{
45 fn n_lits(&self) -> usize {
46 self.in_lits.len()
47 }
48
49 fn encode<Col>(
50 &mut self,
51 collector: &mut Col,
52 var_manager: &mut dyn ManageVars,
53 ) -> Result<(), crate::OutOfMemory>
54 where
55 Col: CollectClauses,
56 {
57 if self.in_lits.len() <= 1 {
58 return Ok(());
59 }
60 let prev_clauses = collector.n_clauses();
61 let prev_vars = var_manager.n_used();
62
63 let n_splits = self.in_lits.len().div_ceil(N);
64 let p = utils::digits(n_splits - 1, 2);
65
66 let aux_vars: Vec<_> = (0..p).map(|_| var_manager.new_var()).collect();
67
68 for split in 0..n_splits {
69 let lits = &self.in_lits[split * N..std::cmp::min(self.in_lits.len(), (split + 1) * N)];
70 for (k, aux) in aux_vars.iter().enumerate().take(p as usize) {
71 let aux = aux.lit(split & (1 << k) == 0);
72 collector.extend_clauses(atomics::clause_impl_lit(lits, aux))?;
73 }
74 let mut sub = lits.iter().copied().collect::<Sub>();
75 sub.encode(collector, var_manager)?;
76 }
77
78 self.n_clauses = collector.n_clauses() - prev_clauses;
79 self.n_vars += var_manager.n_used() - prev_vars;
80 Ok(())
81 }
82}
83
84impl<const N: usize, Sub> IterInputs for Bimander<N, Sub> {
85 type Iter<'a>
86 = std::iter::Copied<std::slice::Iter<'a, Lit>>
87 where
88 Sub: 'a;
89
90 fn iter(&self) -> Self::Iter<'_> {
91 self.in_lits.iter().copied()
92 }
93}
94
95impl<const N: usize, Sub> EncodeStats for Bimander<N, Sub> {
96 fn n_clauses(&self) -> usize {
97 self.n_clauses
98 }
99
100 fn n_vars(&self) -> u32 {
101 self.n_vars
102 }
103}
104
105impl<const N: usize, Sub> From<Vec<Lit>> for Bimander<N, Sub> {
106 fn from(lits: Vec<Lit>) -> Self {
107 Self {
108 in_lits: lits,
109 n_clauses: 0,
110 n_vars: 0,
111 _phantom: PhantomData,
112 }
113 }
114}
115
116impl<const N: usize, Sub> FromIterator<Lit> for Bimander<N, Sub> {
117 fn from_iter<T: IntoIterator<Item = Lit>>(iter: T) -> Self {
118 Self {
119 in_lits: Vec::from_iter(iter),
120 n_clauses: 0,
121 n_vars: 0,
122 _phantom: PhantomData,
123 }
124 }
125}
126
127impl<const N: usize, Sub> Extend<Lit> for Bimander<N, Sub> {
128 fn extend<T: IntoIterator<Item = Lit>>(&mut self, iter: T) {
129 self.in_lits.extend(iter);
130 }
131}
132
133#[cfg(test)]
134mod tests {
135 use crate::{
136 encodings::am1::Encode,
137 instances::{BasicVarManager, Cnf, ManageVars},
138 lit, var,
139 };
140
141 #[test]
142 fn basic() {
143 let mut enc: super::Bimander = [lit![0], lit![1], lit![2], lit![3]].into_iter().collect();
144 let mut cnf = Cnf::new();
145 let mut vm = BasicVarManager::from_next_free(var![4]);
146 enc.encode(&mut cnf, &mut vm).unwrap();
147 assert_eq!(vm.n_used(), 5);
148 assert_eq!(cnf.len(), 10);
149 }
150}