///|
/// Parameters for deterministic synthetic CVRP/VRPTW instances.
pub struct GeneratorConfig {
name : String
customer_count : Int
coordinate_limit : Double
vehicle_capacity : Double
fleet_size : Int
max_demand : Int
horizon : Double
service_time : Double
seed : Int
} derive(Debug, ToJson)
///|
pub fn GeneratorConfig::default() -> GeneratorConfig {
{
name: "generated-cvrp",
customer_count: 24,
coordinate_limit: 100.0,
vehicle_capacity: 40.0,
fleet_size: 6,
max_demand: 8,
horizon: 500.0,
service_time: 5.0,
seed: 17,
}
}
///|
pub fn GeneratorConfig::tune(
self : GeneratorConfig,
name? : String = self.name,
customer_count? : Int = self.customer_count,
coordinate_limit? : Double = self.coordinate_limit,
vehicle_capacity? : Double = self.vehicle_capacity,
fleet_size? : Int = self.fleet_size,
max_demand? : Int = self.max_demand,
horizon? : Double = self.horizon,
service_time? : Double = self.service_time,
seed? : Int = self.seed,
) -> GeneratorConfig {
{
name,
customer_count,
coordinate_limit,
vehicle_capacity,
fleet_size,
max_demand,
horizon,
service_time,
seed,
}
}
///|
pub fn GeneratorConfig::name(self : GeneratorConfig) -> String {
self.name
}
///|
pub fn GeneratorConfig::customer_count(self : GeneratorConfig) -> Int {
self.customer_count
}
///|
pub fn GeneratorConfig::coordinate_limit(self : GeneratorConfig) -> Double {
self.coordinate_limit
}
///|
pub fn GeneratorConfig::vehicle_capacity(self : GeneratorConfig) -> Double {
self.vehicle_capacity
}
///|
pub fn GeneratorConfig::fleet_size(self : GeneratorConfig) -> Int {
self.fleet_size
}
///|
pub fn GeneratorConfig::max_demand(self : GeneratorConfig) -> Int {
self.max_demand
}
///|
pub fn GeneratorConfig::horizon(self : GeneratorConfig) -> Double {
self.horizon
}
///|
pub fn GeneratorConfig::service_time(self : GeneratorConfig) -> Double {
self.service_time
}
///|
pub fn GeneratorConfig::seed(self : GeneratorConfig) -> Int {
self.seed
}
///|
fn safe_count(value : Int) -> Int {
value.max(0).min(5_000)
}
///|
fn safe_limit(value : Double) -> Double {
value.max(1.0)
}
///|
fn generated_depot(config : GeneratorConfig) -> @core.Depot {
let center = safe_limit(config.coordinate_limit) / 2.0
@core.Depot::new(center, center, due_time=config.horizon.max(1.0))
}
///|
fn generated_vehicle(config : GeneratorConfig) -> @core.VehicleProfile {
@core.VehicleProfile::new(
config.vehicle_capacity.max(0.1),
fleet_size=config.fleet_size.max(1),
max_route_duration=config.horizon.max(1.0),
)
}
///|
fn generated_customer(
rng : @rng.Rng,
config : GeneratorConfig,
index : Int,
) -> @core.Customer {
let limit = safe_limit(config.coordinate_limit)
let demand_limit = config.max_demand.max(1)
let x = rng.next_double() * limit
let y = rng.next_double() * limit
let demand = Double::from_int(1 + rng.next_int(demand_limit))
@core.Customer::new(
index + 1,
x,
y,
demand,
service_time=config.service_time.max(0.0),
)
}
///|
/// Creates a deterministic CVRP instance for load testing and tutorials.
pub fn generate_cvrp(config : GeneratorConfig) -> @core.VrpInstance {
let rng = @rng.Rng::new(config.seed)
let customers : Array[@core.Customer] = []
for index in 0.. (Double, Double) {
let horizon = config.horizon.max(10.0)
let ready = rng.next_double() * horizon * 0.65
let width = horizon * 0.25 + rng.next_double() * horizon * 0.15
(ready, Double::min(horizon, ready + width))
}
///|
/// Creates a deterministic Solomon-style VRPTW instance.
pub fn generate_vrptw(config : GeneratorConfig) -> @core.VrpInstance {
let rng = @rng.Rng::new(config.seed)
let customers : Array[@core.Customer] = []
for index in 0.. String {
let (minimum, maximum, average) = instance.distance_summary()
[
instance.instance_name(),
instance.variant().name(),
"customers=\{instance.customer_count()}",
"fleet=\{instance.vehicle().fleet_size()}",
"capacity=\{instance.vehicle().capacity()}",
"min=\{minimum}",
"max=\{maximum}",
"avg=\{average}",
].join("|")
}