Skip to content

Commit

Permalink
extra documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
JeroenGar committed Jan 25, 2023
1 parent 84d155e commit e9dd51a
Show file tree
Hide file tree
Showing 18 changed files with 84,440 additions and 78,609 deletions.
39,119 changes: 19,936 additions & 19,183 deletions examples/large_example_result.html

Large diffs are not rendered by default.

123,804 changes: 64,415 additions & 59,389 deletions examples/large_example_result.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src/core/entities/sendable_layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ use crate::core::entities::layout::Layout;
use crate::core::insertion::node_blueprint::NodeBlueprint;
use crate::Instance;

///Representation of a layout that can be sent across threads

#[derive(Debug, Clone)]
pub struct SendableLayout {
sheettype_id: usize,
Expand Down
3 changes: 3 additions & 0 deletions src/core/insertion/insertion_blueprint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ use crate::core::insertion::node_blueprint::NodeBlueprint;
use crate::core::layout_index::LayoutIndex;
use crate::PartType;

/// Representation of how a part can be inserted into a Node of a Layout
/// Layouts can use InsertionBlueprints to insert parts

#[derive(Debug, Clone)]
pub struct InsertionBlueprint<'a> {
layout_i: LayoutIndex,
Expand Down
7 changes: 6 additions & 1 deletion src/core/insertion/insertion_option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,17 @@ use crate::core::insertion::insertion_blueprint::InsertionBlueprint;
use crate::core::layout_index::LayoutIndex;
use crate::optimization::problem::Problem;

/// Represents the possibility to insert a parttype into a node with a certain rotation
/// Does not define how exactly, just that it is possible
///
/// InsertionOptions can generate InsertionBlueprints which define exactly how a part is inserted

#[derive(Debug, PartialEq, Eq)]
pub struct InsertionOption<'a> {
layout_i: LayoutIndex,
original_node_i: Index,
parttype: &'a PartType,
rotation: Option<Rotation>,
rotation: Option<Rotation>, // None means both rotations are possible
}

