diff --git a/app-proto/main.css b/app-proto/main.css index a00d309..7981285 100644 --- a/app-proto/main.css +++ b/app-proto/main.css @@ -184,7 +184,6 @@ details[open]:has(li) .element-switch::after { #diagnostics-bar { display: flex; - gap: 8px; } #realization-status { @@ -208,14 +207,6 @@ details[open]:has(li) .element-switch::after { content: '⚠'; } -#step-input > label { - padding-right: 4px; -} - -#step-input > input { - width: 45px; -} - .diagnostics-panel { margin-top: 10px; min-height: 180px; diff --git a/app-proto/src/assembly.rs b/app-proto/src/assembly.rs index 669c0d0..94e7b3c 100644 --- a/app-proto/src/assembly.rs +++ b/app-proto/src/assembly.rs @@ -534,7 +534,6 @@ pub struct Assembly { // realization diagnostics pub realization_status: Signal>, pub descent_history: Signal, - pub step: Signal, } impl Assembly { @@ -548,33 +547,20 @@ impl Assembly { realization_trigger: create_signal(()), realization_status: create_signal(Ok(())), descent_history: create_signal(DescentHistory::new()), - step: create_signal(SpecifiedValue::from_empty_spec()), }; // realize the assembly whenever the element list, the regulator list, // a regulator's set point, or the realization trigger is updated - let assembly_for_realization = assembly.clone(); + let assembly_for_effect = assembly.clone(); create_effect(move || { - assembly_for_realization.elements.track(); - assembly_for_realization.regulators.with( + assembly_for_effect.elements.track(); + assembly_for_effect.regulators.with( |regs| for reg in regs { reg.set_point().track(); } ); - assembly_for_realization.realization_trigger.track(); - assembly_for_realization.realize(); - }); - - // load a configuration from the descent history whenever the active - // step is updated - let assembly_for_step_selection = assembly.clone(); - create_effect(move || { - if let Some(step) = assembly.step.with(|n| n.value) { - let config = assembly.descent_history.with_untracked( - |history| history.config[step as usize].clone() - ); - assembly_for_step_selection.load_config(&config) - } + assembly_for_effect.realization_trigger.track(); + assembly_for_effect.realize(); }); assembly @@ -661,16 +647,6 @@ impl Assembly { }); } - // --- updating the configuration --- - - pub fn load_config(&self, config: &DMatrix) { - for elt in self.elements.get_clone_untracked() { - elt.representation().update( - |rep| rep.set_column(0, &config.column(elt.column_index().unwrap())) - ); - } - } - // --- realization --- pub fn realize(&self) { @@ -720,12 +696,11 @@ impl Assembly { console_log!("Loss: {}", history.scaled_loss.last().unwrap()); } - // report the descent history - let step_cnt = history.config.len(); + // report the loss history self.descent_history.set(history); match result { - Ok(ConfigNeighborhood { nbhd: tangent, .. }) => { + Ok(ConfigNeighborhood { config, nbhd: tangent }) => { /* DEBUG */ // report the tangent dimension console_log!("Tangent dimension: {}", tangent.dim()); @@ -733,15 +708,12 @@ impl Assembly { // report the realization status self.realization_status.set(Ok(())); - // display the last realization step - self.step.set( - if step_cnt > 0 { - let last_step = step_cnt - 1; - SpecifiedValue::try_from(last_step.to_string()).unwrap() - } else { - SpecifiedValue::from_empty_spec() - } - ); + // read out the solution + for elt in self.elements.get_clone_untracked() { + elt.representation().update( + |rep| rep.set_column(0, &config.column(elt.column_index().unwrap())) + ); + } // save the tangent space self.tangent.set_silent(tangent); @@ -751,10 +723,7 @@ impl Assembly { // setting the status to has a different type than the // `Err(message)` we received from the match: we're changing the // `Ok` type from `Realization` to `()` - self.realization_status.set(Err(message)); - - // display the initial guess - self.step.set(SpecifiedValue::from(Some(0.0))); + self.realization_status.set(Err(message)) }, } } diff --git a/app-proto/src/components/diagnostics.rs b/app-proto/src/components/diagnostics.rs index 51d58f1..e265982 100644 --- a/app-proto/src/components/diagnostics.rs +++ b/app-proto/src/components/diagnostics.rs @@ -7,7 +7,7 @@ use charming::{ }; use sycamore::prelude::*; -use crate::{AppState, specified::SpecifiedValue}; +use crate::AppState; #[derive(Clone)] struct DiagnosticsState { @@ -48,69 +48,6 @@ fn RealizationStatus() -> View { } } -// history step input -#[component] -fn StepInput() -> View { - // get the assembly - let state = use_context::(); - let assembly = state.assembly; - - // the `last_step` signal holds the index of the last step - let last_step = assembly.descent_history.map( - |history| match history.config.len() { - 0 => None, - n => Some(n - 1), - } - ); - let input_max = last_step.map(|last| last.unwrap_or(0)); - - // these signals hold the entered step number - let value = create_signal(String::new()); - let value_as_number = create_signal(0.0); - - create_effect(move || { - value.set(assembly.step.with(|n| n.spec.clone())); - }); - - view! { - div(id = "step-input") { - label { "Step" } - input( - r#type = "number", - min = "0", - max = input_max.with(|max| max.to_string()), - bind:value = value, - bind:valueAsNumber = value_as_number, - on:change = move |_| { - if last_step.with(|last| last.is_some()) { - // clamp the step within its allowed range. the lower - // bound is redundant on browsers that make it - // impossible to type negative values into a number - // input with a non-negative `min`, but there's no harm - // in being careful - let step_raw = value.with( - |val| SpecifiedValue::try_from(val.clone()) - .unwrap_or(SpecifiedValue::from_empty_spec() - ) - ); - let step = SpecifiedValue::from( - step_raw.value.map( - |val| val.clamp(0.0, input_max.get() as f64) - ) - ); - - // set the input string and the assembly's active step - value.set(step.spec.clone()); - assembly.step.set(step); - } else { - value.set(String::new()); - } - }, - ) - } - } -} - fn into_log10_time_point((step, value): (usize, f64)) -> Vec> { vec![ Some(step as f64), @@ -311,7 +248,6 @@ pub fn Diagnostics() -> View { option(value = "loss") { "Loss" } option(value = "spectrum") { "Spectrum" } } - StepInput {} } DiagnosticsPanel(name = "loss") { LossHistory {} } DiagnosticsPanel(name = "spectrum") { SpectrumHistory {} } diff --git a/app-proto/src/components/display.rs b/app-proto/src/components/display.rs index 98be85e..da921dd 100644 --- a/app-proto/src/components/display.rs +++ b/app-proto/src/components/display.rs @@ -588,25 +588,7 @@ pub fn Display() -> View { location_z *= (time_step * ZOOM_SPEED * zoom).exp(); // manipulate the assembly - /* KLUDGE */ - // to avoid the complexity of making tangent space projection - // conditional and dealing with unnormalized representation vectors, - // we only allow manipulation when we're looking at the last step of - // a successful realization - let realization_successful = state.assembly.realization_status.with( - |status| status.is_ok() - ); - let step_val = state.assembly.step.with_untracked(|step| step.value); - let on_init_step = step_val.is_some_and(|n| n == 0.0); - let on_last_step = step_val.is_some_and( - |n| state.assembly.descent_history.with_untracked( - |history| n as usize + 1 == history.config.len().max(1) - ) - ); - let on_manipulable_step = - !realization_successful && on_init_step - || realization_successful && on_last_step; - if on_manipulable_step && state.selection.with(|sel| sel.len() == 1) { + if state.selection.with(|sel| sel.len() == 1) { let sel = state.selection.with( |sel| sel.into_iter().next().unwrap().clone() ); diff --git a/app-proto/src/engine.rs b/app-proto/src/engine.rs index ef150a0..d033c01 100644 --- a/app-proto/src/engine.rs +++ b/app-proto/src/engine.rs @@ -353,7 +353,7 @@ fn seek_better_config( // a first-order neighborhood of a configuration pub struct ConfigNeighborhood { - #[cfg(feature = "dev")] pub config: DMatrix, + pub config: DMatrix, pub nbhd: ConfigSubspace, } @@ -388,7 +388,7 @@ pub fn realize_gram( if assembly_dim == 0 { let result = Ok( ConfigNeighborhood { - #[cfg(feature = "dev")] config: guess.clone(), + config: guess.clone(), nbhd: ConfigSubspace::zero(0), } ); @@ -509,7 +509,7 @@ pub fn realize_gram( // find the kernel of the Hessian. give it the uniform inner product let tangent = ConfigSubspace::symmetric_kernel(hess, unif_to_std, assembly_dim); - Ok(ConfigNeighborhood { #[cfg(feature = "dev")] config: state.config, nbhd: tangent }) + Ok(ConfigNeighborhood { config: state.config, nbhd: tangent }) } else { Err("Failed to reach target accuracy".to_string()) }; diff --git a/app-proto/src/specified.rs b/app-proto/src/specified.rs index b0f04b5..788460b 100644 --- a/app-proto/src/specified.rs +++ b/app-proto/src/specified.rs @@ -26,17 +26,6 @@ impl SpecifiedValue { } } -// a `SpecifiedValue` can be constructed from a floating-point option, which is -// given a canonical specification -impl From> for SpecifiedValue { - fn from(value: Option) -> Self { - match value { - Some(x) => SpecifiedValue{ spec: x.to_string(), value }, - None => SpecifiedValue::from_empty_spec(), - } - } -} - // a `SpecifiedValue` can be constructed from a specification string, formatted // as described in the comment on the structure definition. the result is `Ok` // if the specification is properly formatted, and `Error` if not