Circle-Packings/fractal_dimension/circle_counting_new/src/lib.rs

129 lines
4.2 KiB
Rust
Raw Normal View History

2021-07-15 10:50:33 -07:00
use ansi_term::Color::Yellow;
2021-07-06 19:29:22 -07:00
use linregress::{FormulaRegressionBuilder, RegressionDataBuilder};
use nalgebra::{DMatrix, DVector};
pub fn fractal_dimension(
generators: Vec<DMatrix<f64>>,
root: DVector<f64>,
faces: Vec<Vec<usize>>,
upper_bound: f64,
n: usize,
debug: bool,
2021-07-11 11:11:03 -07:00
generations: usize,
orthogonal_generators: Vec<Vec<usize>>,
2021-07-06 19:29:22 -07:00
) -> Result<f64, linregress::Error> {
let mut totals = vec![root.len(); n];
2021-07-20 11:42:01 -07:00
let mut current = vec![(root, std::usize::MAX, false)];
2021-07-06 19:29:22 -07:00
let mut next = vec![];
2021-07-17 07:50:31 -07:00
let mut nodes: u64 = 1;
2021-07-06 19:29:22 -07:00
let xs: Vec<f64> = (1..=n)
2021-07-15 14:15:05 -07:00
.map(|x| (x as f64 * upper_bound / (2.0 * n as f64) + upper_bound / 2.0))
2021-07-06 19:29:22 -07:00
.collect();
let mut i = 0;
2021-07-07 10:38:30 -07:00
2021-07-06 19:29:22 -07:00
loop {
next.clear();
2021-07-20 11:42:01 -07:00
for (tuple, previous_generator, tuple_too_big) in &current {
2021-07-20 07:59:28 -07:00
let mut add_children = false;
let mut children = vec![];
2021-07-06 19:29:22 -07:00
for (i, generator) in generators.iter().enumerate() {
2021-07-11 11:11:03 -07:00
let mut skip = false;
for orthogonal_pairs in &orthogonal_generators {
if i == orthogonal_pairs[1] && *previous_generator == orthogonal_pairs[0] {
skip = true;
break;
}
}
if skip {
continue;
}
2021-07-06 19:29:22 -07:00
if i != *previous_generator {
let new_tuple = generator * tuple;
2021-07-20 11:42:01 -07:00
let mut too_big = true;
2021-07-06 19:29:22 -07:00
for (j, curvature) in new_tuple.iter().enumerate() {
let mut skip = false;
2021-07-07 07:39:06 -07:00
for vertex in &faces[i] {
if j == *vertex {
2021-07-06 19:29:22 -07:00
skip = true;
break;
}
}
if skip {
continue;
}
for (k, max) in xs.iter().enumerate() {
if curvature <= max {
2021-07-20 11:42:01 -07:00
add_children = true;
too_big = false;
2021-07-06 19:29:22 -07:00
totals[k] += 1;
}
}
}
2021-07-20 11:42:01 -07:00
children.push((new_tuple, i, too_big));
2021-07-06 19:29:22 -07:00
}
}
2021-07-20 11:42:01 -07:00
if add_children || !tuple_too_big {
2021-07-20 07:59:28 -07:00
nodes += 1;
for child in children {
next.push(child);
}
}
2021-07-06 19:29:22 -07:00
}
std::mem::swap(&mut current, &mut next);
2021-07-15 10:50:33 -07:00
2021-07-06 19:29:22 -07:00
i += 1;
2021-07-06 21:37:50 -07:00
if generations != 0 && i > generations {
break;
}
2021-07-06 19:29:22 -07:00
if debug {
println!("Generation {}:", i);
println!("\tnumber of leaves:\t{}", current.len());
if !current.is_empty() {
2021-07-08 09:31:54 -07:00
let tuple = &current[current.len() / 2];
println!("\trandom tuple:\t\t{}", tuple.0);
2021-07-06 19:29:22 -07:00
}
println!();
}
if current.is_empty() {
break;
}
}
if debug {
println!("{}", Yellow.paint("Done counting circles!"));
println!("sample points:\n{:?}", xs);
2021-07-15 10:50:33 -07:00
println!(
"\nnumber of circles fewer than each of those sample points:\n{:?}",
totals
2021-07-20 11:42:01 -07:00
);
2021-07-15 14:15:05 -07:00
println!("\nTotal number of nodes:\t{}", nodes);
2021-07-06 19:29:22 -07:00
}
let xs: Vec<f64> = xs.iter().map(|x| x.ln()).collect();
let ys: Vec<f64> = totals.iter().map(|x| (*x as f64).ln()).collect();
let data = vec![("Y", ys), ("X", xs)];
let data = RegressionDataBuilder::new().build_from(data)?;
let formula = "Y ~ X";
let model = FormulaRegressionBuilder::new()
.data(&data)
.formula(formula)
.fit()?;
if debug {
println!("\n{}", Yellow.paint("Built regression model!"));
println!("Model info:");
println!("\tr^2:\t\t{}", model.rsquared);
println!("\tp-value:\t{}", model.pvalues.pairs()[0].1);
println!("\tintercept:\t{}", model.parameters.intercept_value);
println!("\tslope:\t{}", model.parameters.regressor_values[0]);
}
let parameters = model.parameters;
Ok(parameters.regressor_values[0])
}