Struct Solution

Source
pub struct Solution {
    pub id: i32,
    pub solution: Vec<Vec<Game>>,
}
Expand description

Represents a solution for the scheduling problem.

Each Solution contains an id identifying the solution, and a solution matrix where solution[slot][team] stores a Game indicating the opponent and if the game is home or away.

§Fields

  • id - A unique identifier for the solution.
  • solution - A 2D vector of Game instances representing the schedule matrix.

§Example

let solution = Solution {
    id: 1,
    solution: vec![vec![Game { home_game: true, opponent: 2 }]],
};
println!("Solution ID: {}", solution.id);

Fields§

§id: i32§solution: Vec<Vec<Game>>

Implementations§

Source§

impl Solution

Source

pub fn new(data: &Rawdata) -> Solution

Creates a new, empty Solution instance initialized with default game values.

This function constructs a solution matrix where each slot and team position is filled with a Game:

  • home_game is set to false
  • opponent is set to -1 (indicating: no opponent assigned yet)
§Arguments
  • data - A reference to the Rawdata structure containing teams and slots information. The size of the solution matrix is derived from:
    • data.teams.len()
    • data.slots.len()
§Returns

A Solution struct with:

  • id initialized to -1
  • solution initialized as a slots x teams matrix filled with default games.
§Example
let data = Rawdata::generate_example();
let solution = Solution::new(&data);
assert_eq!(solution.solution.len(), data.slots.len());
assert_eq!(solution.solution[0].len(), data.teams.len());
Source

pub fn generate_traveling_distance_matrix(data: &Rawdata) -> Vec<Vec<i32>>

Generates a traveling distance matrix based on the distance in Rawdata.

This function constructs a 2D matrix where each cell (i, j) represents the distance traveled from team i to team j. The matrix is initialized with zeros and populated using the distances list contained inside Rawdata.

§Arguments
  • data - A reference to the Rawdata structure containing team distance relationships. data.distances is expected to list distances between pairs of teams.
§Returns

A 2D vector (Vec<Vec<i32>>) where:

  • The row index corresponds to the origin team
  • The column index corresponds to the destination team
  • Each cell contains the travel distance between them
§Example
let data = Rawdata::generate_example();
let distance_matrix = generate_traveling_distance_matrix(&data);

println!("Distance: {}", distance_matrix[0][2]);
Source

pub fn has_duplicate_solutions(solutions: &Vec<Solution>) -> bool

Checks if a list of Solution objects contains duplicates.

This function iterates over all solutions and attempts to insert each one into a HashSet. If insertion fails for any solution, it means a duplicate exists, and the function returns true.

§Arguments
  • solutions - A reference to a vector of Solution instances to be checked.
§Returns
  • true if one or more duplicates are found.
  • false if all solutions are unique.
§Requirements

The Solution type must implement:

  • Hash
  • Eq
§Example
let solutions = load_solutions("output/solutions/");
if has_duplicate_solutions(&solutions) {
    println!("Duplicate.");
} else {
    println!("No duplicates.");
}
Source

pub fn load_solutions(path: &str) -> Vec<Solution>

Loads all solution files from a directory and returns them as a vector of Solution.

This function scans the directory for files whose names follow the pattern solutions_*.json. Each file is opened, deserialized into a Solution, and collected into a vector. After loading, the solutions are sorted in ascending order based on their id field.

§Arguments
  • path - A string slice representing the directory to search for solution files.
§Returns

A vector of Solution objects loaded from the directory.

§Panics

This function will panic if:

  • The directory cannot be read.
  • A file cannot be opened.
  • A JSON file cannot be deserialized into a Solution.
§Example
let solutions = load_solutions("output/solutions/");
println!("Loaded {} solutions", solutions.len());

if let Some(first) = solutions.first() {
    println!("First solution ID: {}", first.id);
}
Source

pub fn generate_distances( solutions: Vec<Solution>, data: &Rawdata, traveling_distance_matrix: &Vec<Vec<i32>>, ) -> Vec<i128>

Calculates the total traveling distances for a list of solutions.

This function iterates over each solution, evaluates it using the provided traveling distance matrix, and collects the total distances into a vector.

§Arguments
  • solutions - A vector of Solution instances to evaluate.
  • data - A reference to the Rawdata containing teams and constraints.
  • traveling_distance_matrix - A reference to a 2D vector where matrix[i][j] represents the distance from team i to team j.
§Returns

A vector of i128 where each element represents the total traveling distance of the corresponding solution.

§Example
let data = Rawdata::generate_example();
let distance_matrix = vec![vec![0,5,7], vec![5,0,3], vec![7,3,0]];
let solutions = vec![Solution::generate_example(), Solution::generate_example()];
let distances = generate_distances(solutions, &data, &distance_matrix);
println!("All distances: {:?}", distances);
Source

