Skip to content

Commit

Permalink
Refactor goal API
Browse files Browse the repository at this point in the history
  • Loading branch information
reinterpretcat committed Jul 8, 2024
1 parent 51d3902 commit 34379e1
Show file tree
Hide file tree
Showing 16 changed files with 274 additions and 241 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ This release focuses on refactorings to simplify code usage and overall maintain
* refactor route intervals and multi trip enablers
* refactor feature objective trait
* refactor dimensions/extras approach to avoid using strings as keys
* how goal of optimization is defined


## [v1.23.0]- 2023-12-22
Expand Down
3 changes: 1 addition & 2 deletions vrp-core/examples/custom_constraint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,7 @@ fn define_goal(transport: Arc<dyn TransportCost + Send + Sync>) -> GenericResult
.build()?;

// configure goal of optimization
GoalContextBuilder::with_features(vec![minimize_unassigned, transport_feature, capacity_feature, hardware_feature])?
.set_goal(&["min-unassigned", "min-distance"], &["min-distance"])?
GoalContextBuilder::with_features(&[minimize_unassigned, transport_feature, capacity_feature, hardware_feature])?
.build()
}

Expand Down
8 changes: 1 addition & 7 deletions vrp-core/examples/custom_objective.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,13 +130,7 @@ fn define_goal(transport: Arc<dyn TransportCost + Send + Sync>) -> GenericResult
.build()?;

// configure goal of optimization
GoalContextBuilder::with_features(vec![priority_feature, minimize_unassigned, transport_feature, capacity_feature])?
.set_goal(
// on global level, prefer more maximized jobs over anything else
&["maximize-priority", "min-unassigned", "min-distance"],
// on local level, prefer it over min-distance as distance is less important
&["maximize-priority", "min-distance"],
)?
GoalContextBuilder::with_features(&[priority_feature, minimize_unassigned, transport_feature, capacity_feature])?
.build()
}

Expand Down
13 changes: 4 additions & 9 deletions vrp-core/examples/cvrp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,10 @@ fn define_goal(transport: Arc<dyn TransportCost + Send + Sync>) -> GenericResult
.set_time_constrained(false)
.build_minimize_distance()?;

// configure goal of optimization
GoalContextBuilder::with_features(vec![minimize_unassigned, transport_feature, capacity_feature])?
// the goal is split into global and local parts:
// - on global level we prefer solutions where:
// 1. minimum of unassigned jobs
// 2. minimum distance traveled
// - on local level, as all jobs have the same weight, we prefer jobs that introduce a minimal distance change
.set_goal(&["min-unassigned", "min-distance"], &["min-distance"])?
.build()
// configure goal of optimization: features with objectives are read from ordered feature list. Here we have:
// 1. minimum of unassigned jobs as the main objective
// 2. minimum distance traveled
GoalContextBuilder::with_features(&[minimize_unassigned, transport_feature, capacity_feature])?.build()
}

fn main() -> GenericResult<()> {
Expand Down
9 changes: 1 addition & 8 deletions vrp-core/examples/pdptw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,7 @@ fn define_goal(transport: Arc<dyn TransportCost + Send + Sync>) -> GenericResult
.build_minimize_distance()?;

// configure goal of optimization
GoalContextBuilder::with_features(vec![minimize_unassigned, transport_feature, capacity_feature])?
// the goal is split into global and local parts:
// - on global level we prefer solutions where:
// 1. minimum of unassigned jobs
// 2. minimum distance traveled
// - on local level, as all jobs have the same weight, we prefer jobs that introduce a minimal distance change
.set_goal(&["min-unassigned", "min-distance"], &["min-distance"])?
.build()
GoalContextBuilder::with_features(&[minimize_unassigned, transport_feature, capacity_feature])?.build()
}

fn main() -> GenericResult<()> {
Expand Down
28 changes: 21 additions & 7 deletions vrp-core/src/construction/enablers/feature_combinator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,19 @@ impl FeatureState for CombinedFeatureState {
accept_route_state_with_states(&self.states, route_ctx)
}

fn accept_solution_state(&self, solution_ctx: &mut SolutionContext) {
accept_solution_state_with_states(&self.states, solution_ctx)
fn accept_solution_state(&self, ctx: &mut SolutionContext) {
// NOTE should not use a version with fallback to avoid hiding changes for other states
self.states.iter().try_for_each(|state| {
let previous_state = (ctx.required.len(), ctx.ignored.len(), ctx.unassigned.len());

state.accept_solution_state(ctx);

if has_changes(ctx, previous_state) {
ControlFlow::Break(())
} else {
ControlFlow::Continue(())
}
});
}
}

Expand Down Expand Up @@ -183,11 +194,6 @@ pub(crate) fn accept_route_state_with_states(states: &[Arc<dyn FeatureState>], r
}

pub(crate) fn accept_solution_state_with_states(states: &[Arc<dyn FeatureState>], solution_ctx: &mut SolutionContext) {
let has_changes = |ctx: &SolutionContext, previous_state: (usize, usize, usize)| {
let (required, ignored, unassigned) = previous_state;
required != ctx.required.len() || ignored != ctx.ignored.len() || unassigned != ctx.unassigned.len()
};

let _ = (0..).try_fold((usize::MAX, usize::MAX, usize::MAX), |(required, ignored, unassigned), counter| {
// NOTE if any job promotion occurs, then we might need to recalculate states.
// As it is hard to maintain dependencies between different modules, we reset process to
Expand Down Expand Up @@ -244,3 +250,11 @@ pub(crate) fn evaluate_with_constraints(
})
.unwrap_value()
}

fn has_changes(solution_ctx: &SolutionContext, previous_state: (usize, usize, usize)) -> bool {
let (required, ignored, unassigned) = previous_state;

required != solution_ctx.required.len()
|| ignored != solution_ctx.ignored.len()
|| unassigned != solution_ctx.unassigned.len()
}
4 changes: 1 addition & 3 deletions vrp-core/src/models/examples.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,7 @@ fn create_example_goal_ctx(
CapacityFeatureBuilder::<SingleDimLoad>::new("capacity").build()?,
];

GoalContextBuilder::with_features(features)?
.set_goal(&["min_jobs", "min_tours", "min_distance"], &["min_tours", "min_distance"])?
.build()
GoalContextBuilder::with_features(&features)?.build()
}

pub fn build_example_problem() -> GenericResult<Arc<Problem>> {
Expand Down
Loading

0 comments on commit 34379e1

Please sign in to comment.