#![warn(warnings)] #![warn(clippy::all, clippy::pedantic)] #![allow(non_upper_case_globals)] #![allow(clippy::needless_return)] #![allow(clippy::items_after_statements)] #![allow(unused_variables, unused_imports, dead_code)] pub mod misc; mod generic_master_problem; mod ui; pub mod solvers; use std::fmt::Debug; use std::marker::PhantomData; use std::sync::Arc; use std::thread; pub use generic_master_problem::*; pub use ui::*; use crate::branch::{Branch, BranchComparator}; use crate::column_pool::{ColumnId, ColumnPool, ColumnPoolFilter}; use crate::misc::blocking_queue::BlockingQueue; pub trait BnPFactory { fn new(&self, instance : &ProblemInstance) -> Type; } pub struct BranchAndPrice, BranchGroupType : Clone + Debug + Send + Sync, Constr : Clone, Env : LPEnv,Model : LPModel,Var : Clone, PricingSolver : UserPricingSolver , ProblemInstance : Clone + Send + Sync, UMasterProblem : UserMasterProblem + Clone, > where ColumnPool : ColumnPoolFilter{ _b : PhantomData, _c : PhantomData, _bpt: PhantomData, _mm: PhantomData, _ds: PhantomData, _cs: PhantomData, _ev: PhantomData, _md: PhantomData, _vr: PhantomData, _pi: PhantomData, _ps : PhantomData, _mp : PhantomData, problem_instance : ProblemInstance, } impl, BranchGroupType : Clone + Debug + Send + Sync, Constr : Clone, Env : LPEnv,Model : LPModel,Var : Clone, PricingSolver : UserPricingSolver, ProblemInstance: Clone + Send + Sync, UMasterProblem : UserMasterProblem + Clone + Send + Sync, > BranchAndPrice where ColumnPool : ColumnPoolFilter{ pub fn new( problem_instance : ProblemInstance) -> Self { BranchAndPrice { _b: PhantomData, _c: PhantomData, _bpt: PhantomData, _mm: PhantomData, _ds: PhantomData, _cs: PhantomData, _ev: PhantomData, _md: PhantomData, _vr: PhantomData, _pi : PhantomData, _ps: PhantomData, _mp: PhantomData, problem_instance } } pub fn solve(&self, ui : &UI, num_threads : usize, column_pool : ColumnPool) -> (f64, Vec<(f64, Column)>) { let open_branches = BlockingQueue::new( BranchComparator::with_bound(), BranchComparator::without_bound() ); let shared = Arc::new(SharedState::new(column_pool, &ui, None, open_branches)); // start with phase main { *shared.phase.write().unwrap() = Phase::PrimalHeuristic; } shared .open_branches .add_job(Branch::create_lds_root()); shared.ui_sender.send(UIUserMessage::StartPhase("Primal Heuristic", 0)); // run main thread::scope(|s| { for i in 0..num_threads { let shared = shared.clone(); let pi = self.problem_instance.clone(); s.spawn(move || { let mp = UMasterProblem::new(&pi, shared.ui_sender.clone()); let ps = PricingSolver::new(&pi, shared.ui_sender.clone()); let mut master_problem = MasterProblem::new( shared, mp, ps ); master_problem.run_worker(0.0, f64::INFINITY, (0 + i) as i32); }); } }); // start with phase main { *shared.phase.write().unwrap() = Phase::Main; } shared .open_branches .add_job(Branch::default()); shared.ui_sender.send(UIUserMessage::StartPhase("Main Phase", 0)); thread::scope(|s| { for i in 0..num_threads { let shared = shared.clone(); let pi = self.problem_instance.clone(); s.spawn(move || { let mp = UMasterProblem::new(&pi, shared.ui_sender.clone()); let ps = PricingSolver::new(&pi, shared.ui_sender.clone()); let mut master_problem = MasterProblem::new( shared, mp, ps ); master_problem.run_worker(0.0, f64::INFINITY, (0 + i) as i32); }); } }); ui.get_sender().send(UIUserMessage::ExitUi { root_node: shared.duration_root_node.lock().unwrap().clone(), lds_root_node_duration: shared.duration_lds_root_node.lock().unwrap().clone(), }); let (best,pattern) = { shared.best.read().unwrap().to_owned() }; let columns: Vec<(f64, Column)> = pattern .iter() .filter(|(v, _)| *v > 0.0) .map(|(v, c)| { let c = shared .column_pool .read() .unwrap() .get_column(*c) .data .clone(); (*v,c) }) .collect(); (best, columns) } }