fn log_solution( solution: &Solution, data: &Rawdata, traveling_distance_matrix: &Vec<Vec<i32>>, ) -> i32

Logs a solution’s schedule and its evaluation metrics.

This function prints a representation of the solution, including the total traveling distance, capacity, round-robin and separation constraint violations, It also returns the total distance.

§Arguments
  • solution - A reference to the Solution to log.
  • data - A reference to the Rawdata containing teams and constraints.
  • traveling_distance_matrix - A reference to a 2D vector where matrix[i][j] represents the distance from team i to team j.
§Returns

The total traveling distance (i32) of the solution.

§Example
let data = Rawdata::generate_example();
let solution = Solution::generate_example();
let distance = Solution::log_solution(&solution, &data, &vec![vec![0,5,7], vec![5,0,3], vec![7,3,0]]);
println!("Total distance: {}", distance);
Source

fn generate_solution( data: &Rawdata, perm: &Vec<Team>, fixed_team: usize, upward: bool, id: i32, ) -> Solution

Generates a complete solution for a given team permutation using Florian’s method.

This function clones the input Rawdata, applies the given team permutation, and generates a round-robin schedule using generate_florian_solution. The resulting solution is assigned the provided ID.

§Arguments
  • data - A reference to the Rawdata containing the original teams, traveling_distance_matrix and constraints.
  • perm - A reference to a vector of Team representing the ordered permutation of teams.
  • fixed_team - The index of the team to remain fixed during the method rotations.
  • upward - If true, the home/away pattern follows an upward direction, otherwise downward.
  • id - The unique ID to assign to the generated solution.
§Returns

A Solution struct representing the generated schedule with the specified ID.

§Example
let data = Rawdata::generate_example();
let perm = data.teams.clone();
let solution = generate_solution(&data, &perm, 0, true, 1);
println!("{}", solution_to_string(&solution, &data));
Source

pub fn generate_random_permutations( data: &Rawdata, number_permutations: i32, seed: u64, path: &str, save: bool, ) -> Vec<Vec<i32>>

Generates a set of unique random permutations of the team IDs.

This function takes the list of teams from Rawdata and generates the requested number of unique permutations. Each permutation is randomized and stored in a Vec<i32>.

§Arguments
  • data - A reference to the Rawdata struct containing the list of teams.
  • number_permutation - A reference to an i32 specifying how many unique permutations should be generated.
§Returns

A vector of vectors (Vec<Vec<i32>>), where each inner vector is a unique permutation of the team IDs.

§Example
let data = Rawdata::generate_example();
let permutations = generate_random_permutations(&data, &5);
Source

pub fn generate_all_solutions( data: &Rawdata, traveling_distance_matrix: &Vec<Vec<i32>>, permutation: Vec<Vec<i32>>, path: &str, save: bool, ) -> (Vec<Solution>, Vec<i128>)

Generates all possible solutions for a given team permutation using Florian’s method, evaluates their distances, and optionally saves them to disk.

This function iterates over all possible combinations of fixed teams and home/away patterns (upward/downward) for a given permutation of teams. Each generated solution is evaluated using the traveling distance matrix, logged, and optionally saved as JSON.

§Arguments
  • data - A reference to the Rawdata containing teams, slots, and constraints.
  • traveling_distance_matrix - A reference to a 2D vector where matrix[i][j] represents the distance from team i to team j.
  • permutation - A vector of vect of team IDs representing the order in which teams are considered.
  • path - A string slice representing the directory path where solutions will be saved if SAVE_ENABLED is true.
§Returns

A tuple (solutions, all_distances):

  • solutions (Vec): all generated solution matrices.
  • all_distances (Vec): total traveling distance for each solution.
§Panics

This function may panic if saving a solution to file fails.

§Example
let data = Rawdata::generate_example();
let distance_matrix = vec![vec![0,5,7], vec![5,0,3], vec![7,3,0]];
let permutation = vec![0,1,2];
let (solutions, distances) = generate_all_solutions(&data, &distance_matrix, permutation, "output");
println!("Solutions length {}", solutions.len());
println!("Distances: {:?}", distances);
Source

pub fn generate_florian_solution( data: &Rawdata, fixed_team: usize, upward: bool, ) -> Solution

Generates a schedule using Florian’s method construction.

This function constructs a round-robin schedule fixing a team. The upward flag determines the pattern of home/away assignments for the first match of each pairing.

§Arguments
  • data - A reference to Rawdata containing team information.
  • fixed_team - The index of the team to remain fixed during rotations.
  • upward - If true, the home team assignment follows an upward pattern; otherwise downward.
§Returns

A Solution struct with the scheduled matches for all slots and teams.

§Example
let data = Rawdata::generate_example();
let solution = generate_florian_solution(&data, 0, true);
println!("{}", solution_to_string(&solution, &data));
Source

