assembly_theory/
bounds.rs1use bit_set::BitSet;
15use clap::ValueEnum;
16
17use crate::molecule::{Bond, Element, Molecule};
18
19#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
21pub enum Bound {
22 Log,
28 Int,
32 VecSimple,
38 VecSmallFrags,
43 CoverNoSort,
50 CoverSort,
53 CliqueBudget,
57}
58
59#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
61struct EdgeType {
62 bond: Bond,
63 ends: (Element, Element),
64}
65
66pub fn bound_exceeded(
68 mol: &Molecule,
69 fragments: &[BitSet],
70 state_index: usize,
71 best_index: usize,
72 largest_remove: usize,
73 bounds: &[Bound],
74) -> bool {
75 for bound_type in bounds {
76 let exceeds = match bound_type {
77 Bound::Log => state_index - log_bound(fragments) >= best_index,
78 Bound::Int => state_index - int_bound(fragments, largest_remove) >= best_index,
79 Bound::VecSimple => {
80 state_index - vec_simple_bound(fragments, largest_remove, mol) >= best_index
81 }
82 Bound::VecSmallFrags => {
83 state_index - vec_small_frags_bound(fragments, largest_remove, mol) >= best_index
84 }
85 _ => {
86 panic!("One of the chosen bounds is not implemented yet!")
87 }
88 };
89 if exceeds {
90 return true;
91 }
92 }
93 false
94}
95
96fn log_bound(fragments: &[BitSet]) -> usize {
98 let mut size = 0;
99 for f in fragments {
100 size += f.len();
101 }
102
103 size - (size as f32).log2().ceil() as usize
104}
105
106fn int_bound(fragments: &[BitSet], m: usize) -> usize {
108 let mut max_s: usize = 0;
109 let mut frag_sizes: Vec<usize> = Vec::new();
110
111 for f in fragments {
112 frag_sizes.push(f.len());
113 }
114
115 let size_sum: usize = frag_sizes.iter().sum();
116
117 for max in 2..m + 1 {
119 let log = (max as f32).log2().ceil();
120 let mut aux_sum: usize = 0;
121
122 for len in &frag_sizes {
123 aux_sum += (len / max) + (len % max != 0) as usize
124 }
125
126 max_s = max_s.max(size_sum - log as usize - aux_sum);
127 }
128
129 max_s
130}
131
132fn unique_edges(fragment: &BitSet, mol: &Molecule) -> Vec<EdgeType> {
136 let g = mol.graph();
137 let mut nodes: Vec<Element> = Vec::new();
138 for v in g.node_weights() {
139 nodes.push(v.element());
140 }
141 let edges: Vec<petgraph::prelude::EdgeIndex> = g.edge_indices().collect();
142 let weights: Vec<Bond> = g.edge_weights().copied().collect();
143
144 let mut types: Vec<EdgeType> = Vec::new();
146 for idx in fragment.iter() {
147 let bond = weights[idx];
148 let e = edges[idx];
149
150 let (e1, e2) = g.edge_endpoints(e).expect("bad");
151 let e1 = nodes[e1.index()];
152 let e2 = nodes[e2.index()];
153 let ends = if e1 < e2 { (e1, e2) } else { (e2, e1) };
154
155 let edge_type = EdgeType { bond, ends };
156
157 if types.contains(&edge_type) {
158 continue;
159 } else {
160 types.push(edge_type);
161 }
162 }
163
164 types
165}
166
167fn vec_simple_bound(fragments: &[BitSet], m: usize, mol: &Molecule) -> usize {
169 let mut s = 0;
172 for f in fragments {
173 s += f.len();
174 }
175
176 let mut union_set = BitSet::new();
177 for f in fragments {
178 union_set.union_with(f);
179 }
180 let z = unique_edges(&union_set, mol).len();
181
182 (s - z) - ((s - z) as f32 / m as f32).ceil() as usize
183}
184
185fn vec_small_frags_bound(fragments: &[BitSet], m: usize, mol: &Molecule) -> usize {
187 let mut size_two_fragments: Vec<BitSet> = Vec::new();
188 let mut large_fragments: Vec<BitSet> = fragments.to_owned();
189 let mut indices_to_remove: Vec<usize> = Vec::new();
190
191 for (i, frag) in fragments.iter().enumerate() {
193 if frag.len() == 2 {
194 indices_to_remove.push(i);
195 }
196 }
197 for &index in indices_to_remove.iter().rev() {
198 let removed_bitset = large_fragments.remove(index);
199 size_two_fragments.push(removed_bitset);
200 }
201
202 let mut fragments_union = BitSet::new();
204 let mut size_two_fragments_union = BitSet::new();
205 for f in fragments {
206 fragments_union.union_with(f);
207 }
208 for f in size_two_fragments.iter() {
209 size_two_fragments_union.union_with(f);
210 }
211 let z = unique_edges(&fragments_union, mol).len()
212 - unique_edges(&size_two_fragments_union, mol).len();
213
214 let mut s = 0;
217 let mut sl = 0;
218 for f in fragments {
219 s += f.len();
220 }
221 for f in large_fragments {
222 sl += f.len();
223 }
224
225 let mut size_two_types: Vec<(EdgeType, EdgeType)> = Vec::new();
227 for f in size_two_fragments.iter() {
228 let mut types = unique_edges(f, mol);
229 types.sort();
230 if types.len() == 1 {
231 size_two_types.push((types[0], types[0]));
232 } else {
233 size_two_types.push((types[0], types[1]));
234 }
235 }
236 size_two_types.sort();
237 size_two_types.dedup();
238
239 s - (z + size_two_types.len() + size_two_fragments.len())
240 - ((sl - z) as f32 / m as f32).ceil() as usize
241}