///|
/// Result of a solver portfolio run across construction and improvement modes.
pub struct PortfolioResult {
  result : @core.SolveResult
  strategies : Array[@constructive.ConstructionStrategy]
  selected_index : Int
  evaluated : Int
} derive(Debug)

///|
pub fn PortfolioResult::result(self : PortfolioResult) -> @core.SolveResult {
  self.result
}

///|
pub fn PortfolioResult::strategies(
  self : PortfolioResult,
) -> Array[@constructive.ConstructionStrategy] {
  self.strategies.copy()
}

///|
pub fn PortfolioResult::selected_index(self : PortfolioResult) -> Int {
  self.selected_index
}

///|
pub fn PortfolioResult::evaluated(self : PortfolioResult) -> Int {
  self.evaluated
}

///|
fn portfolio_strategies() -> Array[@constructive.ConstructionStrategy] {
  [
    @constructive.ConstructionStrategy::ClarkeWright,
    @constructive.ConstructionStrategy::NearestNeighbor,
    @constructive.ConstructionStrategy::CheapestInsertion,
    @constructive.ConstructionStrategy::DemandFirst,
    @constructive.ConstructionStrategy::Radial,
    @constructive.ConstructionStrategy::Balanced,
  ]
}

///|
/// Evaluates a broad but bounded strategy portfolio and returns its best run.
pub fn solve_portfolio(
  instance : @core.VrpInstance,
  config : @core.SolveConfig,
) -> PortfolioResult {
  let strategies = portfolio_strategies()
  let mut selected_index = 0
  let mut best = solve_with_seed(
    instance,
    @constructive.seed_by_strategy(instance, strategies[0], config),
    config~,
  )
  for index in 1.. String {
  let result = portfolio.result
  let strategy = portfolio.strategies[portfolio.selected_index]
  [
    "Portfolio attempts: \{portfolio.evaluated}",
    "Selected strategy: \{Repr(strategy)}",
    "Best objective: \{result.best_solution.objective}",
    "Feasible: \{result.best_solution.feasible}",
  ].join("\n")
}