pub fn solution_to_string(solution_matrix: &Solution, data: &Rawdata) -> String

Converts a Solution matrix into a formatted string representation.

This function generates a human-readable string showing the schedule of all teams for each slot. Each cell shows the opponent ID followed by H for a home game or A for an away game. The output also includes team names and IDs as headers.

§Arguments
  • solution_matrix - A reference to the Solution containing the schedule.
  • data - A reference to the Rawdata struct containing team information.
§Returns

A String representing the formatted solution.

§Example
let data = Rawdata::generate_example();
let solution = Solution::generate_example();
let output_str = solution_to_string(&solution, &data);
println!("{}", output_str);

Example output:

Id: 1
         ATL:0    NYM:1    PHI:2
Slot:0    1H       2A       0H
Slot:1    2H       0A       1H
Source

fn check_constraints( data: &Rawdata, solution_matrix: &Solution, ) -> (i32, i32, bool)

Checks all constraints for a solution, including capacity, separation, and round-robin.

  1. Capacity constraints: Verifies for each team, within the specified interval (c_intp) of consecutive slots, the number of home or away games falls within the minimum (c_min) and maximum (c_max) allowed.

  2. Separation constraints: Ensures that matches between two teams respect the minimum and maximum separation distances defined by each constraint.

  3. Round-robin constraints: Checks that no pair of teams plays against each other more than 4 times (2 pairs of game).

§Arguments
  • data - A reference to the Rawdata containing teams and constraints.
  • solution_matrix - A reference to the Solution with the scheduled games.
§Returns

A tuple (capacity_violations, separation_violations, round_robin_respected)

  • capacity_violations (i32): total number of capacity constraint violations.
  • separation_violations (i32): total number of separation constraint violations.
  • round_robin_respected (bool): true if all pairs of teams respect the round-robin.
§Example
let data = Rawdata::generate_example();
let solution = Solution::generate_example();
let (cap_viol, sep_viol, rr_ok) = check_constraints(&data, &solution);
println!("Capacity violations: {}, Separation violations: {}, Round-robin ok: {}", cap_viol, sep_viol, rr_ok);
Source

fn evaluate_objective( traveling_distance_matrix: &Vec<Vec<i32>>, solution_matrix: &Solution, ) -> i32

Calculates the total traveling distance for all teams in a given solution.

This function iterates over all teams and all slots in the solution. For each team, it tracks the current location and adds the distance to the next game location. Home games do not require traveling, while away games add the distance to the opponent’s location.

§Arguments
  • traveling_distance_matrix - A reference to a 2D vector where matrix[i][j] represents the distance from team i to team j.
  • solution_matrix - A reference to the Solution containing the schedule of games for all slots and teams.
§Returns

The total traveling distance for all teams (i32).

§Example
let distance_matrix = vec![vec![0, 5, 7], vec![5, 0, 3], vec![7, 3, 0]];
let total = evaluate_objective(&distance_matrix, &solution);
println!("Total traveling distance: {}", total);
Source

pub fn evaluate_solution( data: &Rawdata, traveling_distance_matrix: &Vec<Vec<i32>>, solution_matrix: &Solution, ) -> (i32, i32, i32, bool)

Evaluates a given solution by calculating the total traveling distance and checking constraints.

This function combines the distance evaluation and constraint checks for a solution. It returns the total traveling distance, the total violations of capacity constraints, the total violations of separation constraints, and a boolean indicating if the round-robin structure is respected.

§Arguments
  • data - A reference to the Rawdata struct containing teams, slots, and constraints.
  • traveling_distance_matrix - A reference to a 2D vector where matrix[i][j] represents the distance from team i to team j.
  • solution_matrix - A reference to the Solution containing the schedule of games for all slots and teams.
§Returns

A tuple (total_distance, capacity_violations, separation_violations, round_robin_respected)

  • total_distance (i32): total traveling distance for all teams.
  • capacity_violations (i32): total penalty for capacity constraints violations.
  • separation_violations (i32): total penalty for separation constraints violations.
  • round_robin_respected (bool): true if the round-robin structure is respected.
§Example
let data = Rawdata::generate_example();
let distance_matrix = vec![vec![0,5,7], vec![5,0,3], vec![7,3,0]];
let solution = Solution::generate_example();
let (total_distance, cap_viol, sep_viol, rr_ok) = evaluate_solution(&data, &distance_matrix, &solution);

Trait Implementations§

Source§

impl Clone for Solution

Source§

fn clone(&self) -> Solution

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Solution

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for Solution

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Hash for Solution

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl PartialEq for Solution

Source§

fn eq(&self, other: &Solution) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Serialize for Solution

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl Eq for Solution

Source§

impl StructuralPartialEq for Solution

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dst: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,