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

231 lines
5.9 KiB
Rust
Raw Normal View History

2021-07-06 19:29:22 -07:00
#![allow(dead_code)]
2021-07-05 12:52:54 -07:00
use crate::{
fractal::fractal_dimension,
gram_matrix::{algebraic_generators, geometric_generators, root_tuple},
parser::read_file,
};
use nalgebra::DVector;
2021-07-06 19:29:22 -07:00
use std::process;
use structopt::StructOpt;
2021-07-05 12:52:54 -07:00
2021-07-06 19:29:22 -07:00
use ansi_term::Color::Yellow;
2021-07-05 12:52:54 -07:00
2021-08-03 00:27:07 -07:00
pub mod constants;
2021-07-26 09:39:57 -07:00
pub mod fractal;
pub mod gram_matrix;
2021-07-26 09:39:57 -07:00
pub mod parser;
pub mod search;
2021-07-05 12:52:54 -07:00
2021-07-06 19:29:22 -07:00
/// Compute fractal dimension of crystallographic packings via the circle counting method
#[derive(StructOpt)]
#[structopt(name = "Circle Counter")]
struct Opt {
/// File containing data in the order generators, root, faces
#[structopt(name = "data file")]
data_file: String,
2021-07-05 12:52:54 -07:00
2021-07-06 19:29:22 -07:00
/// Activate debug mode
#[structopt(short, long)]
debug: bool,
2021-07-05 12:52:54 -07:00
2021-07-06 19:29:22 -07:00
/// Number of sample points in linear regression
#[structopt(short, long, default_value = "50")]
n: usize,
2021-07-05 12:52:54 -07:00
2021-07-06 19:29:22 -07:00
/// Maximum curvature of circles
#[structopt(short, long, default_value = "1000000")]
max: f64,
/// Whether or not to time excecution (automatically enabled by --debug)
#[structopt(short, long)]
time: bool,
2021-07-06 21:37:50 -07:00
2021-08-03 00:27:07 -07:00
/// Cap on the recursion depth (0 means no cap)
2021-07-06 21:37:50 -07:00
#[structopt(short, long, default_value = "0")]
2021-08-03 00:27:07 -07:00
depth: usize,
/// Whether the generators given are geometric or algebraic generators (defaults to algebraic)
#[structopt(short, long)]
geometric: bool,
2021-07-05 12:52:54 -07:00
}
fn main() {
2021-07-06 19:29:22 -07:00
let opt = Opt::from_args();
let debug = opt.debug;
let time = debug || opt.time;
2021-08-03 00:27:07 -07:00
let depth = opt.depth;
2021-07-06 19:29:22 -07:00
let beginning = std::time::Instant::now();
let (gram_matrix, faces) = read_file(&opt.data_file).unwrap_or_else(|err| {
eprintln!("{}", err);
process::exit(-1);
});
2021-07-05 12:52:54 -07:00
2021-07-06 19:29:22 -07:00
let after_parsing = std::time::Instant::now();
if time {
let duration = after_parsing.duration_since(beginning);
println!(
"Took {}s to parse {}",
duration.as_secs_f64(),
opt.data_file
);
}
if debug {
println!(
"{} (parsed from command args):\t{}",
Yellow.paint("max"),
opt.max
);
println!(
"{} (parsed from command args):\t{}",
Yellow.paint("n"),
opt.n
);
}
2021-07-05 12:52:54 -07:00
2021-07-06 19:29:22 -07:00
if debug {
println!(
"{} (parsed from file {}):",
Yellow.paint("Gram Matrix"),
2021-07-06 19:29:22 -07:00
opt.data_file
);
println!("{}\n", gram_matrix);
2021-07-06 19:29:22 -07:00
println!(
"{} (parsed from file {}):",
Yellow.paint("Faces"),
opt.data_file
);
println!("{:?}\n", faces);
/* println!(
2021-07-11 11:11:03 -07:00
"{} (parsed from file {}):",
Yellow.paint("Orthogonal Generators"),
opt.data_file
);
println!("{:?}\n", orthogonal_generators); */
}
// finding a suitable root tuple
let mut root = None;
for face in faces.iter().skip(1) {
for vertex in face {
let mut valid = true;
for vertex2 in &faces[0] {
if *vertex == *vertex2 {
valid = false;
break;
}
}
if valid {
let temp = root_tuple(
&gram_matrix,
(faces[0][0], faces[0][1], faces[0][2]),
*vertex,
);
let mut valid = true;
let generators = geometric_generators(&gram_matrix, &faces, &temp);
for gen in generators {
if gen[(1, 0)].abs() <= 1e-8 || !gen[(1, 0)].is_finite() {
valid = false;
break;
}
}
if valid {
root = Some(temp);
println!("{}\t{:?}", vertex, faces[0]);
break;
}
}
}
if root.is_some() {
break;
}
}
if root.is_none() {
panic!("Invalid face scheme!");
}
let root = root.unwrap();
let generators = geometric_generators(&gram_matrix, &faces, &root);
if debug {
println!(
"{} (computed using gram_matrix):",
Yellow.paint("Root Matrix")
);
println!("{}", root);
println!(
"{} (computed using gram_matrix and root):",
Yellow.paint("Geometric generators")
);
for generator in &generators {
println!("{}", generator);
}
let generators = algebraic_generators(&gram_matrix, &faces);
println!(
"{} (computed using gram_matrix and root):",
Yellow.paint("Algebraic generators")
);
for generator in &generators {
println!("{}", generator);
}
}
let mut temp = vec![];
for circle in root.column_iter() {
temp.push(DVector::from_iterator(
4,
circle.iter().map(|val| val.clone()),
));
2021-07-06 19:29:22 -07:00
}
let root = temp;
2021-07-06 19:29:22 -07:00
2021-07-15 10:50:33 -07:00
let delta = fractal_dimension(
generators,
root,
opt.max,
opt.n,
debug,
2021-08-03 00:27:07 -07:00
depth,
faces,
vec![],
2021-07-15 10:50:33 -07:00
)
.unwrap();
2021-07-06 19:29:22 -07:00
let after_computing = std::time::Instant::now();
if time {
let duration1 = after_computing.duration_since(after_parsing);
let duration2 = after_computing.duration_since(beginning);
2021-07-08 07:54:50 -07:00
let time1 = duration1.as_secs_f64();
let time2 = duration2.as_secs_f64();
let seconds1 = time1 % 60.0;
let seconds2 = time2 % 60.0;
let minutes1 = (time1 as isize) / 60;
let minutes2 = (time2 as isize) / 60;
if minutes1 > 0 {
println!(
"\nTook {}m {}s to compute fractal dimension; {}m {}s total",
minutes1, seconds1, minutes2, seconds2
);
} else {
println!(
"\nTook {}s to compute fractal dimension; {}s total",
seconds1, seconds2,
);
}
2021-07-06 19:29:22 -07:00
}
println!("\n{}", delta);
2021-07-05 12:52:54 -07:00
}