diff --git a/fractal_dimension/circle_counting_new/instructions.md b/fractal_dimension/circle_counting_new/instructions.md index d65af3b..a5fc006 100644 --- a/fractal_dimension/circle_counting_new/instructions.md +++ b/fractal_dimension/circle_counting_new/instructions.md @@ -6,4 +6,11 @@ You need to compile the code before you can run it. You can compile it locally, Next you will need to give the code the right data. Inside this directory there is a folder called `data` which has all the data. For each polyhedron, there is a corresponding file called `polyhedron.txt` (e.g. `tetrahedron.txt`) with the corresponding data. First is the Gram matrix in the format Mathematica spits out. Next is the face data. It should correspond with the Gram matrix and be in Mathematica's list format, but *it is indexed starting from 0* unlike Mathematica. The file `fractal_dimension.nb` has some functions that make this convenient. You can simply type up the gram matrix, then run `FindFace[graphFromG[G]]-1` and that will spit out exactly what you want. Then put this somewhere in the data folder where it makes sense. # Actually running -I wrote a little script called `driver.sh` that runs this code on everything in the data folder that isn't already computed and stores the result in a folder called `output`. You should just be able to run `./driver.sh ` (I'd recommend `./driver.sh 1e3` to see if it works, then `./driver.sh 1e6` and/or `./driver.sh 1e7`). If you want to run it manually, you can run `./target/release/circle_counting dimension --help` and it will tell you what the options and their defaults are. Likewise, if you want to generate a picture, you can run `./target/release/circle_counting picture --help` and it will tell you how to run that. You can also tweak the options in `driver.sh`, but that can have some unexpected effects. +## Fractal dimension +I wrote a little script called `driver.sh` that runs this code on everything in the data folder that isn't already computed and stores the result in a folder called `output`. You should just be able to run `./driver.sh ` (I'd recommend `./driver.sh 1e3` to see if it works, then `./driver.sh 1e6` and/or `./driver.sh 1e7`). If you want to run it manually, you can run `./target/release/circle_counting dimension --help` and it will tell you what the options and their defaults are. You can also tweak the options in `driver.sh`, but that can have some unexpected effects. + +## Computing Generators/Root Tuple +This program can also compute generators (both geometric and algebraic, but mathematica can probably get more accurate results for the algebraic generators) and a bounded root tuple. The command for that is `./target/release/circle_counting generators `. If you want the output formatted like python (e.g. for use with Emmi's McMullen code), add the `--format=python` flag. The formats `mathematica`, `c`, and `human-readable` are also handled. I would also recommend adding `> output.txt` or something like that to the end to save the results in a text file. + +## Picture +If you want to generate a picture, you can run `./target/release/circle_counting picture --help` and it will tell you how to run that. I would recommend just running `./target/release/circle_counting picture `, as the defaults are pretty good. diff --git a/fractal_dimension/circle_counting_new/src/command_args.rs b/fractal_dimension/circle_counting_new/src/command_args.rs index 8033ac0..e70b82a 100644 --- a/fractal_dimension/circle_counting_new/src/command_args.rs +++ b/fractal_dimension/circle_counting_new/src/command_args.rs @@ -1,3 +1,5 @@ +use std::str::FromStr; + use structopt::StructOpt; /// General tool for working with polyhedral circle packings. Can be used to create high detail svg @@ -67,4 +69,37 @@ pub enum Polyhedral { #[structopt(short, long, default_value = "1000")] height: usize, }, + + /// Find bounded root tuple and geometric generators + Generators { + /// File containing the gram matrix as well as information about the faces + #[structopt(name = "data file")] + data_file: String, + + /// Format to output data in + #[structopt(short, long, default_value = "human-readable")] + format: DataFormats, + }, +} + +#[derive(Debug)] +pub enum DataFormats { + HumanReadable, + Python, + Mathematica, + CStyle, +} + +impl FromStr for DataFormats { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "human-readable" => Ok(DataFormats::HumanReadable), + "python" => Ok(DataFormats::Python), + "mathematica" => Ok(DataFormats::Mathematica), + "c" => Ok(DataFormats::CStyle), + other => Err(format!("format {} not supported; expected \"human-readable\", \"python\", \"mathematica\", or \"c\"", other)), + } + } } diff --git a/fractal_dimension/circle_counting_new/src/main.rs b/fractal_dimension/circle_counting_new/src/main.rs index 379ae06..bad8ca9 100644 --- a/fractal_dimension/circle_counting_new/src/main.rs +++ b/fractal_dimension/circle_counting_new/src/main.rs @@ -3,14 +3,16 @@ mod command_args; mod dimension; mod gram_matrix; +mod output_formats; mod parser; mod picture; mod search; mod time; +use crate::output_formats::{format_matrix, format_vec_of_matrices}; use command_args::Polyhedral; use dimension::fractal_dimension; -use gram_matrix::{bounded_root_tuple, geometric_generators}; +use gram_matrix::{algebraic_generators, bounded_root_tuple, geometric_generators}; use parser::read_file; use picture::render_packing; use structopt::StructOpt; @@ -71,5 +73,23 @@ fn main() { &timer, ); } + + Polyhedral::Generators { data_file, format } => { + let (gram_matrix, faces) = read_file(&data_file); + let root = bounded_root_tuple(&gram_matrix, &faces); + let alggen = algebraic_generators(&gram_matrix, &faces); + let geomgen = geometric_generators(&gram_matrix, &faces, &root); + println!("File: {}\n", data_file); + println!("Gram matrix:\n{}\n", format_matrix(&gram_matrix, &format)); + println!( + "Algebraic generators:\n{}\n", + format_vec_of_matrices(&alggen, &format) + ); + println!( + "Geometric generators:\n{}\n", + format_vec_of_matrices(&alggen, &format) + ); + println!("Bounded root tuple:\n{}", format_matrix(&root, &format)); + } } } diff --git a/fractal_dimension/circle_counting_new/src/output_formats.rs b/fractal_dimension/circle_counting_new/src/output_formats.rs new file mode 100644 index 0000000..8ba6156 --- /dev/null +++ b/fractal_dimension/circle_counting_new/src/output_formats.rs @@ -0,0 +1,80 @@ +#![allow(dead_code)] + +use crate::command_args::DataFormats; +use nalgebra::DMatrix; +use std::fmt::{Debug, Display}; + +/// Formats a matrix according to the format specified by `format`. +pub fn format_matrix(matrix: &DMatrix, format: &DataFormats) -> String +where + T: Display + Copy + Debug + PartialEq, +{ + match format { + DataFormats::HumanReadable => format!("{}", matrix), + DataFormats::Mathematica | DataFormats::CStyle => { + let mut res = "{".to_string(); + for (i, row) in matrix.row_iter().enumerate() { + res += "{"; + for (j, elem) in row.iter().enumerate() { + res += format!("{}", elem).as_str(); + if j < row.len() - 1 { + res += ", "; + } + } + res += "}"; + if i < matrix.nrows() - 1 { + res += ",\n"; + } + } + + res + "}" + } + DataFormats::Python => { + let mut res = "numpy.array([".to_string(); + for (i, row) in matrix.row_iter().enumerate() { + res += "["; + for (j, elem) in row.iter().enumerate() { + res += format!("{}", elem).as_str(); + if j < row.len() - 1 { + res += ", "; + } + } + res += "]"; + if i < matrix.nrows() - 1 { + res += ",\n"; + } + } + + res + "])" + } + } +} + +/// Formats a vector of matrices according to the format specified by `format`. +pub fn format_vec_of_matrices(vec: &Vec>, format: &DataFormats) -> String +where + T: Display + Copy + Debug + PartialEq, +{ + match format { + DataFormats::HumanReadable | DataFormats::Python => { + let mut res = "[".to_string(); + for (i, elem) in vec.iter().enumerate() { + res += format!("{}", format_matrix(elem, format)).as_str(); + if i < vec.len() - 1 { + res += ", "; + } + } + res + "]" + } + DataFormats::CStyle | DataFormats::Mathematica => { + let mut res = "{".to_string(); + for (i, elem) in vec.iter().enumerate() { + res += format!("{}", format_matrix(elem, format)).as_str(); + if i < vec.len() - 1 { + res += ", "; + } + } + res + "}" + } + } +}