oxilean_std/combinatorics/
types.rs1use super::functions::*;
5
6#[derive(Debug, Clone)]
12pub struct LovaszLocalLemma {
13 pub num_events: usize,
15 pub prob_numerator: u64,
17 pub prob_denominator: u64,
18 pub max_degree: usize,
20}
21impl LovaszLocalLemma {
22 pub fn new(
24 num_events: usize,
25 prob_numerator: u64,
26 prob_denominator: u64,
27 max_degree: usize,
28 ) -> Self {
29 Self {
30 num_events,
31 prob_numerator,
32 prob_denominator,
33 max_degree,
34 }
35 }
36 pub fn symmetric_condition_holds(&self) -> bool {
40 let lhs = 4u64
41 .saturating_mul(self.prob_numerator)
42 .saturating_mul((self.max_degree + 1) as u64);
43 lhs <= self.prob_denominator
44 }
45 pub fn asymmetric_condition_holds(&self) -> bool {
49 let numerator = 271828u64
50 .saturating_mul(self.prob_numerator)
51 .saturating_mul((self.max_degree + 1) as u64);
52 let denominator = self.prob_denominator.saturating_mul(100000);
53 numerator <= denominator
54 }
55 pub fn slack(&self) -> i64 {
57 let lhs = 4i64 * self.prob_numerator as i64 * (self.max_degree as i64 + 1);
58 self.prob_denominator as i64 - lhs
59 }
60}
61#[derive(Debug, Clone, PartialEq, Eq)]
63pub struct Poly(pub Vec<i64>);
64impl Poly {
65 pub fn zero() -> Self {
67 Poly(vec![])
68 }
69 pub fn constant(c: i64) -> Self {
71 if c == 0 {
72 Poly::zero()
73 } else {
74 Poly(vec![c])
75 }
76 }
77 pub fn degree(&self) -> usize {
79 self.0.len().saturating_sub(1)
80 }
81 pub fn eval(&self, x: i64) -> i64 {
83 self.0.iter().rev().fold(0i64, |acc, &c| acc * x + c)
84 }
85 pub fn trim(mut self) -> Self {
87 while self.0.last() == Some(&0) {
88 self.0.pop();
89 }
90 self
91 }
92 pub fn add(&self, other: &Self) -> Self {
94 let len = self.0.len().max(other.0.len());
95 let mut result = vec![0i64; len];
96 for (i, &c) in self.0.iter().enumerate() {
97 result[i] += c;
98 }
99 for (i, &c) in other.0.iter().enumerate() {
100 result[i] += c;
101 }
102 Poly(result).trim()
103 }
104 pub fn mul(&self, other: &Self) -> Self {
106 if self.0.is_empty() || other.0.is_empty() {
107 return Poly::zero();
108 }
109 let len = self.0.len() + other.0.len() - 1;
110 let mut result = vec![0i64; len];
111 for (i, &a) in self.0.iter().enumerate() {
112 for (j, &b) in other.0.iter().enumerate() {
113 result[i + j] += a * b;
114 }
115 }
116 Poly(result).trim()
117 }
118 pub fn conv_truncated(a: &[i64], b: &[i64], n: usize) -> Vec<i64> {
120 let mut c = vec![0i64; n + 1];
121 for i in 0..=n {
122 for j in 0..=i {
123 if j < a.len() && (i - j) < b.len() {
124 c[i] += a[j] * b[i - j];
125 }
126 }
127 }
128 c
129 }
130}
131#[derive(Debug, Clone)]
133pub struct TuranDensityComputer {
134 pub forbidden_clique: usize,
136 pub bounds: Vec<(usize, u64)>,
138}
139impl TuranDensityComputer {
140 pub fn new(r: usize) -> Self {
142 Self {
143 forbidden_clique: r + 1,
144 bounds: Vec::new(),
145 }
146 }
147 pub fn turan_edges(&self, n: usize) -> u64 {
152 let r = self.forbidden_clique - 1;
153 if r == 0 {
154 return 0;
155 }
156 let q = n / r;
157 let rem = n % r;
158 let total_edges = (n as u64 * (n as u64 - 1)) / 2;
159 let intra: u64 = (0..r)
160 .map(|i| {
161 let part_size = if i < rem { q + 1 } else { q } as u64;
162 part_size * (part_size - 1) / 2
163 })
164 .sum();
165 total_edges - intra
166 }
167 pub fn density(&self) -> (usize, usize) {
171 let r = self.forbidden_clique - 1;
172 if r <= 1 {
173 return (0, 1);
174 }
175 let g = gcd_usize(r - 1, r);
176 ((r - 1) / g, r / g)
177 }
178 pub fn cache_bound(&mut self, n: usize, bound: u64) {
180 self.bounds.push((n, bound));
181 }
182}
183#[derive(Debug, Clone)]
188pub struct MatroidIntersectionSolver {
189 pub ground_set_size: usize,
191 pub block_assignment_1: Vec<usize>,
193 pub rank_bounds_1: Vec<usize>,
195 pub block_assignment_2: Vec<usize>,
197 pub rank_bounds_2: Vec<usize>,
199}
200impl MatroidIntersectionSolver {
201 pub fn new(
203 n: usize,
204 block_assignment_1: Vec<usize>,
205 rank_bounds_1: Vec<usize>,
206 block_assignment_2: Vec<usize>,
207 rank_bounds_2: Vec<usize>,
208 ) -> Self {
209 Self {
210 ground_set_size: n,
211 block_assignment_1,
212 rank_bounds_1,
213 block_assignment_2,
214 rank_bounds_2,
215 }
216 }
217 pub fn is_independent_1(&self, mask: u64) -> bool {
219 let mut counts = vec![0usize; self.rank_bounds_1.len()];
220 for i in 0..self.ground_set_size {
221 if mask & (1 << i) != 0 {
222 let b = self.block_assignment_1[i];
223 if b < counts.len() {
224 counts[b] += 1;
225 if counts[b] > self.rank_bounds_1[b] {
226 return false;
227 }
228 }
229 }
230 }
231 true
232 }
233 pub fn is_independent_2(&self, mask: u64) -> bool {
235 let mut counts = vec![0usize; self.rank_bounds_2.len()];
236 for i in 0..self.ground_set_size {
237 if mask & (1 << i) != 0 {
238 let b = self.block_assignment_2[i];
239 if b < counts.len() {
240 counts[b] += 1;
241 if counts[b] > self.rank_bounds_2[b] {
242 return false;
243 }
244 }
245 }
246 }
247 true
248 }
249 pub fn solve_brute_force(&self) -> (usize, u64) {
253 let n = self.ground_set_size.min(20);
254 let mut best_size = 0;
255 let mut best_mask = 0u64;
256 for mask in 0u64..(1 << n) {
257 if self.is_independent_1(mask) && self.is_independent_2(mask) {
258 let size = mask.count_ones() as usize;
259 if size > best_size {
260 best_size = size;
261 best_mask = mask;
262 }
263 }
264 }
265 (best_size, best_mask)
266 }
267}
268#[derive(Debug, Clone)]
273pub struct CycleIndexPolynomial {
274 pub group_name: String,
276 pub terms: Vec<(u64, Vec<u32>)>,
279 pub group_order: u64,
281}
282impl CycleIndexPolynomial {
283 pub fn new(group_name: impl Into<String>, group_order: u64) -> Self {
285 Self {
286 group_name: group_name.into(),
287 terms: Vec::new(),
288 group_order,
289 }
290 }
291 pub fn add_term(&mut self, coeff: u64, exponents: Vec<u32>) {
293 self.terms.push((coeff, exponents));
294 }
295 pub fn eval_all_ones(&self) -> u64 {
297 let total: u64 = self.terms.iter().map(|(c, _)| c).sum();
298 total / self.group_order.max(1)
299 }
300 pub fn burnside_count(&self, k: u64) -> u64 {
305 let total: u64 = self
306 .terms
307 .iter()
308 .map(|(coeff, exps)| {
309 let sum_exps: u32 = exps.iter().sum();
310 let product = k.pow(sum_exps);
311 coeff * product
312 })
313 .sum();
314 total / self.group_order.max(1)
315 }
316 pub fn cyclic(n: u32) -> Self {
318 let mut cip = Self::new(format!("C_{}", n), n as u64);
319 for d in 1..=(n as u64) {
320 if n as u64 % d == 0 {
321 let phi_d = euler_phi(d);
322 let exp_pos = (d as usize).saturating_sub(1);
323 let count = n as u64 / d;
324 let mut exps = vec![0u32; n as usize];
325 if exp_pos < exps.len() {
326 exps[exp_pos] = count as u32;
327 }
328 cip.add_term(phi_d, exps);
329 }
330 }
331 cip
332 }
333}