///|
/// Original benchmark text from the Augerat Set A CVRPLIB family.
///
/// The fixture keeps the published node numbering, EUC_2D convention, vehicle
/// capacity, and five-vehicle limit. It is parsed at runtime by the same
/// parser that users can call for their own TSPLIB-compatible files.
pub let a_n32_k5_text : String =
#|NAME : A-n32-k5
#|COMMENT : (Augerat et al, Min no of trucks: 5, Optimal value: 784)
#|TYPE : CVRP
#|DIMENSION : 32
#|EDGE_WEIGHT_TYPE : EUC_2D
#|CAPACITY : 100
#|TRUCKS : 5
#|NODE_COORD_SECTION
#|1 82 76
#|2 96 44
#|3 50 5
#|4 49 8
#|5 13 7
#|6 29 89
#|7 58 30
#|8 84 39
#|9 14 24
#|10 2 39
#|11 3 82
#|12 5 10
#|13 98 52
#|14 84 25
#|15 61 59
#|16 1 65
#|17 88 51
#|18 91 2
#|19 19 32
#|20 93 3
#|21 50 93
#|22 98 14
#|23 5 42
#|24 42 9
#|25 61 62
#|26 9 97
#|27 80 55
#|28 57 69
#|29 23 15
#|30 20 70
#|31 85 60
#|32 98 5
#|DEMAND_SECTION
#|1 0
#|2 19
#|3 21
#|4 6
#|5 19
#|6 7
#|7 12
#|8 16
#|9 6
#|10 16
#|11 8
#|12 14
#|13 21
#|14 16
#|15 3
#|16 22
#|17 18
#|18 19
#|19 1
#|20 24
#|21 8
#|22 12
#|23 4
#|24 8
#|25 24
#|26 24
#|27 2
#|28 20
#|29 15
#|30 2
#|31 14
#|32 9
#|DEPOT_SECTION
#|1
#|-1
#|EOF
///|
pub struct BenchmarkCase {
name : String
instance : @core.VrpInstance
known_best : Double
source : String
} derive(Debug)
///|
pub struct BenchmarkResult {
case_name : String
customer_count : Int
known_best : Double
seed_objective : Double
best_objective : Double
gap_percent : Double
best_solution : @core.Solution
stats : @core.SolveStats
} derive(Debug)
///|
pub fn BenchmarkCase::name(self : BenchmarkCase) -> String {
self.name
}
///|
pub fn BenchmarkCase::instance(self : BenchmarkCase) -> @core.VrpInstance {
self.instance
}
///|
pub fn BenchmarkCase::customer_count(self : BenchmarkCase) -> Int {
self.instance.customer_count()
}
///|
pub fn BenchmarkCase::vehicle_capacity(self : BenchmarkCase) -> Double {
self.instance.vehicle().capacity()
}
///|
pub fn BenchmarkCase::known_best(self : BenchmarkCase) -> Double {
self.known_best
}
///|
pub fn BenchmarkCase::source(self : BenchmarkCase) -> String {
self.source
}
///|
pub fn BenchmarkResult::case_name(self : BenchmarkResult) -> String {
self.case_name
}
///|
pub fn BenchmarkResult::customer_count(self : BenchmarkResult) -> Int {
self.customer_count
}
///|
pub fn BenchmarkResult::known_best(self : BenchmarkResult) -> Double {
self.known_best
}
///|
pub fn BenchmarkResult::seed_objective(self : BenchmarkResult) -> Double {
self.seed_objective
}
///|
pub fn BenchmarkResult::best_objective(self : BenchmarkResult) -> Double {
self.best_objective
}
///|
pub fn BenchmarkResult::gap_percent(self : BenchmarkResult) -> Double {
self.gap_percent
}
///|
pub fn BenchmarkResult::best_solution(self : BenchmarkResult) -> @core.Solution {
self.best_solution.copy()
}
///|
pub fn BenchmarkResult::stats(self : BenchmarkResult) -> @core.SolveStats {
self.stats
}
///|
pub fn a_n32_k5_case() -> BenchmarkCase raise @instance.ParseError {
let instance = @instance.parse_cvrp(a_n32_k5_text)
{
name: "A-n32-k5",
instance,
known_best: 784.0,
source: "CVRPLIB / Augerat Set A (1995)",
}
}
///|
pub fn run_case(
case : BenchmarkCase,
config : @core.SolveConfig,
) -> BenchmarkResult {
let seed = @constructive.clarke_wright_seed(case.instance, config~)
let result = @search.solve_with_seed(case.instance, seed, config~)
let gap_percent = (result.best_solution.objective - case.known_best) /
case.known_best *
100.0
{
case_name: case.name,
customer_count: case.customer_count(),
known_best: case.known_best,
seed_objective: result.stats.seed_objective,
best_objective: result.stats.best_objective,
gap_percent,
best_solution: result.best_solution,
stats: result.stats,
}
}
///|
pub fn result_text(result : BenchmarkResult) -> String {
[
"Benchmark: \{result.case_name}",
"Customers: \{result.customer_count}",
"Known best: \{result.known_best}",
"Seed objective: \{result.seed_objective}",
"Best objective: \{result.best_objective}",
"Gap (%): \{result.gap_percent}",
"Feasible: \{result.best_solution.feasible}",
"Routes: \{result.best_solution.routes.length()}",
"Iterations: \{result.stats.iterations}",
].join("\n")
}