Skip to content

Commit

Permalink
working on compare
Browse files Browse the repository at this point in the history
  • Loading branch information
Bruno02468 committed May 1, 2024
1 parent e9cc836 commit 54b89f8
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 31 deletions.
12 changes: 11 additions & 1 deletion f06/src/blocks/compare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,16 @@ pub enum DisjunctionBehaviour {
Flag
}

impl Display for DisjunctionBehaviour {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
return write!(f, "{}", match self {
DisjunctionBehaviour::Skip => "skip",
DisjunctionBehaviour::AssumeZeroes => "assume zeros",
DisjunctionBehaviour::Flag => "flag",
});
}
}

impl Default for DisjunctionBehaviour {
fn default() -> Self {
return Self::AssumeZeroes;
Expand Down Expand Up @@ -219,7 +229,7 @@ pub struct FoundValues {
}

/// The reason a value was flagged.
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq)]
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, PartialOrd)]
pub enum FlagReason {
/// Flagged due to an absolute difference.
Difference {
Expand Down
6 changes: 4 additions & 2 deletions f06/src/f06file/extraction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ impl Error for ExtractionError {}
/// This structure represents a way to extract a subset of the data from an F06
/// so one can apply comparison criteria to it.
#[derive(
Debug, Clone, Serialize, Deserialize, PartialOrd, Ord, PartialEq, Eq, Default
Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default
)]
pub struct Extraction {
/// Subcases to get data from.
Expand All @@ -265,7 +265,9 @@ pub struct Extraction {
/// Column filter (for when you want very specific data).
pub cols: Specifier<NasIndex>,
/// Raw column filter (for ease of separation).
pub raw_cols: Specifier<usize>
pub raw_cols: Specifier<usize>,
/// What to do in case of disjunctions.
pub dxn: DisjunctionBehaviour
}

impl Extraction {
Expand Down
63 changes: 61 additions & 2 deletions nastester/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
//! fully-interactive (like the GUI).
use std::collections::BTreeMap;
use std::collections::BTreeSet;
use std::collections::VecDeque;
use std::path::PathBuf;
use std::sync::atomic::AtomicUsize;
Expand All @@ -11,6 +12,8 @@ use std::sync::Mutex;
use std::thread;

use f06::prelude::*;
use rayon::iter::IntoParallelRefIterator;
use rayon::iter::ParallelIterator;
use serde::Deserialize;
use serde::Serialize;
use uuid::Uuid;
Expand Down Expand Up @@ -238,15 +241,71 @@ impl AppState {
} else {
self.runner.max_jobs
};
for jn in 0..4 {
for jn in 0..nt {
if self.runner.current_jobs.load(relaxed) < nt {
let queue = self.runner.job_queue.clone();
let job_count = self.runner.current_jobs.clone();
thread::Builder::new()
.name(format!("job_runner_{}", jn+1))
.spawn(move || runner(queue, job_count))
.expect("failed to spawn thread");
.expect("failed to spawn runner thread");
}
}
}

/// Re-computes the flagged values for a deck.
pub(crate) fn recompute_flagged(&mut self, deck: Uuid) {
let critsets = self.suite.criteria_sets.clone();
if let Some((deck, results_mtx)) = self.get_deck(deck) {
let mut results = results_mtx.lock().expect("mutex poisoned");
results.flagged.clear();
let pair = (&results.ref_f06, &results.test_f06);
if let (RunState::Finished(r), RunState::Finished(t)) = pair {
for (exn, crit_uuid) in deck.extractions.iter() {
if let Some(critset) = crit_uuid.and_then(|u| critsets.get(&u)) {
let in_ref = exn.lookup(r).collect::<BTreeSet<_>>();
let in_test = exn.lookup(t).collect::<BTreeSet<_>>();
let in_either = in_ref.union(&in_test).collect::<BTreeSet<_>>();
let dxn = in_ref.symmetric_difference(&in_test)
.collect::<BTreeSet<_>>();
let mut flagged: BTreeSet<DatumIndex> = BTreeSet::new();
if exn.dxn == DisjunctionBehaviour::Flag {
flagged.extend(dxn);
}
let get = |f: &F06File, ix: &DatumIndex| -> Option<F06Number> {
let v = ix.get_from(f);
if v.is_err() && exn.dxn == DisjunctionBehaviour::AssumeZeroes {
return Some(0.0.into());
} else {
return Some(v.unwrap());
}
};
for ix in in_either {
let val_ref = get(r, ix);
let val_test = get(t, ix);
if let (Some(rv), Some(tv)) = (val_ref, val_test) {
if critset.criteria.check(rv.into(), tv.into()).is_some() {
flagged.insert(*ix);
}
}
}
results_mtx.lock().expect("poisoned").flagged.push(Some(flagged));
} else {
results_mtx.lock().expect("mutex poisoned").flagged.push(None);
}
}
}
}
}

/// Re-computes all flagged values in a background thread.
pub(crate) fn recompute_all_flagged(&mut self) {
let decks = self.suite.decks.keys().cloned().collect::<Vec<_>>();
let mref = Arc::new(Mutex::new(self));
decks.par_iter()
.map(|u| (u, mref.clone()))
.for_each(|(u, s)| {
if let Ok(mut s) = s.lock() { s.recompute_flagged(*u); }
})
}
}
92 changes: 67 additions & 25 deletions nastester/src/gui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::path::PathBuf;
use std::str::FromStr;

use egui::{
Align, Color32, ComboBox, DragValue, Id, Layout, TextStyle, Ui, Visuals, WidgetText
Align, Color32, ComboBox, Context, DragValue, Id, Layout, TextStyle, Ui, Visuals, WidgetText
};
use egui_extras::{Column, TableBuilder};
use f06::blocks::types::BlockType;
Expand All @@ -34,8 +34,10 @@ pub(crate) enum View {
Solvers,
/// The criteria sets.
CriteriaSets,
/// A specific deck.
Deck(Uuid),
/// A specific deck's extractions.
Extractions(Uuid),
/// A deck's side-by-side results.
Results(Uuid, Option<usize>)
}

/// This struct rerpresents the GUI.
Expand Down Expand Up @@ -409,7 +411,7 @@ impl Gui {
}

/// Render function for the menu bar.
fn show_menu(&mut self, ctx: &egui::Context, ui: &mut Ui) {
fn show_menu(&mut self, ctx: &Context, ui: &mut Ui) {
egui::menu::bar(ui, |ui| {
// suite menu
ui.menu_button("Suite", |ui| {
Expand Down Expand Up @@ -509,6 +511,10 @@ impl Gui {
} else if ui.button("Change to dark mode").clicked() {
ctx.set_visuals(Visuals::dark());
}
// recompute flags
if ui.button("Recompute flags").clicked() {
self.state.recompute_all_flagged();
}
// dump app state
if ui.button("Dump app state").clicked() {
info!("User-requested dump of app state:\n{:#?}", self);
Expand All @@ -526,15 +532,16 @@ impl Gui {
}

/// Render function for the global decks list.
fn view_decks(&mut self, ctx: &egui::Context) {
fn view_decks(&mut self, ctx: &Context) {
// one per deck
let deck_data = self.state.decks_by_name()
.map(|(u, d, r)| (u, d.clone(), r))
.collect::<Vec<_>>();
egui::CentralPanel::default().show(ctx, |ui| {
self.show_menu(ctx, ui);
let heading_height = ui.text_style_height(&TextStyle::Heading);
let body_height = ui.text_style_height(&TextStyle::Body);
let dy = ui.spacing().item_spacing.y;
let body_height = ui.text_style_height(&TextStyle::Body) + dy;
let mut cells = Layout::left_to_right(Align::Center);
cells.main_wrap = false;
let ndecks = deck_data.len();
Expand Down Expand Up @@ -573,11 +580,13 @@ impl Gui {
.column(Column::auto().resizable(true))
.column(Column::auto().resizable(true))
.column(Column::auto().resizable(true))
.column(Column::auto().resizable(true))
.header(heading_height, |mut header| {
header.col(|ui| { ui.heading("File name"); });
header.col(|ui| { ui.heading("Status"); });
header.col(|ui| { ui.heading("Reference run"); });
header.col(|ui| { ui.heading("Test run"); });
header.col(|ui| { ui.heading("Flagged"); });
header.col(|ui| { ui.heading("Actions"); });
})
.body(|body| {
Expand Down Expand Up @@ -622,6 +631,16 @@ impl Gui {
row.col(|ui| lblres(ui, &handle.ref_f06));
// test run
row.col(|ui| lblres(ui, &handle.test_f06));
// flags
row.col(|ui| {
let nflags: usize = handle.flagged
.iter()
.map(|v| match v {
Some(ref m) => m.len(),
None => 0,
}).sum();
ui.label(format!("{} values", nflags));
});
} else {
// reference run
row.col(|ui| lblres(ui, &RunState::Running));
Expand All @@ -637,8 +656,8 @@ impl Gui {
// actions
row.col(|ui| {
ui.horizontal(|ui| {
if ui.button("Configure").clicked() {
self.switch_to(View::Deck(*uuid));
if ui.button("Extractions...").clicked() {
self.switch_to(View::Extractions(*uuid));
}
if ui.button("Remove").clicked() {
self.state.suite.decks.remove(uuid);
Expand All @@ -653,9 +672,10 @@ impl Gui {
}

/// Render function for a single deck, its extractions, etcetera.
fn view_deck(&mut self, ctx: &egui::Context, uuid: Uuid) {
fn view_deck_exns(&mut self, ctx: &Context, uuid: Uuid) {
if self.state.suite.decks.contains_key(&uuid) {
let exns_ui = |ui: &mut Ui| {
self.show_menu(ctx, ui);
ui.vertical_centered(|ui| {
ui.strong("Deck extractions:");
if ui.button("Add new").clicked() {
Expand All @@ -676,12 +696,14 @@ impl Gui {
.column(Column::remainder().resizable(true))
.column(Column::remainder().resizable(true))
.column(Column::remainder().resizable(true))
.column(Column::remainder().resizable(true))
.header(heading_height, |mut header| {
header.col(|ui| { ui.label("nº"); });
header.col(|ui| { ui.label("blocks"); });
header.col(|ui| { ui.label("subcases"); });
header.col(|ui| { ui.label("nodes"); });
header.col(|ui| { ui.label("elements"); });
header.col(|ui| { ui.label("on disjunction"); });
header.col(|ui| { ui.label("criteria"); });
})
.body(|mut body| {
Expand All @@ -699,7 +721,6 @@ impl Gui {
].into_iter().max().unwrap() + 1;
let est_height = max_exn_lens as f32 * item_height;
body.row(est_height, |mut row| {
let mut new_height = body_height;
row.col(|ui| { ui.label(&i.to_string()); });
row.col(|ui| {
self.combo_specifier(
Expand All @@ -717,23 +738,38 @@ impl Gui {
.extractions.get_mut(i).expect("bad extraction index!")
.0.subcases
);
new_height = new_height.max(ui.min_rect().height());
});
row.col(|ui| {
self.text_specifier(ui, |s| &mut s.state
.suite.decks.get_mut(&uuid).expect("deck UUID missing!")
.extractions.get_mut(i).expect("bad extraction index!")
.0.grid_points
);
new_height = new_height.max(ui.min_rect().height());
});
row.col(|ui| {
self.text_specifier(ui, |s| &mut s.state
.suite.decks.get_mut(&uuid).expect("deck UUID missing!")
.extractions.get_mut(i).expect("bad extraction index!")
.0.elements
);
new_height = new_height.max(ui.min_rect().height());
});
row.col(|ui| {
let dxn = &mut self.state
.suite.decks.get_mut(&uuid).expect("deck UUID missing!")
.extractions.get_mut(i).expect("bad extraction index!")
.0.dxn;
ComboBox::from_id_source(ui.next_auto_id())
.selected_text(dxn.to_string())
.show_ui(ui, |ui| {
let all = [
DisjunctionBehaviour::AssumeZeroes,
DisjunctionBehaviour::Skip,
DisjunctionBehaviour::Flag
];
for db in all {
ui.selectable_value(dxn, db, db.to_string());
}
});
});
row.col(|ui| {
ComboBox::from_id_source(ui.next_auto_id())
Expand All @@ -744,11 +780,17 @@ impl Gui {
.map(|c| c.name.clone())
.expect("critset UUID missing"))
).show_ui(ui, |ui| {
let crit_mut = &mut self.state.suite.decks.get_mut(&uuid).unwrap().extractions.get_mut(i).unwrap().1;
let crit_mut = &mut self.state.suite.decks
.get_mut(&uuid).unwrap()
.extractions.get_mut(i).unwrap().1;
ui.selectable_value(crit_mut, None, "<none>");
let critsets = self.state.suite.criteria_sets.iter();
for (uuid, crit) in critsets {
ui.selectable_value(crit_mut, Some(*uuid), &crit.name);
ui.selectable_value(
crit_mut,
Some(*uuid),
&crit.name
);
}
});
});
Expand All @@ -757,13 +799,7 @@ impl Gui {
})
})
};
egui::TopBottomPanel::bottom("deck_extractions")
.resizable(true)
.show_separator_line(true)
.show(ctx, exns_ui);
egui::CentralPanel::default().show(ctx, |ui| {
self.show_menu(ctx, ui);
});
egui::CentralPanel::default().show(ctx, exns_ui);
} else {
egui::CentralPanel::default().show(ctx, |ui| {
self.show_menu(ctx, ui);
Expand All @@ -774,7 +810,7 @@ impl Gui {
}

/// Render function for the criteria set list.
fn view_criteria_sets(&mut self, ctx: &egui::Context) {
fn view_criteria_sets(&mut self, ctx: &Context) {
egui::CentralPanel::default().show(ctx, |ui| {
self.show_menu(ctx, ui);
let heading_height = ui.text_style_height(&TextStyle::Heading);
Expand Down Expand Up @@ -895,18 +931,24 @@ impl Gui {
}
});
}

/// Render function for a deck's results, side-by-side.
fn view_results(&mut self, _ctx: &Context, _d: Uuid, _exn: Option<usize>) {

}
}

impl eframe::App for Gui {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
fn update(&mut self, ctx: &Context, _frame: &mut eframe::Frame) {
//if cfg!(debug_assertions) {
// ctx.set_debug_on_hover(true);
//}
match self.view {
View::Decks => self.view_decks(ctx),
View::Solvers => todo!(),
View::CriteriaSets => self.view_criteria_sets(ctx),
View::Deck(uuid) => self.view_deck(ctx, uuid),
View::Extractions(uuid) => self.view_deck_exns(ctx, uuid),
View::Results(uuid, n) => self.view_results(ctx, uuid, n)
};
}
}
Loading

0 comments on commit 54b89f8

Please sign in to comment.