diff --git a/lab1/src/algo/mod.rs b/lab1/src/algo/mod.rs index 2b657db..7b2b4da 100644 --- a/lab1/src/algo/mod.rs +++ b/lab1/src/algo/mod.rs @@ -2,4 +2,6 @@ mod board; mod misc; mod simulation; -pub(crate) use board::Board; \ No newline at end of file +pub(crate) use board::Board; +pub(crate) use simulation::AnnealingConfig; +pub(crate) use simulation::simulateAnnealing; \ No newline at end of file diff --git a/lab1/src/algo/simulation.rs b/lab1/src/algo/simulation.rs index 102f259..4ca146f 100644 --- a/lab1/src/algo/simulation.rs +++ b/lab1/src/algo/simulation.rs @@ -2,7 +2,7 @@ use crate::algo::misc::{initializeBoard, isOnDiagonal, swapRandomQueensOnce}; use crate::algo::Board; use eframe::emath::Numeric; -pub(super) fn calculateEnergy(b: &Board) -> f64 { +fn calculateEnergy(b: &Board) -> f64 { let mut conflictsCount = 0usize; for i1 in 0..b.len() { for i2 in (i1 + 1)..b.len() { diff --git a/lab1/src/main.rs b/lab1/src/main.rs index e2e9b4a..9e6fe38 100644 --- a/lab1/src/main.rs +++ b/lab1/src/main.rs @@ -3,6 +3,150 @@ mod algo; -fn main() { +use eframe::egui; +use eframe::egui::Ui; +use eframe::emath::Numeric; +use rand::SeedableRng; +use std::ops::RangeInclusive; +use std::time::{SystemTime, UNIX_EPOCH}; -} \ No newline at end of file +fn main() -> eframe::Result { + let options = eframe::NativeOptions { + viewport: egui::ViewportBuilder::default().with_inner_size([640.0, 400.0]), + ..Default::default() + }; + eframe::run_native( + "Annealing Simulation for Chess Queens Task", + options, + Box::new(|cc| { + // This gives us image support: + // egui_extras::install_image_loaders(&cc.egui_ctx); + + Ok(Box::::default()) + }), + ) +} + +struct MyApp { + simulationConfig: algo::AnnealingConfig, + boardSize: usize, + _isFirstFrame: bool, + result: Option, +} + +impl Default for MyApp { + fn default() -> Self { + Self { + simulationConfig: algo::AnnealingConfig { + initialTemperature: 30.0, + targetTemperature: 0.5, + cooldownCoefficient: 0.99, + iterationsPerAge: 100, + }, + boardSize: 20, + _isFirstFrame: true, + result: None, + } + } +} + +fn _slider( + ui: &mut Ui, + name: &str, + storage: &mut T, + range: RangeInclusive, + step: f64, +) { + let label = ui.label(name); + + ui.scope(|ui| { + ui.spacing_mut().slider_width = ui.available_width() + - ui.spacing().interact_size.x + - ui.spacing().button_padding.x * 2.0; + ui.add(egui::Slider::new(storage, range).step_by(step)) + .labelled_by(label.id); + }); +} + +impl eframe::App for MyApp { + fn update(&mut self, ui: &eframe::egui::Context, _frame: &mut eframe::Frame) { + egui::CentralPanel::default().show(ui, |ui| { + ui.add_enabled_ui(matches!(self.result, None), |ui| { + _slider(ui, "Board size:", &mut self.boardSize, 2..=50, 1.0); + ui.label(""); + + _slider( + ui, + "Initial temperature:", + &mut self.simulationConfig.initialTemperature, + self.simulationConfig.targetTemperature + 0.01..=100.0, + 0.01, + ); + ui.label(""); + _slider( + ui, + "Target Temperature:", + &mut self.simulationConfig.targetTemperature, + 0.0..=99.98, + 0.01, + ); + ui.label(""); + _slider( + ui, + "Cooldown coefficient:", + &mut self.simulationConfig.cooldownCoefficient, + 0.001..=0.999, + 0.001, + ); + ui.label(""); + + _slider( + ui, + "Iterations per age:", + &mut self.simulationConfig.iterationsPerAge, + 1..=1000, + 1.0, + ); + + ui.label(""); + if ui.button("Calculate").clicked() { + self.result = Some(algo::simulateAnnealing( + self.boardSize, + &self.simulationConfig, + &mut rand::rngs::SmallRng::seed_from_u64( + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs(), + ), + )) + } + }); + + match &self.result { + None => {} + Some(result) => ui.ctx().show_viewport_immediate( + egui::ViewportId::from_hash_of("immediate_viewport"), + egui::ViewportBuilder::default() + .with_title("Immediate Viewport") + .with_inner_size([200.0, 100.0]), + |ui, class| { + if class == egui::ViewportClass::Embedded { + /*ui.label( + "This viewport is embedded in the parent window, and cannot be moved outside of it.", + );*/ + } else { + egui::CentralPanel::default().show(ui, |ui| { + ui.label("Hello from immediate viewport"); + + if ui.input(|i| i.viewport().close_requested()) { + self.result = None + } + }); + } + }, + ), + } + }); + } +}