impl<'a> InsertionOption<'a> {
Expand Down
2 changes: 2 additions & 0 deletions src/core/insertion/node_blueprint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use crate::core::cost::Cost;
use crate::core::entities::node::Node;
use crate::core::leftover_valuator;

/// Represents a node in an InsertionBlueprint

#[derive(Debug, Clone)]
pub struct NodeBlueprint {
width: u64,
Expand Down
4 changes: 2 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,14 @@ fn main() {


let handle = thread::Builder::new().name(thread_name).spawn(move || {
let local_sol_collector = LocalSolCollector::new(rx_sync, tx_solution_report_thread);
let local_sol_collector = LocalSolCollector::new(instance_thread.clone(), rx_sync, tx_solution_report_thread, COST_COMPARATOR);
let mut gdrr = GDRR::new(&instance_thread, &config_thread, local_sol_collector);
gdrr.lahc();
});
gdrr_thread_handlers.push(handle.expect("could not spawn thread"));
}

let mut global_sol_collector = GlobalSolCollector::new(instance, config, tx_syncs, rx_solution_report);
let mut global_sol_collector = GlobalSolCollector::new(instance, config, tx_syncs, rx_solution_report, COST_COMPARATOR);

global_sol_collector.monitor(gdrr_thread_handlers);

Expand Down
2 changes: 2 additions & 0 deletions src/optimization/config.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use serde::{Deserialize, Serialize};

/// Contains all the configurable parameters of the algorithm

#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Config {
Expand Down
3 changes: 3 additions & 0 deletions src/optimization/gdrr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ use crate::util::biased_sampler::{BiasedSampler, BiasMode};
use crate::util::macros::timed_thread_println;
use crate::util::util;

/// Goal-Driven Ruin and Recreate algorithm

pub struct GDRR<'a> {
config: &'a Config,
instance: &'a Instance,
Expand All @@ -47,6 +49,7 @@ impl<'a> GDRR<'a> {
}
}

// Late Acceptance Hill Climbing metaheuristic
pub fn lahc(&'a mut self) {
let start_time = std::time::Instant::now();

Expand Down
2 changes: 1 addition & 1 deletion src/optimization/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::core::entities::sheettype::SheetType;
use crate::util::assertions;

#[derive(Debug)]
/// Instance is a static representation of a collection of parts and sheets to be optimized.
/// Instance is a immutable representation of the collection of parts and sheets that need to be optimized.
pub struct Instance {
parts: Vec<(PartType, usize)>,
sheets: Vec<(SheetType, usize)>,
Expand Down
6 changes: 4 additions & 2 deletions src/optimization/rr/insertion_option_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ use crate::optimization::problem::Problem;
use crate::optimization::rr::cache_updates::IOCUpdates;
use crate::util::multi_map::MultiMap;

/// This struct functions as a cache for all InsertionOptions during the recreate phase
/// It is kept up to date by removing and adding InsertionOptions when nodes are removed or added
/// A cache for InsertionOptions during the recreate phase
/// It allows very fast lookup of all InsertionOptions that are valid for a given node or a given parttype
/// It is kept up-to-date throughout the recreate phase, by receiving updates about which nodes are removed or added

pub struct InsertionOptionCache<'a> {
option_node_map: MultiMap<(LayoutIndex, Index), Rc<InsertionOption<'a>>>,
option_parttype_map: MultiMap<&'a PartType, Rc<InsertionOption<'a>>>,
Expand Down
20 changes: 10 additions & 10 deletions src/optimization/sol_collectors/global_sol_collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ use crate::util::util;

const MONITOR_INTERVAL: Duration = Duration::from_millis(10);

/// Global Solution Collector
/// communicates with a set of LocalSolCollectors
/// It receives solutions and sends out sync messages (material limit lowering, terminate)

pub struct GlobalSolCollector {
_instance: Arc<Instance>,
config: Arc<Config>,
Expand All @@ -35,21 +39,16 @@ impl GlobalSolCollector {
config: Arc<Config>,
tx_syncs: Vec<Sender<SyncMessage>>,
rx_solution_report: Receiver<SolutionReportMessage>,
cost_comparator: fn(&Cost, &Cost) -> Ordering,
) -> Self {
let material_limit = None;
let best_complete_solution = None;
let best_incomplete_solution = None;
let best_incomplete_cost = None;
let cost_comparator = crate::COST_COMPARATOR;

Self {
_instance,
config,
best_complete_solution,
best_incomplete_solution,
best_incomplete_cost,
best_complete_solution : None,
best_incomplete_solution : None,
best_incomplete_cost : None,
cost_comparator,
material_limit,
material_limit : None,
tx_syncs,
rx_solution_report,
}
Expand Down Expand Up @@ -165,6 +164,7 @@ impl GlobalSolCollector {
pub fn best_incomplete_cost(&self) -> &Option<Cost> {
&self.best_incomplete_cost
}

pub fn material_limit(&self) -> Option<u64> {
self.material_limit
}
Expand Down
39 changes: 21 additions & 18 deletions src/optimization/sol_collectors/local_sol_collector.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
use std::cmp::Ordering;
use std::sync::Arc;
use std::sync::mpsc::{Receiver, Sender};

use colored::*;

use crate::core::cost::Cost;
use crate::optimization::instance::Instance;
use crate::optimization::solutions::problem_solution::ProblemSolution;
use crate::optimization::solutions::sendable_solution::SendableSolution;
use crate::optimization::solutions::solution::Solution;
use crate::optimization::solutions::solution_stats::SolutionStats;
use crate::util::macros::{timed_thread_println};
use crate::util::messages::{SolutionReportMessage, SyncMessage};

/// Local solution collectors collect and compare solutions from GDRR threads.
/// It keeps track of the best complete and incomplete solutions.
/// It also communicates with a GlobalSolCollector to transfer solutions and synchronize.
///
pub struct LocalSolCollector<'a> {
instance: Arc<Instance>,
best_complete_solution: Option<ProblemSolution<'a>>,
best_incomplete_solution: Option<ProblemSolution<'a>>,
cost_comparator: fn(&Cost, &Cost) -> Ordering,
Expand All @@ -25,27 +32,23 @@ pub struct LocalSolCollector<'a> {


impl<'a> LocalSolCollector<'a> {
pub fn new(rx_sync: Receiver<SyncMessage>,
tx_solution_report: Sender<SolutionReportMessage>) -> Self {
let best_complete_solution = None;
let best_incomplete_solution = None;
let cost_comparator = crate::COST_COMPARATOR;
let material_limit = None;
let best_complete_transferred = false;
let best_incomplete_transferred = false;
let terminate = false;

pub fn new(instance: Arc<Instance>,
rx_sync: Receiver<SyncMessage>,
tx_solution_report: Sender<SolutionReportMessage>,
cost_comparator: fn(&Cost, &Cost) -> Ordering,
) -> Self {

Self {
best_complete_solution,
best_incomplete_solution,
instance,
best_complete_solution : None,
best_incomplete_solution : None,
cost_comparator,
material_limit,
material_limit : None,
rx_sync,
tx_solution_report,
best_complete_transferred,
best_incomplete_transferred,
terminate,
best_complete_transferred : false,
best_incomplete_transferred : false,
terminate : false,
}
}

Expand Down Expand Up @@ -112,7 +115,7 @@ impl<'a> LocalSolCollector<'a> {
}
None => {
//timed_thread_println!("{}", "Sending full incomplete solution");
let sendable_solution = SendableSolution::new(&best_incomplete_solution);
let sendable_solution = SendableSolution::new(self.instance.clone(), &best_incomplete_solution);
SolutionReportMessage::NewIncompleteSolution(thread_name, sendable_solution)
}
};
Expand All @@ -127,7 +130,7 @@ impl<'a> LocalSolCollector<'a> {
Some(best_complete_solution) => {
if !self.best_complete_transferred {
let thread_name = std::thread::current().name().unwrap().parse().unwrap();
let sendable_solution = SendableSolution::new(best_complete_solution);
let sendable_solution = SendableSolution::new(self.instance.clone(), &best_complete_solution);
//timed_thread_println!("{}", "Sending full solution".green());
self.tx_solution_report.send(
SolutionReportMessage::NewCompleteSolution(thread_name, sendable_solution)
Expand Down
18 changes: 15 additions & 3 deletions src/optimization/solutions/sendable_solution.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,34 @@
use std::sync::Arc;
use crate::core::cost::Cost;
use crate::core::entities::sendable_layout::SendableLayout;
use crate::optimization::instance::Instance;
use crate::optimization::solutions::problem_solution::ProblemSolution;
use crate::optimization::solutions::solution::Solution;

/// Representation of a solution, based on ProblemSolution, but that can be sent across threads

#[derive(Debug, Clone)]
pub struct SendableSolution {
instance: Arc<Instance>,
layouts: Vec<SendableLayout>,
cost: Cost,
usage: f64,
parttype_qtys: Vec<usize>,
sheettype_qtys: Vec<usize>,
cost: Cost,
usage: f64,
}

impl SendableSolution {
pub fn new(problem_solution: &ProblemSolution) -> SendableSolution {
pub fn new(instance: Arc<Instance>, problem_solution: &ProblemSolution) -> SendableSolution {
debug_assert!(instance.as_ref() as *const _ == problem_solution.instance() as *const _);

let layouts = problem_solution.layouts().iter().map(|(_id, l)| SendableLayout::new(l)).collect();
let cost = problem_solution.cost().clone();
let usage = problem_solution.usage();
let parttype_qtys = problem_solution.parttype_qtys().clone();
let sheettype_qtys = problem_solution.sheettype_qtys().clone();

Self {
instance,
layouts,
cost,
usage,
Expand All @@ -32,6 +40,10 @@ impl SendableSolution {
pub fn layouts(&self) -> &Vec<SendableLayout> {
&self.layouts
}

pub fn instance(&self) -> &Arc<Instance> {
&self.instance
}
}


Expand Down
4 changes: 4 additions & 0 deletions src/util/assertions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ use crate::optimization::problem::Problem;
use crate::optimization::rr::insertion_option_cache::InsertionOptionCache;
use crate::optimization::solutions::problem_solution::ProblemSolution;

/// A set of functions which ensure correct behaviour of the code. Used for debugging purposes
/// They are called with debug_assert!() macro throughout the code.
/// Are not compiled in release mode

pub fn children_nodes_fit(node_i: &Index, arena: &Arena<Node>) -> bool {
let node = &arena[*node_i];
match node.children().is_empty() {
Expand Down
9 changes: 9 additions & 0 deletions src/util/blink.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ use std::ops::Range;
use rand::Rng;
use rand::rngs::SmallRng;

/// Christiaens, J., & Vanden Berghe, G. (2020). Slack Induction by String Removals for Vehicle Routing Problems. (https://lirias.kuleuven.be/retrieve/510989)
///
/// It basically selects the lowest value from a list of entries,
/// but with a certain chance to skip over ('blink') values.
///
/// Example:
/// A blink chance of 1% means that 99% of the time, the lowest value will be selected,
/// 0.99% of the time, the second lowest value will be selected, and so on.

pub fn select_lowest_entry(entries: &Vec<usize>, blink_chance: f32, rand: &mut SmallRng) -> usize {
let mut lowest_value = usize::MAX;
let mut selected_index = 0;
Expand Down
2 changes: 2 additions & 0 deletions src/util/messages.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use crate::optimization::solutions::sendable_solution::SendableSolution;
use crate::optimization::solutions::solution_stats::SolutionStats;

/// Messages between GlobalSolCollector and LocalSolCollectors

pub enum SyncMessage {
SyncMatLimit(u64),
Terminate,
Expand Down
3 changes: 3 additions & 0 deletions src/util/multi_map.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use std::hash::Hash;
use fxhash::FxHashMap;

/// A map that can contain multiple values for a single key.
/// Uses the fxhash crate, which hashes considerably faster the default one.

pub struct MultiMap<K: Hash + Eq, V> {
map: FxHashMap<K, Vec<V>>,
}
Expand Down

0 comments on commit e9dd51a

Please sign in to comment.