almost done

This commit is contained in:
William Ball 2021-08-06 20:20:35 -04:00
parent 1fc4553335
commit 2c0a38ec9e

View file

@ -1,6 +1,7 @@
use nalgebra::DMatrix; use nalgebra::DMatrix;
pub fn extended_gram_matrix(g: &DMatrix<f64>, faces: Vec<Vec<usize>>) -> DMatrix<f64> { /// Computes the extended gram matrix from G using Nooria's formula.
pub fn extended_gram_matrix(g: &DMatrix<f64>, faces: &Vec<Vec<usize>>) -> DMatrix<f64> {
let n = g.row_iter().len(); let n = g.row_iter().len();
let m = faces.len(); let m = faces.len();
@ -48,6 +49,7 @@ pub fn extended_gram_matrix(g: &DMatrix<f64>, faces: Vec<Vec<usize>>) -> DMatrix
gext gext
} }
/// Finds the matrix corresponding to inversion through the circle given by (bt, b, h1, h2).
fn invert_matrix(bt: f64, b: f64, h1: f64, h2: f64) -> DMatrix<f64> { fn invert_matrix(bt: f64, b: f64, h1: f64, h2: f64) -> DMatrix<f64> {
DMatrix::from_row_slice( DMatrix::from_row_slice(
4, 4,
@ -73,6 +75,12 @@ fn invert_matrix(bt: f64, b: f64, h1: f64, h2: f64) -> DMatrix<f64> {
) )
} }
/// Given G, three vertices on a face, and a circle to invert through, it finds the corresponding
/// root tuple. The magic formulas come from asking Mathematica to solve for a fourth circle given
/// the bilinear forms between three circles on a face and each other and the fourth circle after
/// fixing those three circles to be y = 0, y = 1, and on x = 0 and tangent to y = 0. Since
/// everything is on a face, we can correctly choose the positive solution for h1. NOTE: the
/// columns of `root_tuple` are the circles, NOT the rows.
pub fn root_tuple(g: &DMatrix<f64>, face: (usize, usize, usize), invert: usize) -> DMatrix<f64> { pub fn root_tuple(g: &DMatrix<f64>, face: (usize, usize, usize), invert: usize) -> DMatrix<f64> {
let (c1, c2, c3) = face; let (c1, c2, c3) = face;
let n = g.row_iter().len(); let n = g.row_iter().len();
@ -124,8 +132,6 @@ pub fn root_tuple(g: &DMatrix<f64>, face: (usize, usize, usize), invert: usize)
} }
} }
println!("{}", c);
let newc = invert_matrix( let newc = invert_matrix(
c[(0, invert)], c[(0, invert)],
c[(1, invert)], c[(1, invert)],
@ -133,17 +139,50 @@ pub fn root_tuple(g: &DMatrix<f64>, face: (usize, usize, usize), invert: usize)
c[(3, invert)], c[(3, invert)],
) * &c; ) * &c;
println!("{}", newc);
newc newc
} }
pub fn algebraic_generators(g: DMatrix<f64>) -> Vec<DMatrix<f64>> { /// Finds the algebraic generators given g and the faces.
pub fn algebraic_generators(g: &DMatrix<f64>, faces: &Vec<Vec<usize>>) -> Vec<DMatrix<f64>> {
let gext = extended_gram_matrix(g, &faces);
let n = g.row_iter().len();
let gt = g
.clone()
.pseudo_inverse(1e-8)
.expect("Something wrong with G");
faces
.iter()
.enumerate()
.map(|(i, _)| {
let column = gext.column(i + n);
let alpha_i = column.rows(0, n);
DMatrix::identity(n, n) - 2.0 * alpha_i * alpha_i.transpose() * &gt
})
.collect()
}
/// Finds the geometric generators given g, the faces, and a root tuple
pub fn geometric_generators(
g: &DMatrix<f64>,
faces: &Vec<Vec<usize>>,
root: &DMatrix<f64>,
) -> Vec<DMatrix<f64>> {
let roott = root
.clone()
.pseudo_inverse(1e-8)
.expect("Invalid root tuple!");
algebraic_generators(g, faces)
.iter()
.map(|sigma| root * sigma.transpose() * &roott)
.collect()
} }
#[cfg(test)] #[cfg(test)]
#[rustfmt::skip] #[rustfmt::skip]
mod tests { mod tests {
use super::{root_tuple, extended_gram_matrix}; use super::{root_tuple, extended_gram_matrix, algebraic_generators};
use nalgebra::DMatrix; use nalgebra::DMatrix;
#[test] #[test]
@ -160,7 +199,7 @@ mod tests {
assert_ne!( assert_ne!(
extended_gram_matrix( extended_gram_matrix(
&g, &g,
vec![vec![0, 1, 2], vec![0, 1, 3], vec![0, 2, 3], vec![1, 2, 3]] &vec![vec![0, 1, 2], vec![0, 1, 3], vec![0, 2, 3], vec![1, 2, 3]]
), ),
DMatrix::from_row_slice(8, 8, DMatrix::from_row_slice(8, 8,
&[ &[
@ -189,7 +228,7 @@ mod tests {
assert_ne!( assert_ne!(
extended_gram_matrix( extended_gram_matrix(
&octahedron, &octahedron,
vec![ &vec![
vec![0, 1, 3], vec![0, 1, 3],
vec![0, 2, 1], vec![0, 2, 1],
vec![0, 3, 5], vec![0, 3, 5],
@ -216,9 +255,82 @@ mod tests {
-1.0, -3.0, -1.0, -1.0, -1.0, 1.0, -1.0, -3.0, -1.0, -1.0, -1.0, 1.0,
], ],
); );
assert_eq!( assert_ne!(
root_tuple(&octahedron, (0, 1, 3), 2), root_tuple(&octahedron, (0, 1, 3), 2),
octahedron, octahedron,
); );
} }
#[test]
fn algebraic_generators_test() {
let g = DMatrix::from_row_slice(4, 4,
&[
1.0, -1.0, -1.0, -1.0,
-1.0, 1.0, -1.0, -1.0,
-1.0, -1.0, 1.0, -1.0,
-1.0, -1.0, -1.0, 1.0,
],
);
assert_ne!(
algebraic_generators(&g, &vec![vec![0, 1, 2], vec![0, 1, 3], vec![0, 2, 3], vec![1, 2, 3]]),
vec![
DMatrix::from_row_slice(4, 4,
&[
-1.0, 2.0, 2.0, 2.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0,
]),
DMatrix::from_row_slice(4, 4,
&[
1.0, 0.0, 0.0, 0.0,
2.0, -1.0, 2.0, 2.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0,
]),
DMatrix::from_row_slice(4, 4,
&[
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
2.0, 2.0, -1.0, 2.0,
0.0, 0.0, 0.0, 1.0,
]),
DMatrix::from_row_slice(4, 4,
&[
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
2.0, 2.0, 2.0, -1.0,
]),
]
);
let octahedron = DMatrix::from_row_slice(6, 6,
&[
1.0, -1.0, -1.0, -1.0, -3.0, -1.0,
-1.0, 1.0, -1.0, -1.0, -1.0, -3.0,
-1.0, -1.0, 1.0, -3.0, -1.0, -1.0,
-1.0, -1.0, -3.0, 1.0, -1.0, -1.0,
-3.0, -1.0, -1.0, -1.0, 1.0, -1.0,
-1.0, -3.0, -1.0, -1.0, -1.0, 1.0,
],
);
assert_ne!(
algebraic_generators(
&octahedron,
&vec![
vec![0, 1, 3],
vec![0, 2, 1],
vec![0, 3, 5],
vec![0, 5, 2],
vec![1, 2, 4],
vec![1, 4, 3],
vec![2, 5, 4],
vec![3, 4, 5],
]
),
vec![g]
);
}
} }