Skip to content

Rjf/metric constraints#120

Merged
robfitzgerald merged 19 commits intomainfrom
rjf/metric-constraints
Mar 18, 2026
Merged

Rjf/metric constraints#120
robfitzgerald merged 19 commits intomainfrom
rjf/metric-constraints

Conversation

@robfitzgerald
Copy link
Collaborator

@robfitzgerald robfitzgerald commented Mar 12, 2026

this PR Closes #35 by introducing additional multimodal constraints that are based on metrics rather than the mode switching history of the trip.

note: this implementation is complete for distance and time metrics, but not for energy. a tech debt issue was created for this in #121, since energy-based metrics are not currently a priority.

along the way,

  • removed the trip legs constraint, which is now handled automatically by the MultimodalConstraintModel
  • max_trip_legs type changed to a NonZeroU64 to prevent underflow/prevent invalid configuration (max == 0 is nonsensical)

@robfitzgerald robfitzgerald requested a review from Copilot March 12, 2026 23:36
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduces new multimodal constraint capabilities based on traversal metrics (distance/time/energy) and leg-specific targeting, while moving trip-leg limiting into the MultimodalConstraintModel itself (closing #35).

Changes:

  • Added energy state accessors and fieldnames for per-leg energy tracking.
  • Expanded multimodal constraint configuration to include metric-based and leg-targeted constraints (distance/time/energy), plus a richer limit operation model.
  • Moved max-trip-legs enforcement into MultimodalConstraintModel::valid_frontier and updated tests accordingly.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
rust/bambam/src/model/state/multimodal_state_ops.rs Adds per-leg energy accessor to support energy-based constraints.
rust/bambam/src/model/state/fieldname.rs Adds leg energy fieldname to standardize state variable naming.
rust/bambam/src/model/constraint/multimodal/model.rs Enforces max trip legs early in valid_frontier; adjusts tests to remove explicit constraint.
rust/bambam/src/model/constraint/multimodal/mod.rs Re-exports newly introduced constraint config types.
rust/bambam/src/model/constraint/multimodal/constraint_config.rs Adds metric-based constraint types, leg targeting, and limit operations; updates config schema/docs.
rust/bambam/src/model/constraint/multimodal/constraint.rs Implements validation for new metric-based constraints and conversion from config to runtime constraints.
rust/bambam-core/src/model/bambam_json.rs Removes obsolete JSON model types.
Comments suppressed due to low confidence (1)

rust/bambam/src/model/constraint/multimodal/constraint_config.rs:1

  • These structs include both a limit as a uom quantity and a separate unit, but the unit is not used when evaluating constraints (test compares value directly to self.limit). As a result, configs like { limit = 0.5, unit = \"miles\" } will either deserialize incorrectly (depending on how uom is configured) or will not apply the unit conversion. Consider storing limit as a raw number (e.g., f64) plus unit, and constructing Length/Time/Energy during validation, or implement custom (de)serialization that converts (limit, unit) into the correct uom quantity.
use bambam_core::model::{

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Collaborator

@yamilbknsu yamilbknsu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Super cool. 🚀

I'm wondering if it would be a good idea for the future to extend the idea of the TripLegConstraint enum to be able to describe the mode_sequences.

Intrusive thought:

One could (not necessarily should) do something like:

mode_leg_time_limit.walk = { leg.type = "first", constraint = { limit = 0.0, unit = "minutes", op="min_exclusive" } }

to force the first leg to be walk, right?

/// mode_distance_limit.walk = { limit = 0.5, unit = "miles" }
/// ```
///
/// ## Walk mode can only be used at the beginning and end of a trip
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this be Walk must be the beginning and end of a trip + Walk can only be used at the beginning and end of a trip?

And if I'm reading it correctly, it should be exact_sequences right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah good catch. rewrote it to say Walk mode can only be used in the first or third leg of a trip which may include a middle leg in either bike or drive mode. and changed to exact_sequences

@robfitzgerald
Copy link
Collaborator Author

Super cool. 🚀

I'm wondering if it would be a good idea for the future to extend the idea of the TripLegConstraint enum to be able to describe the mode_sequences.

maybe? it would require refactoring the how for exact_sequences. that's currently backed by a Trie data structure which we traverse to find accepted sub-sequences. i'm not sure we can build the same structure from TripLegConstraint values, since the semantics for a few variants are only acceptable at certain positions (root, leaf) in the trie. but we could also likely build a trie from a Vec<(TripLegConstraint, String)> of modenames with constraints. 🤷 open to the idea.

Intrusive thought:

One could (not necessarily should) do something like:

mode_leg_time_limit.walk = { leg.type = "first", constraint = { limit = 0.0, unit = "minutes", op="min_exclusive" } }

to force the first leg to be walk, right?

that should work! maybe something we circle back around to if we encounter issues with performance.

@robfitzgerald robfitzgerald merged commit 819b717 into main Mar 18, 2026
1 check passed
@robfitzgerald robfitzgerald deleted the rjf/metric-constraints branch March 18, 2026 22:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

multimodal metric-based constraints

3 participants