Improve naming in realization output structures

This commit is contained in:
Aaron Fenyes 2025-07-18 12:16:40 -07:00
parent 477d6a5064
commit f1865f85a1
7 changed files with 53 additions and 47 deletions

View file

@ -2,14 +2,14 @@
use nalgebra::DMatrix; use nalgebra::DMatrix;
use dyna3::engine::{Q, DescentHistory, RealizationResult}; use dyna3::engine::{Q, DescentHistory, Realization};
pub fn title(title: &str) { pub fn title(title: &str) {
println!("─── {title} ───"); println!("─── {title} ───");
} }
pub fn realization_diagnostics(realization_result: &RealizationResult) { pub fn realization_diagnostics(realization: &Realization) {
let RealizationResult { result, history } = realization_result; let Realization { result, history } = realization;
println!(); println!();
if let Err(ref message) = result { if let Err(ref message) = result {
println!("❌️ {message}"); println!("❌️ {message}");

View file

@ -1,14 +1,14 @@
#[path = "common/print.rs"] #[path = "common/print.rs"]
mod print; mod print;
use dyna3::engine::{Realization, examples::realize_irisawa_hexlet}; use dyna3::engine::{ConfigNeighborhood, examples::realize_irisawa_hexlet};
fn main() { fn main() {
const SCALED_TOL: f64 = 1.0e-12; const SCALED_TOL: f64 = 1.0e-12;
let realization_result = realize_irisawa_hexlet(SCALED_TOL); let realization = realize_irisawa_hexlet(SCALED_TOL);
print::title("Irisawa hexlet"); print::title("Irisawa hexlet");
print::realization_diagnostics(&realization_result); print::realization_diagnostics(&realization);
if let Ok(Realization { config, .. }) = realization_result.result { if let Ok(ConfigNeighborhood { config, .. }) = realization.result {
// print the diameters of the chain spheres // print the diameters of the chain spheres
println!("\nChain diameters:"); println!("\nChain diameters:");
println!(" {} sun (given)", 1.0 / config[(3, 3)]); println!(" {} sun (given)", 1.0 / config[(3, 3)]);
@ -19,5 +19,5 @@ fn main() {
// print the completed Gram matrix // print the completed Gram matrix
print::gram_matrix(&config); print::gram_matrix(&config);
} }
print::loss_history(&realization_result.history); print::loss_history(&realization.history);
} }

View file

@ -3,14 +3,14 @@ mod print;
use nalgebra::{DMatrix, DVector}; use nalgebra::{DMatrix, DVector};
use dyna3::engine::{Realization, examples::realize_kaleidocycle}; use dyna3::engine::{ConfigNeighborhood, examples::realize_kaleidocycle};
fn main() { fn main() {
const SCALED_TOL: f64 = 1.0e-12; const SCALED_TOL: f64 = 1.0e-12;
let realization_result = realize_kaleidocycle(SCALED_TOL); let realization = realize_kaleidocycle(SCALED_TOL);
print::title("Kaleidocycle"); print::title("Kaleidocycle");
print::realization_diagnostics(&realization_result); print::realization_diagnostics(&realization);
if let Ok(Realization { config, tangent }) = realization_result.result { if let Ok(ConfigNeighborhood { config, nbhd: tangent }) = realization.result {
// print the completed Gram matrix and the realized configuration // print the completed Gram matrix and the realized configuration
print::gram_matrix(&config); print::gram_matrix(&config);
print::config(&config); print::config(&config);

View file

@ -5,8 +5,8 @@ use dyna3::engine::{
point, point,
realize_gram, realize_gram,
sphere, sphere,
ConstraintProblem, ConfigNeighborhood,
Realization ConstraintProblem
}; };
fn main() { fn main() {
@ -20,14 +20,14 @@ fn main() {
} }
} }
problem.frozen.push(3, 0, problem.guess[(3, 0)]); problem.frozen.push(3, 0, problem.guess[(3, 0)]);
let realization_result = realize_gram( let realization = realize_gram(
&problem, 1.0e-12, 0.5, 0.9, 1.1, 200, 110 &problem, 1.0e-12, 0.5, 0.9, 1.1, 200, 110
); );
print::title("Point on a sphere"); print::title("Point on a sphere");
print::realization_diagnostics(&realization_result); print::realization_diagnostics(&realization);
if let Ok(Realization{ config, .. }) = realization_result.result { if let Ok(ConfigNeighborhood{ config, .. }) = realization.result {
print::gram_matrix(&config); print::gram_matrix(&config);
print::config(&config); print::config(&config);
} }
print::loss_history(&realization_result.history); print::loss_history(&realization.history);
} }

View file

@ -1,7 +1,12 @@
#[path = "common/print.rs"] #[path = "common/print.rs"]
mod print; mod print;
use dyna3::engine::{realize_gram, sphere, ConstraintProblem, Realization}; use dyna3::engine::{
realize_gram,
sphere,
ConfigNeighborhood,
ConstraintProblem
};
fn main() { fn main() {
let mut problem = ConstraintProblem::from_guess({ let mut problem = ConstraintProblem::from_guess({
@ -17,13 +22,13 @@ fn main() {
problem.gram.push_sym(j, k, if j == k { 1.0 } else { -1.0 }); problem.gram.push_sym(j, k, if j == k { 1.0 } else { -1.0 });
} }
} }
let realization_result = realize_gram( let realization = realize_gram(
&problem, 1.0e-12, 0.5, 0.9, 1.1, 200, 110 &problem, 1.0e-12, 0.5, 0.9, 1.1, 200, 110
); );
print::title("Three spheres"); print::title("Three spheres");
print::realization_diagnostics(&realization_result); print::realization_diagnostics(&realization);
if let Ok(Realization{ config, .. }) = realization_result.result { if let Ok(ConfigNeighborhood{ config, .. }) = realization.result {
print::gram_matrix(&config); print::gram_matrix(&config);
} }
print::loss_history(&realization_result.history); print::loss_history(&realization.history);
} }

View file

@ -23,11 +23,11 @@ use crate::{
project_sphere_to_normalized, project_sphere_to_normalized,
realize_gram, realize_gram,
sphere, sphere,
ConfigNeighborhood,
ConfigSubspace, ConfigSubspace,
ConstraintProblem, ConstraintProblem,
DescentHistory, DescentHistory,
Realization, Realization
RealizationResult
}, },
outline::OutlineItem, outline::OutlineItem,
specified::SpecifiedValue specified::SpecifiedValue
@ -696,7 +696,7 @@ impl Assembly {
console_log!("Old configuration:{:>8.3}", problem.guess); console_log!("Old configuration:{:>8.3}", problem.guess);
// look for a configuration with the given Gram matrix // look for a configuration with the given Gram matrix
let RealizationResult { result, history } = realize_gram( let Realization { result, history } = realize_gram(
&problem, 1.0e-12, 0.5, 0.9, 1.1, 200, 110 &problem, 1.0e-12, 0.5, 0.9, 1.1, 200, 110
); );
@ -714,7 +714,7 @@ impl Assembly {
self.descent_history.set(history); self.descent_history.set(history);
match result { match result {
Ok(Realization { config, tangent }) => { Ok(ConfigNeighborhood { config, nbhd: tangent }) => {
/* DEBUG */ /* DEBUG */
// report the tangent dimension // report the tangent dimension
console_log!("Tangent dimension: {}", tangent.dim()); console_log!("Tangent dimension: {}", tangent.dim());

View file

@ -393,13 +393,14 @@ fn seek_better_config(
None None
} }
pub struct Realization { // a first-order neighborhood of a configuration
pub struct ConfigNeighborhood {
pub config: DMatrix<f64>, pub config: DMatrix<f64>,
pub tangent: ConfigSubspace pub nbhd: ConfigSubspace
} }
pub struct RealizationResult { pub struct Realization {
pub result: Result<Realization, String>, pub result: Result<ConfigNeighborhood, String>,
pub history: DescentHistory pub history: DescentHistory
} }
@ -415,7 +416,7 @@ pub fn realize_gram(
reg_scale: f64, reg_scale: f64,
max_descent_steps: i32, max_descent_steps: i32,
max_backoff_steps: i32 max_backoff_steps: i32
) -> RealizationResult { ) -> Realization {
// destructure the problem data // destructure the problem data
let ConstraintProblem { let ConstraintProblem {
gram, guess, frozen gram, guess, frozen
@ -501,7 +502,7 @@ pub fn realize_gram(
*/ */
let hess_cholesky = match hess.clone().cholesky() { let hess_cholesky = match hess.clone().cholesky() {
Some(cholesky) => cholesky, Some(cholesky) => cholesky,
None => return RealizationResult { None => return Realization {
result: Err("Cholesky decomposition failed".to_string()), result: Err("Cholesky decomposition failed".to_string()),
history history
} }
@ -518,7 +519,7 @@ pub fn realize_gram(
state = better_state; state = better_state;
history.backoff_steps.push(backoff_steps); history.backoff_steps.push(backoff_steps);
} else { } else {
return RealizationResult { return Realization {
result: Err("Line search failed".to_string()), result: Err("Line search failed".to_string()),
history history
} }
@ -539,11 +540,11 @@ pub fn realize_gram(
// find the kernel of the Hessian. give it the uniform inner product // find the kernel of the Hessian. give it the uniform inner product
let tangent = ConfigSubspace::symmetric_kernel(hess, unif_to_std, assembly_dim); let tangent = ConfigSubspace::symmetric_kernel(hess, unif_to_std, assembly_dim);
Ok(Realization { config: state.config, tangent }) Ok(ConfigNeighborhood { config: state.config, nbhd: tangent })
} else { } else {
Err("Failed to reach target accuracy".to_string()) Err("Failed to reach target accuracy".to_string())
}; };
RealizationResult{ result, history } Realization { result, history }
} }
// --- tests --- // --- tests ---
@ -562,7 +563,7 @@ pub mod examples {
// "Japan's 'Wasan' Mathematical Tradition", by Abe Haruki // "Japan's 'Wasan' Mathematical Tradition", by Abe Haruki
// https://www.nippon.com/en/japan-topics/c12801/ // https://www.nippon.com/en/japan-topics/c12801/
// //
pub fn realize_irisawa_hexlet(scaled_tol: f64) -> RealizationResult { pub fn realize_irisawa_hexlet(scaled_tol: f64) -> Realization {
let mut problem = ConstraintProblem::from_guess( let mut problem = ConstraintProblem::from_guess(
[ [
sphere(0.0, 0.0, 0.0, 15.0), sphere(0.0, 0.0, 0.0, 15.0),
@ -613,7 +614,7 @@ pub mod examples {
// set up a kaleidocycle, made of points with fixed distances between them, // set up a kaleidocycle, made of points with fixed distances between them,
// and find its tangent space // and find its tangent space
pub fn realize_kaleidocycle(scaled_tol: f64) -> RealizationResult { pub fn realize_kaleidocycle(scaled_tol: f64) -> Realization {
const N_HINGES: usize = 6; const N_HINGES: usize = 6;
let mut problem = ConstraintProblem::from_guess( let mut problem = ConstraintProblem::from_guess(
(0..N_HINGES).step_by(2).flat_map( (0..N_HINGES).step_by(2).flat_map(
@ -737,7 +738,7 @@ mod tests {
} }
problem.frozen.push(3, 0, problem.guess[(3, 0)]); problem.frozen.push(3, 0, problem.guess[(3, 0)]);
problem.frozen.push(3, 1, 0.5); problem.frozen.push(3, 1, 0.5);
let RealizationResult { result, history } = realize_gram( let Realization { result, history } = realize_gram(
&problem, 1.0e-12, 0.5, 0.9, 1.1, 200, 110 &problem, 1.0e-12, 0.5, 0.9, 1.1, 200, 110
); );
let config = result.unwrap().config; let config = result.unwrap().config;
@ -782,10 +783,10 @@ mod tests {
for n in 0..ELEMENT_DIM { for n in 0..ELEMENT_DIM {
problem.frozen.push(n, 0, problem.guess[(n, 0)]); problem.frozen.push(n, 0, problem.guess[(n, 0)]);
} }
let RealizationResult { result, history } = realize_gram( let Realization { result, history } = realize_gram(
&problem, SCALED_TOL, 0.5, 0.9, 1.1, 200, 110 &problem, SCALED_TOL, 0.5, 0.9, 1.1, 200, 110
); );
let Realization { config, tangent } = result.unwrap(); let ConfigNeighborhood { config, nbhd: tangent } = result.unwrap();
assert_eq!(config, problem.guess); assert_eq!(config, problem.guess);
assert_eq!(history.scaled_loss.len(), 1); assert_eq!(history.scaled_loss.len(), 1);
@ -854,8 +855,8 @@ mod tests {
fn tangent_test_kaleidocycle() { fn tangent_test_kaleidocycle() {
// set up a kaleidocycle and find its tangent space // set up a kaleidocycle and find its tangent space
const SCALED_TOL: f64 = 1.0e-12; const SCALED_TOL: f64 = 1.0e-12;
let RealizationResult { result, history } = realize_kaleidocycle(SCALED_TOL); let Realization { result, history } = realize_kaleidocycle(SCALED_TOL);
let Realization { config, tangent } = result.unwrap(); let ConfigNeighborhood { config, nbhd: tangent } = result.unwrap();
assert_eq!(history.scaled_loss.len(), 1); assert_eq!(history.scaled_loss.len(), 1);
// list some motions that should form a basis for the tangent space of // list some motions that should form a basis for the tangent space of
@ -943,10 +944,10 @@ mod tests {
problem_orig.gram.push_sym(0, 0, 1.0); problem_orig.gram.push_sym(0, 0, 1.0);
problem_orig.gram.push_sym(1, 1, 1.0); problem_orig.gram.push_sym(1, 1, 1.0);
problem_orig.gram.push_sym(0, 1, 0.5); problem_orig.gram.push_sym(0, 1, 0.5);
let RealizationResult { result: result_orig, history: history_orig } = realize_gram( let Realization { result: result_orig, history: history_orig } = realize_gram(
&problem_orig, SCALED_TOL, 0.5, 0.9, 1.1, 200, 110 &problem_orig, SCALED_TOL, 0.5, 0.9, 1.1, 200, 110
); );
let Realization { config: config_orig, tangent: tangent_orig } = result_orig.unwrap(); let ConfigNeighborhood { config: config_orig, nbhd: tangent_orig } = result_orig.unwrap();
assert_eq!(config_orig, problem_orig.guess); assert_eq!(config_orig, problem_orig.guess);
assert_eq!(history_orig.scaled_loss.len(), 1); assert_eq!(history_orig.scaled_loss.len(), 1);
@ -964,10 +965,10 @@ mod tests {
guess: guess_tfm, guess: guess_tfm,
frozen: problem_orig.frozen frozen: problem_orig.frozen
}; };
let RealizationResult { result: result_tfm, history: history_tfm } = realize_gram( let Realization { result: result_tfm, history: history_tfm } = realize_gram(
&problem_tfm, SCALED_TOL, 0.5, 0.9, 1.1, 200, 110 &problem_tfm, SCALED_TOL, 0.5, 0.9, 1.1, 200, 110
); );
let Realization { config: config_tfm, tangent: tangent_tfm } = result_tfm.unwrap(); let ConfigNeighborhood { config: config_tfm, nbhd: tangent_tfm } = result_tfm.unwrap();
assert_eq!(config_tfm, problem_tfm.guess); assert_eq!(config_tfm, problem_tfm.guess);
assert_eq!(history_tfm.scaled_loss.len(), 1); assert_eq!(history_tfm.scaled_loss.len(), 1);