1// Copyright 2023 Google LLC 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15syntax = "proto3"; 16 17package google.cloud.optimization.v1; 18 19import "google/api/annotations.proto"; 20import "google/api/client.proto"; 21import "google/api/field_behavior.proto"; 22import "google/cloud/optimization/v1/async_model.proto"; 23import "google/longrunning/operations.proto"; 24import "google/protobuf/duration.proto"; 25import "google/protobuf/timestamp.proto"; 26import "google/type/latlng.proto"; 27 28option go_package = "cloud.google.com/go/optimization/apiv1/optimizationpb;optimizationpb"; 29option java_multiple_files = true; 30option java_outer_classname = "FleetRoutingProto"; 31option java_package = "com.google.cloud.optimization.v1"; 32 33// A service for optimizing vehicle tours. 34// 35// Validity of certain types of fields: 36// 37// * `google.protobuf.Timestamp` 38// * Times are in Unix time: seconds since 1970-01-01T00:00:00+00:00. 39// * seconds must be in [0, 253402300799], 40// i.e. in [1970-01-01T00:00:00+00:00, 9999-12-31T23:59:59+00:00]. 41// * nanos must be unset or set to 0. 42// * `google.protobuf.Duration` 43// * seconds must be in [0, 253402300799], 44// i.e. in [1970-01-01T00:00:00+00:00, 9999-12-31T23:59:59+00:00]. 45// * nanos must be unset or set to 0. 46// * `google.type.LatLng` 47// * latitude must be in [-90.0, 90.0]. 48// * longitude must be in [-180.0, 180.0]. 49// * at least one of latitude and longitude must be non-zero. 50service FleetRouting { 51 option (google.api.default_host) = "cloudoptimization.googleapis.com"; 52 option (google.api.oauth_scopes) = 53 "https://www.googleapis.com/auth/cloud-platform"; 54 55 // Sends an `OptimizeToursRequest` containing a `ShipmentModel` and returns an 56 // `OptimizeToursResponse` containing `ShipmentRoute`s, which are a set of 57 // routes to be performed by vehicles minimizing the overall cost. 58 // 59 // A `ShipmentModel` model consists mainly of `Shipment`s that need to be 60 // carried out and `Vehicle`s that can be used to transport the `Shipment`s. 61 // The `ShipmentRoute`s assign `Shipment`s to `Vehicle`s. More specifically, 62 // they assign a series of `Visit`s to each vehicle, where a `Visit` 63 // corresponds to a `VisitRequest`, which is a pickup or delivery for a 64 // `Shipment`. 65 // 66 // The goal is to provide an assignment of `ShipmentRoute`s to `Vehicle`s that 67 // minimizes the total cost where cost has many components defined in the 68 // `ShipmentModel`. 69 rpc OptimizeTours(OptimizeToursRequest) returns (OptimizeToursResponse) { 70 option (google.api.http) = { 71 post: "/v1/{parent=projects/*/locations/*}:optimizeTours" 72 body: "*" 73 additional_bindings { 74 post: "/v1/{parent=projects/*}:optimizeTours" 75 body: "*" 76 } 77 }; 78 } 79 80 // Optimizes vehicle tours for one or more `OptimizeToursRequest` 81 // messages as a batch. 82 // 83 // This method is a Long Running Operation (LRO). The inputs for optimization 84 // (`OptimizeToursRequest` messages) and outputs (`OptimizeToursResponse` 85 // messages) are read/written from/to Cloud Storage in user-specified 86 // format. Like the `OptimizeTours` method, each `OptimizeToursRequest` 87 // contains a `ShipmentModel` and returns an `OptimizeToursResponse` 88 // containing `ShipmentRoute`s, which are a set of routes to be performed by 89 // vehicles minimizing the overall cost. 90 rpc BatchOptimizeTours(BatchOptimizeToursRequest) 91 returns (google.longrunning.Operation) { 92 option (google.api.http) = { 93 post: "/v1/{parent=projects/*/locations/*}:batchOptimizeTours" 94 body: "*" 95 additional_bindings { 96 post: "/v1/{parent=projects/*}:batchOptimizeTours" 97 body: "*" 98 } 99 }; 100 option (google.longrunning.operation_info) = { 101 response_type: "BatchOptimizeToursResponse" 102 metadata_type: "AsyncModelMetadata" 103 }; 104 } 105} 106 107// Request to be given to a tour optimization solver which defines the 108// shipment model to solve as well as optimization parameters. 109message OptimizeToursRequest { 110 // Defines how the solver should handle the request. In all modes but 111 // `VALIDATE_ONLY`, if the request is invalid, you will receive an 112 // `INVALID_REQUEST` error. See 113 // [max_validation_errors][google.cloud.optimization.v1.OptimizeToursRequest.max_validation_errors] 114 // to cap the number of errors returned. 115 enum SolvingMode { 116 // Solve the model. 117 DEFAULT_SOLVE = 0; 118 119 // Only validates the model without solving it: populates as many 120 // [OptimizeToursResponse.validation_errors][google.cloud.optimization.v1.OptimizeToursResponse.validation_errors] 121 // as possible. 122 VALIDATE_ONLY = 1; 123 124 // Only populates 125 // [OptimizeToursResponse.validation_errors][google.cloud.optimization.v1.OptimizeToursResponse.validation_errors] 126 // or 127 // [OptimizeToursResponse.skipped_shipments][google.cloud.optimization.v1.OptimizeToursResponse.skipped_shipments], 128 // and doesn't actually solve the rest of the request (`status` and `routes` 129 // are unset in the response). 130 // If infeasibilities in `injected_solution_constraint` routes are detected 131 // they are populated in the 132 // [OptimizeToursResponse.validation_errors][google.cloud.optimization.v1.OptimizeToursResponse.validation_errors] 133 // field and 134 // [OptimizeToursResponse.skipped_shipments][google.cloud.optimization.v1.OptimizeToursResponse.skipped_shipments] 135 // is left empty. 136 // 137 // *IMPORTANT*: not all infeasible shipments are returned here, but only the 138 // ones that are detected as infeasible during preprocessing. 139 DETECT_SOME_INFEASIBLE_SHIPMENTS = 2; 140 } 141 142 // Mode defining the behavior of the search, trading off latency versus 143 // solution quality. In all modes, the global request deadline is enforced. 144 enum SearchMode { 145 // Unspecified search mode, equivalent to `RETURN_FAST`. 146 SEARCH_MODE_UNSPECIFIED = 0; 147 148 // Stop the search after finding the first good solution. 149 RETURN_FAST = 1; 150 151 // Spend all the available time to search for better solutions. 152 CONSUME_ALL_AVAILABLE_TIME = 2; 153 } 154 155 // Required. Target project and location to make a call. 156 // 157 // Format: `projects/{project-id}/locations/{location-id}`. 158 // 159 // If no location is specified, a region will be chosen automatically. 160 string parent = 1 [(google.api.field_behavior) = REQUIRED]; 161 162 // If this timeout is set, the server returns a response before the timeout 163 // period has elapsed or the server deadline for synchronous requests is 164 // reached, whichever is sooner. 165 // 166 // For asynchronous requests, the server will generate a solution (if 167 // possible) before the timeout has elapsed. 168 google.protobuf.Duration timeout = 2; 169 170 // Shipment model to solve. 171 ShipmentModel model = 3; 172 173 // By default, the solving mode is `DEFAULT_SOLVE` (0). 174 SolvingMode solving_mode = 4; 175 176 // Search mode used to solve the request. 177 SearchMode search_mode = 6; 178 179 // Guide the optimization algorithm in finding a first solution that is 180 // similar to a previous solution. 181 // 182 // The model is constrained when the first solution is built. 183 // Any shipments not performed on a route are implicitly skipped in the first 184 // solution, but they may be performed in successive solutions. 185 // 186 // The solution must satisfy some basic validity assumptions: 187 // 188 // * for all routes, `vehicle_index` must be in range and not be duplicated. 189 // * for all visits, `shipment_index` and `visit_request_index` must be 190 // in range. 191 // * a shipment may only be referenced on one route. 192 // * the pickup of a pickup-delivery shipment must be performed before 193 // the delivery. 194 // * no more than one pickup alternative or delivery alternative of 195 // a shipment may be performed. 196 // * for all routes, times are increasing (i.e., `vehicle_start_time 197 // <= visits[0].start_time <= visits[1].start_time ... 198 // <= vehicle_end_time`). 199 // * a shipment may only be performed on a vehicle that is allowed. A 200 // vehicle is allowed if 201 // [Shipment.allowed_vehicle_indices][google.cloud.optimization.v1.Shipment.allowed_vehicle_indices] 202 // is empty or its `vehicle_index` is included in 203 // [Shipment.allowed_vehicle_indices][google.cloud.optimization.v1.Shipment.allowed_vehicle_indices]. 204 // 205 // If the injected solution is not feasible, a validation error is not 206 // necessarily returned and an error indicating infeasibility may be returned 207 // instead. 208 repeated ShipmentRoute injected_first_solution_routes = 7; 209 210 // Constrain the optimization algorithm to find a final solution that is 211 // similar to a previous solution. For example, this may be used to freeze 212 // portions of routes which have already been completed or which are to be 213 // completed but must not be modified. 214 // 215 // If the injected solution is not feasible, a validation error is not 216 // necessarily returned and an error indicating infeasibility may be returned 217 // instead. 218 InjectedSolutionConstraint injected_solution_constraint = 8; 219 220 // If non-empty, the given routes will be refreshed, without modifying their 221 // underlying sequence of visits or travel times: only other details will be 222 // updated. This does not solve the model. 223 // 224 // As of 2020/11, this only populates the polylines of non-empty routes and 225 // requires that `populate_polylines` is true. 226 // 227 // The `route_polyline` fields of the passed-in routes may be inconsistent 228 // with route `transitions`. 229 // 230 // This field must not be used together with `injected_first_solution_routes` 231 // or `injected_solution_constraint`. 232 // 233 // `Shipment.ignore` and `Vehicle.ignore` have no effect on the behavior. 234 // Polylines are still populated between all visits in all non-empty routes 235 // regardless of whether the related shipments or vehicles are ignored. 236 repeated ShipmentRoute refresh_details_routes = 9; 237 238 // If true: 239 // 240 // * uses 241 // [ShipmentRoute.vehicle_label][google.cloud.optimization.v1.ShipmentRoute.vehicle_label] 242 // instead of `vehicle_index` to 243 // match routes in an injected solution with vehicles in the request; 244 // reuses the mapping of original 245 // [ShipmentRoute.vehicle_index][google.cloud.optimization.v1.ShipmentRoute.vehicle_index] 246 // to new 247 // [ShipmentRoute.vehicle_index][google.cloud.optimization.v1.ShipmentRoute.vehicle_index] 248 // to update 249 // [ConstraintRelaxation.vehicle_indices][google.cloud.optimization.v1.InjectedSolutionConstraint.ConstraintRelaxation.vehicle_indices] 250 // if non-empty, but the mapping must be unambiguous (i.e., multiple 251 // `ShipmentRoute`s must not share the same original `vehicle_index`). 252 // * uses 253 // [ShipmentRoute.Visit.shipment_label][google.cloud.optimization.v1.ShipmentRoute.Visit.shipment_label] 254 // instead of `shipment_index` 255 // to match visits in an injected solution with shipments in the request; 256 // * uses 257 // [SkippedShipment.label][google.cloud.optimization.v1.SkippedShipment.label] 258 // instead of 259 // [SkippedShipment.index][google.cloud.optimization.v1.SkippedShipment.index] 260 // to 261 // match skipped shipments in the injected solution with request 262 // shipments. 263 // 264 // This interpretation applies to the `injected_first_solution_routes`, 265 // `injected_solution_constraint`, and `refresh_details_routes` fields. 266 // It can be used when shipment or vehicle indices in the request have 267 // changed since the solution was created, perhaps because shipments or 268 // vehicles have been removed from or added to the request. 269 // 270 // If true, labels in the following categories must appear at most once in 271 // their category: 272 // 273 // * [Vehicle.label][google.cloud.optimization.v1.Vehicle.label] in the 274 // request; 275 // * [Shipment.label][google.cloud.optimization.v1.Shipment.label] in the 276 // request; 277 // * [ShipmentRoute.vehicle_label][google.cloud.optimization.v1.ShipmentRoute.vehicle_label] in the injected solution; 278 // * [SkippedShipment.label][google.cloud.optimization.v1.SkippedShipment.label] and [ShipmentRoute.Visit.shipment_label][google.cloud.optimization.v1.ShipmentRoute.Visit.shipment_label] in 279 // the injected solution (except pickup/delivery visit pairs, whose 280 // `shipment_label` must appear twice). 281 // 282 // If a `vehicle_label` in the injected solution does not correspond to a 283 // request vehicle, the corresponding route is removed from the solution 284 // along with its visits. If a `shipment_label` in the injected solution does 285 // not correspond to a request shipment, the corresponding visit is removed 286 // from the solution. If a 287 // [SkippedShipment.label][google.cloud.optimization.v1.SkippedShipment.label] 288 // in the injected solution does not correspond to a request shipment, the 289 // `SkippedShipment` is removed from the solution. 290 // 291 // Removing route visits or entire routes from an injected solution may 292 // have an effect on the implied constraints, which may lead to change in 293 // solution, validation errors, or infeasibility. 294 // 295 // NOTE: The caller must ensure that each 296 // [Vehicle.label][google.cloud.optimization.v1.Vehicle.label] (resp. 297 // [Shipment.label][google.cloud.optimization.v1.Shipment.label]) uniquely 298 // identifies a vehicle (resp. shipment) entity used across the two relevant 299 // requests: the past request that produced the `OptimizeToursResponse` used 300 // in the injected solution and the current request that includes the injected 301 // solution. The uniqueness checks described above are not enough to guarantee 302 // this requirement. 303 bool interpret_injected_solutions_using_labels = 10; 304 305 // Consider traffic estimation in calculating `ShipmentRoute` fields 306 // [Transition.travel_duration][google.cloud.optimization.v1.ShipmentRoute.Transition.travel_duration], 307 // [Visit.start_time][google.cloud.optimization.v1.ShipmentRoute.Visit.start_time], 308 // and `vehicle_end_time`; in setting the 309 // [ShipmentRoute.has_traffic_infeasibilities][google.cloud.optimization.v1.ShipmentRoute.has_traffic_infeasibilities] 310 // field, and in calculating the 311 // [OptimizeToursResponse.total_cost][google.cloud.optimization.v1.OptimizeToursResponse.total_cost] 312 // field. 313 bool consider_road_traffic = 11; 314 315 // If true, polylines will be populated in response `ShipmentRoute`s. 316 bool populate_polylines = 12; 317 318 // If true, polylines will be populated in response 319 // [ShipmentRoute.transitions][google.cloud.optimization.v1.ShipmentRoute.transitions]. 320 // Note that in this case, the polylines will also be populated in the 321 // deprecated `travel_steps`. 322 bool populate_transition_polylines = 13; 323 324 // If this is set, then the request can have a deadline 325 // (see https://grpc.io/blog/deadlines) of up to 60 minutes. 326 // Otherwise, the maximum deadline is only 30 minutes. 327 // Note that long-lived requests have a significantly larger (but still small) 328 // risk of interruption. 329 bool allow_large_deadline_despite_interruption_risk = 14; 330 331 // If true, travel distances will be computed using geodesic distances instead 332 // of Google Maps distances, and travel times will be computed using geodesic 333 // distances with a speed defined by `geodesic_meters_per_second`. 334 bool use_geodesic_distances = 15; 335 336 // When `use_geodesic_distances` is true, this field must be set and defines 337 // the speed applied to compute travel times. Its value must be at least 1.0 338 // meters/seconds. 339 optional double geodesic_meters_per_second = 16; 340 341 // Truncates the number of validation errors returned. These errors are 342 // typically attached to an INVALID_ARGUMENT error payload as a BadRequest 343 // error detail (https://cloud.google.com/apis/design/errors#error_details), 344 // unless solving_mode=VALIDATE_ONLY: see the 345 // [OptimizeToursResponse.validation_errors][google.cloud.optimization.v1.OptimizeToursResponse.validation_errors] 346 // field. 347 // This defaults to 100 and is capped at 10,000. 348 optional int32 max_validation_errors = 5; 349 350 // Label that may be used to identify this request, reported back in the 351 // [OptimizeToursResponse.request_label][google.cloud.optimization.v1.OptimizeToursResponse.request_label]. 352 string label = 17; 353 354 // Deprecated: Use 355 // [OptimizeToursRequest.populate_transition_polylines][google.cloud.optimization.v1.OptimizeToursRequest.populate_transition_polylines] 356 // instead. If true, polylines will be populated in response 357 // [ShipmentRoute.transitions][google.cloud.optimization.v1.ShipmentRoute.transitions]. 358 // Note that in this case, the polylines will also be populated in the 359 // deprecated `travel_steps`. 360 bool populate_travel_step_polylines = 20 [deprecated = true]; 361} 362 363// Response after solving a tour optimization problem containing the routes 364// followed by each vehicle, the shipments which have been skipped and the 365// overall cost of the solution. 366message OptimizeToursResponse { 367 // Overall metrics, aggregated over all routes. 368 message Metrics { 369 // Aggregated over the routes. Each metric is the sum (or max, for loads) 370 // over all 371 // [ShipmentRoute.metrics][google.cloud.optimization.v1.ShipmentRoute.metrics] 372 // fields of the same name. 373 AggregatedMetrics aggregated_route_metrics = 1; 374 375 // Number of mandatory shipments skipped. 376 int32 skipped_mandatory_shipment_count = 2; 377 378 // Number of vehicles used. Note: if a vehicle route is empty and 379 // [Vehicle.used_if_route_is_empty][google.cloud.optimization.v1.Vehicle.used_if_route_is_empty] 380 // is true, the vehicle is considered used. 381 int32 used_vehicle_count = 3; 382 383 // The earliest start time for a used vehicle, computed as the minimum over 384 // all used vehicles of 385 // [ShipmentRoute.vehicle_start_time][google.cloud.optimization.v1.ShipmentRoute.vehicle_start_time]. 386 google.protobuf.Timestamp earliest_vehicle_start_time = 4; 387 388 // The latest end time for a used vehicle, computed as the maximum over all 389 // used vehicles of 390 // [ShipmentRoute.vehicle_end_time][google.cloud.optimization.v1.ShipmentRoute.vehicle_end_time]. 391 google.protobuf.Timestamp latest_vehicle_end_time = 5; 392 393 // Cost of the solution, broken down by cost-related request fields. 394 // The keys are proto paths, relative to the input OptimizeToursRequest, 395 // e.g. "model.shipments.pickups.cost", and the values are the total cost 396 // generated by the corresponding cost field, aggregated over the whole 397 // solution. In other words, costs["model.shipments.pickups.cost"] is the 398 // sum of all pickup costs over the solution. All costs defined in the model 399 // are reported in detail here with the exception of costs related to 400 // TransitionAttributes that are only reported in an aggregated way as of 401 // 2022/01. 402 map<string, double> costs = 10; 403 404 // Total cost of the solution. The sum of all values in the costs map. 405 double total_cost = 6; 406 } 407 408 // Routes computed for each vehicle; the i-th route corresponds to the i-th 409 // vehicle in the model. 410 repeated ShipmentRoute routes = 1; 411 412 // Copy of the 413 // [OptimizeToursRequest.label][google.cloud.optimization.v1.OptimizeToursRequest.label], 414 // if a label was specified in the request. 415 string request_label = 3; 416 417 // The list of all shipments skipped. 418 repeated SkippedShipment skipped_shipments = 4; 419 420 // List of all the validation errors that we were able to detect 421 // independently. See the "MULTIPLE ERRORS" explanation for the 422 // [OptimizeToursValidationError][google.cloud.optimization.v1.OptimizeToursValidationError] 423 // message. 424 repeated OptimizeToursValidationError validation_errors = 5; 425 426 // Duration, distance and usage metrics for this solution. 427 Metrics metrics = 6; 428 429 // Deprecated: Use 430 // [Metrics.total_cost][google.cloud.optimization.v1.OptimizeToursResponse.Metrics.total_cost] 431 // instead. Total cost of the solution. This takes into account all costs: 432 // costs per per hour and travel hour, fixed vehicle costs, unperformed 433 // shipment penalty costs, global duration cost, etc. 434 double total_cost = 2 [deprecated = true]; 435} 436 437// Request to batch optimize tours as an asynchronous operation. 438// Each input file should contain one `OptimizeToursRequest`, and each output 439// file will contain one `OptimizeToursResponse`. The request contains 440// information to read/write and parse the files. All the input and output files 441// should be under the same project. 442message BatchOptimizeToursRequest { 443 // Information for solving one optimization model asynchronously. 444 message AsyncModelConfig { 445 // User defined model name, can be used as alias by users to keep track of 446 // models. 447 string display_name = 1; 448 449 // Required. Information about the input model. 450 InputConfig input_config = 2 [(google.api.field_behavior) = REQUIRED]; 451 452 // Required. The desired output location information. 453 OutputConfig output_config = 3 [(google.api.field_behavior) = REQUIRED]; 454 455 // If this is set, the model will be solved in the checkpoint mode. In this 456 // mode, the input model can have a deadline longer than 30 mins without the 457 // risk of interruption. The model will be solved in multiple short-running 458 // stages. Each stage generates an intermediate checkpoint 459 // and stores it in the user's Cloud Storage buckets. The checkpoint 460 // mode should be preferred over 461 // allow_large_deadline_despite_interruption_risk since it prevents the risk 462 // of interruption. 463 bool enable_checkpoints = 4; 464 } 465 466 // Required. Target project and location to make a call. 467 // 468 // Format: `projects/{project-id}/locations/{location-id}`. 469 // 470 // If no location is specified, a region will be chosen automatically. 471 string parent = 1 [(google.api.field_behavior) = REQUIRED]; 472 473 // Required. Input/Output information each purchase model, such as file paths 474 // and data formats. 475 repeated AsyncModelConfig model_configs = 2 476 [(google.api.field_behavior) = REQUIRED]; 477} 478 479// Response to a `BatchOptimizeToursRequest`. This is returned in 480// the LRO Operation after the operation is complete. 481message BatchOptimizeToursResponse {} 482 483// A shipment model contains a set of shipments which must be performed by a 484// set of vehicles, while minimizing the overall cost, which is the sum of: 485// 486// * the cost of routing the vehicles (sum of cost per total time, cost per 487// travel time, and fixed cost over all vehicles). 488// * the unperformed shipment penalties. 489// * the cost of the global duration of the shipments 490message ShipmentModel { 491 // Specifies a duration and distance matrix from visit and vehicle start 492 // locations to visit and vehicle end locations. 493 message DurationDistanceMatrix { 494 // Specifies a row of the duration and distance matrix. 495 message Row { 496 // Duration values for a given row. It must have as many elements as 497 // [ShipmentModel.duration_distance_matrix_dst_tags][google.cloud.optimization.v1.ShipmentModel.duration_distance_matrix_dst_tags]. 498 repeated google.protobuf.Duration durations = 1; 499 500 // Distance values for a given row. If no costs or constraints refer to 501 // distances in the model, this can be left empty; otherwise it must have 502 // as many elements as `durations`. 503 repeated double meters = 2; 504 } 505 506 // Specifies the rows of the duration and distance matrix. It must have as 507 // many elements as 508 // [ShipmentModel.duration_distance_matrix_src_tags][google.cloud.optimization.v1.ShipmentModel.duration_distance_matrix_src_tags]. 509 repeated Row rows = 1; 510 511 // Tag defining to which vehicles this duration and distance matrix applies. 512 // If empty, this applies to all vehicles, and there can only be a single 513 // matrix. 514 // 515 // Each vehicle start must match exactly one matrix, i.e. exactly one of 516 // their `start_tags` field must match the `vehicle_start_tag` of a matrix 517 // (and of that matrix only). 518 // 519 // All matrices must have a different `vehicle_start_tag`. 520 string vehicle_start_tag = 2; 521 } 522 523 // A precedence rule between two events (each event is the pickup or the 524 // delivery of a shipment): the "second" event has to start at least 525 // `offset_duration` after "first" has started. 526 // 527 // Several precedences can refer to the same (or related) events, e.g., 528 // "pickup of B happens after delivery of A" and "pickup of C happens after 529 // pickup of B". 530 // 531 // Furthermore, precedences only apply when both shipments are performed and 532 // are otherwise ignored. 533 message PrecedenceRule { 534 // Shipment index of the "first" event. This field must be specified. 535 optional int32 first_index = 1; 536 537 // Indicates if the "first" event is a delivery. 538 bool first_is_delivery = 3; 539 540 // Shipment index of the "second" event. This field must be specified. 541 optional int32 second_index = 2; 542 543 // Indicates if the "second" event is a delivery. 544 bool second_is_delivery = 4; 545 546 // The offset between the "first" and "second" event. It can be negative. 547 google.protobuf.Duration offset_duration = 5; 548 } 549 550 // Deprecated: Use top level 551 // [BreakRule][google.cloud.optimization.v1.ShipmentModel.BreakRule] instead. 552 // Rules to generate time breaks for a vehicle (e.g. lunch 553 // breaks). A break is a contiguous period of time during which the vehicle 554 // remains idle at its current position and cannot perform any visit. A break 555 // may occur: 556 // 557 // * during the travel between two visits (which includes the time right 558 // before or right after a visit, but not in the middle of a visit), in 559 // which case it extends the corresponding transit time between the visits 560 // * before the vehicle start (the vehicle may not start in the middle of 561 // a break), in which case it does not affect the vehicle start time. 562 // * after the vehicle end (ditto, with the vehicle end time). 563 message BreakRule { 564 option deprecated = true; 565 566 // The sequence of breaks (i.e. their number and order) that apply to each 567 // vehicle must be known beforehand. The repeated `BreakRequest`s define 568 // that sequence, in the order in which they must occur. Their time windows 569 // (`earliest_start_time` / `latest_start_time`) may overlap, but they must 570 // be compatible with the order (this is checked). 571 message BreakRequest { 572 // Required. Lower bound (inclusive) on the start of the break. 573 google.protobuf.Timestamp earliest_start_time = 1 574 [(google.api.field_behavior) = REQUIRED]; 575 576 // Required. Upper bound (inclusive) on the start of the break. 577 google.protobuf.Timestamp latest_start_time = 2 578 [(google.api.field_behavior) = REQUIRED]; 579 580 // Required. Minimum duration of the break. Must be positive. 581 google.protobuf.Duration min_duration = 3 582 [(google.api.field_behavior) = REQUIRED]; 583 } 584 585 // One may further constrain the frequency and duration of the breaks 586 // specified above, by enforcing a minimum break frequency, such as 587 // "There must be a break of at least 1 hour every 12 hours". Assuming that 588 // this can be interpreted as "Within any sliding time window of 12h, there 589 // must be at least one break of at least one hour", that example would 590 // translate to the following `FrequencyConstraint`: 591 // ``` 592 // { 593 // min_break_duration { seconds: 3600 } # 1 hour. 594 // max_inter_break_duration { seconds: 39600 } # 11 hours (12 - 1 = 11). 595 // } 596 // ``` 597 // 598 // The timing and duration of the breaks in the solution will respect all 599 // such constraints, in addition to the time windows and minimum durations 600 // already specified in the `BreakRequest`. 601 // 602 // A `FrequencyConstraint` may in practice apply to non-consecutive breaks. 603 // For example, the following schedule honors the "1h every 12h" example: 604 // ``` 605 // 04:00 vehicle start 606 // .. performing travel and visits .. 607 // 09:00 1 hour break 608 // 10:00 end of the break 609 // .. performing travel and visits .. 610 // 12:00 20-min lunch break 611 // 12:20 end of the break 612 // .. performing travel and visits .. 613 // 21:00 1 hour break 614 // 22:00 end of the break 615 // .. performing travel and visits .. 616 // 23:59 vehicle end 617 // ``` 618 message FrequencyConstraint { 619 // Required. Minimum break duration for this constraint. Nonnegative. 620 // See description of `FrequencyConstraint`. 621 google.protobuf.Duration min_break_duration = 1 622 [(google.api.field_behavior) = REQUIRED]; 623 624 // Required. Maximum allowed span of any interval of time in the route 625 // that does not include at least partially a break of `duration >= 626 // min_break_duration`. Must be positive. 627 google.protobuf.Duration max_inter_break_duration = 2 628 [(google.api.field_behavior) = REQUIRED]; 629 } 630 631 // Sequence of breaks. See the `BreakRequest` message. 632 repeated BreakRequest break_requests = 1; 633 634 // Several `FrequencyConstraint` may apply. They must all be satisfied by 635 // the `BreakRequest`s of this `BreakRule`. See `FrequencyConstraint`. 636 repeated FrequencyConstraint frequency_constraints = 2; 637 } 638 639 // Set of shipments which must be performed in the model. 640 repeated Shipment shipments = 1; 641 642 // Set of vehicles which can be used to perform visits. 643 repeated Vehicle vehicles = 2; 644 645 // Constrains the maximum number of active vehicles. A vehicle is active if 646 // its route performs at least one shipment. This can be used to limit the 647 // number of routes in the case where there are fewer drivers than 648 // vehicles and that the fleet of vehicles is heterogeneous. The optimization 649 // will then select the best subset of vehicles to use. 650 // Must be strictly positive. 651 optional int32 max_active_vehicles = 4; 652 653 // Global start and end time of the model: no times outside of this range 654 // can be considered valid. 655 // 656 // The model's time span must be less than a year, i.e. the `global_end_time` 657 // and the `global_start_time` must be within 31536000 seconds of each other. 658 // 659 // When using `cost_per_*hour` fields, you might want to set this window to a 660 // smaller interval to increase performance (eg. if you model a single day, 661 // you should set the global time limits to that day). 662 // If unset, 00:00:00 UTC, January 1, 1970 (i.e. seconds: 0, nanos: 0) is used 663 // as default. 664 google.protobuf.Timestamp global_start_time = 5; 665 666 // If unset, 00:00:00 UTC, January 1, 1971 (i.e. seconds: 31536000, nanos: 0) 667 // is used as default. 668 google.protobuf.Timestamp global_end_time = 6; 669 670 // The "global duration" of the overall plan is the difference between the 671 // earliest effective start time and the latest effective end time of 672 // all vehicles. Users can assign a cost per hour to that quantity to try 673 // and optimize for earliest job completion, for example. This cost must be in 674 // the same unit as 675 // [Shipment.penalty_cost][google.cloud.optimization.v1.Shipment.penalty_cost]. 676 double global_duration_cost_per_hour = 7; 677 678 // Specifies duration and distance matrices used in the model. If this field 679 // is empty, Google Maps or geodesic distances will be used instead, depending 680 // on the value of the `use_geodesic_distances` field. If it is not empty, 681 // `use_geodesic_distances` cannot be true and neither 682 // `duration_distance_matrix_src_tags` nor `duration_distance_matrix_dst_tags` 683 // can be empty. 684 // 685 // Usage examples: 686 // 687 // * There are two locations: locA and locB. 688 // * 1 vehicle starting its route at locA and ending it at locA. 689 // * 1 pickup visit request at locB. 690 // 691 // ``` 692 // model { 693 // vehicles { start_tags: "locA" end_tags: "locA" } 694 // shipments { pickups { tags: "locB" } } 695 // duration_distance_matrix_src_tags: "locA" 696 // duration_distance_matrix_src_tags: "locB" 697 // duration_distance_matrix_dst_tags: "locA" 698 // duration_distance_matrix_dst_tags: "locB" 699 // duration_distance_matrices { 700 // rows { # from: locA 701 // durations { seconds: 0 } meters: 0 # to: locA 702 // durations { seconds: 100 } meters: 1000 # to: locB 703 // } 704 // rows { # from: locB 705 // durations { seconds: 102 } meters: 990 # to: locA 706 // durations { seconds: 0 } meters: 0 # to: locB 707 // } 708 // } 709 // } 710 // ``` 711 // 712 // 713 // * There are three locations: locA, locB and locC. 714 // * 1 vehicle starting its route at locA and ending it at locB, using 715 // matrix "fast". 716 // * 1 vehicle starting its route at locB and ending it at locB, using 717 // matrix "slow". 718 // * 1 vehicle starting its route at locB and ending it at locB, using 719 // matrix "fast". 720 // * 1 pickup visit request at locC. 721 // 722 // ``` 723 // model { 724 // vehicles { start_tags: "locA" end_tags: "locB" start_tags: "fast" } 725 // vehicles { start_tags: "locB" end_tags: "locB" start_tags: "slow" } 726 // vehicles { start_tags: "locB" end_tags: "locB" start_tags: "fast" } 727 // shipments { pickups { tags: "locC" } } 728 // duration_distance_matrix_src_tags: "locA" 729 // duration_distance_matrix_src_tags: "locB" 730 // duration_distance_matrix_src_tags: "locC" 731 // duration_distance_matrix_dst_tags: "locB" 732 // duration_distance_matrix_dst_tags: "locC" 733 // duration_distance_matrices { 734 // vehicle_start_tag: "fast" 735 // rows { # from: locA 736 // durations { seconds: 1000 } meters: 2000 # to: locB 737 // durations { seconds: 600 } meters: 1000 # to: locC 738 // } 739 // rows { # from: locB 740 // durations { seconds: 0 } meters: 0 # to: locB 741 // durations { seconds: 700 } meters: 1200 # to: locC 742 // } 743 // rows { # from: locC 744 // durations { seconds: 702 } meters: 1190 # to: locB 745 // durations { seconds: 0 } meters: 0 # to: locC 746 // } 747 // } 748 // duration_distance_matrices { 749 // vehicle_start_tag: "slow" 750 // rows { # from: locA 751 // durations { seconds: 1800 } meters: 2001 # to: locB 752 // durations { seconds: 900 } meters: 1002 # to: locC 753 // } 754 // rows { # from: locB 755 // durations { seconds: 0 } meters: 0 # to: locB 756 // durations { seconds: 1000 } meters: 1202 # to: locC 757 // } 758 // rows { # from: locC 759 // durations { seconds: 1001 } meters: 1195 # to: locB 760 // durations { seconds: 0 } meters: 0 # to: locC 761 // } 762 // } 763 // } 764 // ``` 765 repeated DurationDistanceMatrix duration_distance_matrices = 8; 766 767 // Tags defining the sources of the duration and distance matrices; 768 // `duration_distance_matrices(i).rows(j)` defines durations and distances 769 // from visits with tag `duration_distance_matrix_src_tags(j)` to other visits 770 // in matrix i. 771 // 772 // Tags correspond to 773 // [VisitRequest.tags][google.cloud.optimization.v1.Shipment.VisitRequest.tags] 774 // or [Vehicle.start_tags][google.cloud.optimization.v1.Vehicle.start_tags]. 775 // A given `VisitRequest` or `Vehicle` must match exactly one tag in this 776 // field. Note that a `Vehicle`'s source, destination and matrix tags may be 777 // the same; similarly a `VisitRequest`'s source and destination tags may be 778 // the same. All tags must be different and cannot be empty strings. If this 779 // field is not empty, then `duration_distance_matrices` must not be empty. 780 repeated string duration_distance_matrix_src_tags = 9; 781 782 // Tags defining the destinations of the duration and distance matrices; 783 // `duration_distance_matrices(i).rows(j).durations(k)` (resp. 784 // `duration_distance_matrices(i).rows(j).meters(k))` defines the duration 785 // (resp. the distance) of the travel from visits with tag 786 // `duration_distance_matrix_src_tags(j)` to visits with tag 787 // `duration_distance_matrix_dst_tags(k)` in matrix i. 788 // 789 // Tags correspond to 790 // [VisitRequest.tags][google.cloud.optimization.v1.Shipment.VisitRequest.tags] 791 // or [Vehicle.start_tags][google.cloud.optimization.v1.Vehicle.start_tags]. 792 // A given `VisitRequest` or `Vehicle` must match exactly one tag in this 793 // field. Note that a `Vehicle`'s source, destination and matrix tags may be 794 // the same; similarly a `VisitRequest`'s source and destination tags may be 795 // the same. All tags must be different and cannot be empty strings. If this 796 // field is not empty, then `duration_distance_matrices` must not be empty. 797 repeated string duration_distance_matrix_dst_tags = 10; 798 799 // Transition attributes added to the model. 800 repeated TransitionAttributes transition_attributes = 11; 801 802 // Sets of incompatible shipment_types (see `ShipmentTypeIncompatibility`). 803 repeated ShipmentTypeIncompatibility shipment_type_incompatibilities = 12; 804 805 // Sets of `shipment_type` requirements (see `ShipmentTypeRequirement`). 806 repeated ShipmentTypeRequirement shipment_type_requirements = 13; 807 808 // Set of precedence rules which must be enforced in the model. 809 repeated PrecedenceRule precedence_rules = 14; 810 811 // Deprecated: No longer used. 812 // Set of break rules used in the model. 813 // Each vehicle specifies the `BreakRule` that applies to it via the 814 // [Vehicle.break_rule_indices][google.cloud.optimization.v1.Vehicle.break_rule_indices] 815 // field (which must be a singleton). 816 repeated BreakRule break_rules = 15 [deprecated = true]; 817} 818 819// The shipment of a single item, from one of its pickups to one of its 820// deliveries. For the shipment to be considered as performed, a unique vehicle 821// must visit one of its pickup locations (and decrease its spare capacities 822// accordingly), then visit one of its delivery locations later on (and 823// therefore re-increase its spare capacities accordingly). 824message Shipment { 825 // Request for a visit which can be done by a vehicle: it has a geo-location 826 // (or two, see below), opening and closing times represented by time windows, 827 // and a service duration time (time spent by the vehicle once it has arrived 828 // to pickup or drop off goods). 829 message VisitRequest { 830 // The geo-location where the vehicle arrives when performing this 831 // `VisitRequest`. If the shipment model has duration distance matrices, 832 // `arrival_location` must not be specified. 833 google.type.LatLng arrival_location = 1; 834 835 // The waypoint where the vehicle arrives when performing this 836 // `VisitRequest`. If the shipment model has duration distance matrices, 837 // `arrival_waypoint` must not be specified. 838 Waypoint arrival_waypoint = 2; 839 840 // The geo-location where the vehicle departs after completing this 841 // `VisitRequest`. Can be omitted if it is the same as `arrival_location`. 842 // If the shipment model has duration distance matrices, 843 // `departure_location` must not be specified. 844 google.type.LatLng departure_location = 3; 845 846 // The waypoint where the vehicle departs after completing this 847 // `VisitRequest`. Can be omitted if it is the same as `arrival_waypoint`. 848 // If the shipment model has duration distance matrices, 849 // `departure_waypoint` must not be specified. 850 Waypoint departure_waypoint = 4; 851 852 // Specifies tags attached to the visit request. 853 // Empty or duplicate strings are not allowed. 854 repeated string tags = 5; 855 856 // Time windows which constrain the arrival time at a visit. 857 // Note that a vehicle may depart outside of the arrival time window, i.e. 858 // arrival time + duration do not need to be inside a time window. This can 859 // result in waiting time if the vehicle arrives before 860 // [TimeWindow.start_time][google.cloud.optimization.v1.TimeWindow.start_time]. 861 // 862 // The absence of `TimeWindow` means that the vehicle can perform this visit 863 // at any time. 864 // 865 // Time windows must be disjoint, i.e. no time window must overlap with or 866 // be adjacent to another, and they must be in increasing order. 867 // 868 // `cost_per_hour_after_soft_end_time` and `soft_end_time` can only 869 // be set if there is a single time window. 870 repeated TimeWindow time_windows = 6; 871 872 // Duration of the visit, i.e. time spent by the vehicle between arrival 873 // and departure (to be added to the possible waiting time; see 874 // `time_windows`). 875 google.protobuf.Duration duration = 7; 876 877 // Cost to service this visit request on a vehicle route. This can be used 878 // to pay different costs for each alternative pickup or delivery of a 879 // shipment. This cost must be in the same unit as `Shipment.penalty_cost` 880 // and must not be negative. 881 double cost = 8; 882 883 // Load demands of this visit request. This is just like 884 // [Shipment.load_demands][google.cloud.optimization.v1.Shipment.load_demands] 885 // field, except that it only applies to this 886 // [VisitRequest][google.cloud.optimization.v1.Shipment.VisitRequest] 887 // instead of the whole [Shipment][google.cloud.optimization.v1.Shipment]. 888 // The demands listed here are added to the demands listed in 889 // [Shipment.load_demands][google.cloud.optimization.v1.Shipment.load_demands]. 890 map<string, Load> load_demands = 12; 891 892 // Specifies the types of the visit. This may be used to allocate additional 893 // time required for a vehicle to complete this visit (see 894 // [Vehicle.extra_visit_duration_for_visit_type][google.cloud.optimization.v1.Vehicle.extra_visit_duration_for_visit_type]). 895 // 896 // A type can only appear once. 897 repeated string visit_types = 10; 898 899 // Specifies a label for this `VisitRequest`. This label is reported in the 900 // response as `visit_label` in the corresponding 901 // [ShipmentRoute.Visit][google.cloud.optimization.v1.ShipmentRoute.Visit]. 902 string label = 11; 903 904 // Deprecated: Use 905 // [VisitRequest.load_demands][google.cloud.optimization.v1.Shipment.VisitRequest.load_demands] 906 // instead. 907 repeated CapacityQuantity demands = 9 [deprecated = true]; 908 } 909 910 // When performing a visit, a predefined amount may be added to the vehicle 911 // load if it's a pickup, or subtracted if it's a delivery. This message 912 // defines such amount. See 913 // [load_demands][google.cloud.optimization.v1.Shipment.load_demands]. 914 message Load { 915 // The amount by which the load of the vehicle performing the corresponding 916 // visit will vary. Since it is an integer, users are advised to choose an 917 // appropriate unit to avoid loss of precision. Must be ≥ 0. 918 int64 amount = 2; 919 } 920 921 // Set of pickup alternatives associated to the shipment. If not specified, 922 // the vehicle only needs to visit a location corresponding to the deliveries. 923 repeated VisitRequest pickups = 1; 924 925 // Set of delivery alternatives associated to the shipment. If not specified, 926 // the vehicle only needs to visit a location corresponding to the pickups. 927 repeated VisitRequest deliveries = 2; 928 929 // Load demands of the shipment (for example weight, volume, number of 930 // pallets etc). The keys in the map should be identifiers describing the type 931 // of the corresponding load, ideally also including the units. 932 // For example: "weight_kg", "volume_gallons", "pallet_count", etc. 933 // If a given key does not appear in the map, the corresponding load is 934 // considered as null. 935 map<string, Load> load_demands = 14; 936 937 // If the shipment is not completed, this penalty is added to the overall 938 // cost of the routes. A shipment is considered completed if one of its pickup 939 // and delivery alternatives is visited. The cost may be expressed in the 940 // same unit used for all other cost-related fields in the model and must be 941 // positive. 942 // 943 // *IMPORTANT*: If this penalty is not specified, it is considered infinite, 944 // i.e. the shipment must be completed. 945 optional double penalty_cost = 4; 946 947 // The set of vehicles that may perform this shipment. If empty, all vehicles 948 // may perform it. Vehicles are given by their index in the `ShipmentModel`'s 949 // `vehicles` list. 950 repeated int32 allowed_vehicle_indices = 5; 951 952 // Specifies the cost that is incurred when this shipment is delivered by each 953 // vehicle. If specified, it must have EITHER: 954 // 955 // * the same number of elements as `costs_per_vehicle_indices`. 956 // `costs_per_vehicle[i]` corresponds to vehicle 957 // `costs_per_vehicle_indices[i]` of the model. 958 // * the same number of elements as there are vehicles in the model. The 959 // i-th element corresponds to vehicle #i of the model. 960 // 961 // These costs must be in the same unit as `penalty_cost` and must not be 962 // negative. Leave this field empty, if there are no such costs. 963 repeated double costs_per_vehicle = 6; 964 965 // Indices of the vehicles to which `costs_per_vehicle` applies. If non-empty, 966 // it must have the same number of elements as `costs_per_vehicle`. A vehicle 967 // index may not be specified more than once. If a vehicle is excluded from 968 // `costs_per_vehicle_indices`, its cost is zero. 969 repeated int32 costs_per_vehicle_indices = 7; 970 971 // Specifies the maximum relative detour time compared to the shortest path 972 // from pickup to delivery. If specified, it must be nonnegative, and the 973 // shipment must contain at least a pickup and a delivery. 974 // 975 // For example, let t be the shortest time taken to go from the selected 976 // pickup alternative directly to the selected delivery alternative. Then 977 // setting `pickup_to_delivery_relative_detour_limit` enforces: 978 // 979 // ``` 980 // start_time(delivery) - start_time(pickup) <= 981 // std::ceil(t * (1.0 + pickup_to_delivery_relative_detour_limit)) 982 // ``` 983 // 984 // If both relative and absolute limits are specified on the same shipment, 985 // the more constraining limit is used for each possible pickup/delivery pair. 986 // As of 2017/10, detours are only supported when travel durations do not 987 // depend on vehicles. 988 optional double pickup_to_delivery_relative_detour_limit = 8; 989 990 // Specifies the maximum absolute detour time compared to the shortest path 991 // from pickup to delivery. If specified, it must be nonnegative, and the 992 // shipment must contain at least a pickup and a delivery. 993 // 994 // For example, let t be the shortest time taken to go from the selected 995 // pickup alternative directly to the selected delivery alternative. Then 996 // setting `pickup_to_delivery_absolute_detour_limit` enforces: 997 // 998 // ``` 999 // start_time(delivery) - start_time(pickup) <= 1000 // t + pickup_to_delivery_absolute_detour_limit 1001 // ``` 1002 // 1003 // If both relative and absolute limits are specified on the same shipment, 1004 // the more constraining limit is used for each possible pickup/delivery pair. 1005 // As of 2017/10, detours are only supported when travel durations do not 1006 // depend on vehicles. 1007 google.protobuf.Duration pickup_to_delivery_absolute_detour_limit = 9; 1008 1009 // Specifies the maximum duration from start of pickup to start of delivery of 1010 // a shipment. If specified, it must be nonnegative, and the shipment must 1011 // contain at least a pickup and a delivery. This does not depend on which 1012 // alternatives are selected for pickup and delivery, nor on vehicle speed. 1013 // This can be specified alongside maximum detour constraints: the solution 1014 // will respect both specifications. 1015 google.protobuf.Duration pickup_to_delivery_time_limit = 10; 1016 1017 // Non-empty string specifying a "type" for this shipment. 1018 // This feature can be used to define incompatibilities or requirements 1019 // between `shipment_types` (see `shipment_type_incompatibilities` and 1020 // `shipment_type_requirements` in `ShipmentModel`). 1021 // 1022 // Differs from `visit_types` which is specified for a single visit: All 1023 // pickup/deliveries belonging to the same shipment share the same 1024 // `shipment_type`. 1025 string shipment_type = 11; 1026 1027 // Specifies a label for this shipment. This label is reported in the response 1028 // in the `shipment_label` of the corresponding 1029 // [ShipmentRoute.Visit][google.cloud.optimization.v1.ShipmentRoute.Visit]. 1030 string label = 12; 1031 1032 // If true, skip this shipment, but don't apply a `penalty_cost`. 1033 // 1034 // Ignoring a shipment results in a validation error when there are any 1035 // `shipment_type_requirements` in the model. 1036 // 1037 // Ignoring a shipment that is performed in `injected_first_solution_routes` 1038 // or `injected_solution_constraint` is permitted; the solver removes the 1039 // related pickup/delivery visits from the performing route. 1040 // `precedence_rules` that reference ignored shipments will also be ignored. 1041 bool ignore = 13; 1042 1043 // Deprecated: Use 1044 // [Shipment.load_demands][google.cloud.optimization.v1.Shipment.load_demands] 1045 // instead. 1046 repeated CapacityQuantity demands = 3 [deprecated = true]; 1047} 1048 1049// Specifies incompatibilties between shipments depending on their 1050// shipment_type. The appearance of incompatible shipments on the same route is 1051// restricted based on the incompatibility mode. 1052message ShipmentTypeIncompatibility { 1053 // Modes defining how the appearance of incompatible shipments are restricted 1054 // on the same route. 1055 enum IncompatibilityMode { 1056 // Unspecified incompatibility mode. This value should never be used. 1057 INCOMPATIBILITY_MODE_UNSPECIFIED = 0; 1058 1059 // In this mode, two shipments with incompatible types can never share the 1060 // same vehicle. 1061 NOT_PERFORMED_BY_SAME_VEHICLE = 1; 1062 1063 // For two shipments with incompatible types with the 1064 // `NOT_IN_SAME_VEHICLE_SIMULTANEOUSLY` incompatibility mode: 1065 // 1066 // * If both are pickups only (no deliveries) or deliveries only (no 1067 // pickups), they cannot share the same vehicle at all. 1068 // * If one of the shipments has a delivery and the other a pickup, the two 1069 // shipments can share the same vehicle iff the former shipment is 1070 // delivered before the latter is picked up. 1071 NOT_IN_SAME_VEHICLE_SIMULTANEOUSLY = 2; 1072 } 1073 1074 // List of incompatible types. Two shipments having different `shipment_types` 1075 // among those listed are "incompatible". 1076 repeated string types = 1; 1077 1078 // Mode applied to the incompatibility. 1079 IncompatibilityMode incompatibility_mode = 2; 1080} 1081 1082// Specifies requirements between shipments based on their shipment_type. 1083// The specifics of the requirement are defined by the requirement mode. 1084message ShipmentTypeRequirement { 1085 // Modes defining the appearance of dependent shipments on a route. 1086 enum RequirementMode { 1087 // Unspecified requirement mode. This value should never be used. 1088 REQUIREMENT_MODE_UNSPECIFIED = 0; 1089 1090 // In this mode, all "dependent" shipments must share the same vehicle as at 1091 // least one of their "required" shipments. 1092 PERFORMED_BY_SAME_VEHICLE = 1; 1093 1094 // With the `IN_SAME_VEHICLE_AT_PICKUP_TIME` mode, all "dependent" 1095 // shipments need to have at least one "required" shipment on their vehicle 1096 // at the time of their pickup. 1097 // 1098 // A "dependent" shipment pickup must therefore have either: 1099 // 1100 // * A delivery-only "required" shipment delivered on the route after, or 1101 // * A "required" shipment picked up on the route before it, and if the 1102 // "required" shipment has a delivery, this delivery must be performed 1103 // after the "dependent" shipment's pickup. 1104 IN_SAME_VEHICLE_AT_PICKUP_TIME = 2; 1105 1106 // Same as before, except the "dependent" shipments need to have a 1107 // "required" shipment on their vehicle at the time of their *delivery*. 1108 IN_SAME_VEHICLE_AT_DELIVERY_TIME = 3; 1109 } 1110 1111 // List of alternative shipment types required by the 1112 // `dependent_shipment_types`. 1113 repeated string required_shipment_type_alternatives = 1; 1114 1115 // All shipments with a type in the `dependent_shipment_types` field require 1116 // at least one shipment of type `required_shipment_type_alternatives` to be 1117 // visited on the same route. 1118 // 1119 // NOTE: Chains of requirements such that a `shipment_type` depends on itself 1120 // are not allowed. 1121 repeated string dependent_shipment_types = 2; 1122 1123 // Mode applied to the requirement. 1124 RequirementMode requirement_mode = 3; 1125} 1126 1127// Encapsulates a set of optional conditions to satisfy when calculating 1128// vehicle routes. This is similar to `RouteModifiers` in the Google Maps 1129// Platform API; see: 1130// https://developers.google.com/maps/documentation/routes/reference/rest/v2/RouteModifiers. 1131message RouteModifiers { 1132 // Specifies whether to avoid toll roads where reasonable. Preference will be 1133 // given to routes not containing toll roads. Applies only to motorized travel 1134 // modes. 1135 bool avoid_tolls = 2; 1136 1137 // Specifies whether to avoid highways where reasonable. Preference will be 1138 // given to routes not containing highways. Applies only to motorized travel 1139 // modes. 1140 bool avoid_highways = 3; 1141 1142 // Specifies whether to avoid ferries where reasonable. Preference will be 1143 // given to routes not containing travel by ferries. Applies only to motorized 1144 // travel modes. 1145 bool avoid_ferries = 4; 1146 1147 // Optional. Specifies whether to avoid navigating indoors where reasonable. 1148 // Preference will be given to routes not containing indoor navigation. 1149 // Applies only to the `WALKING` travel mode. 1150 bool avoid_indoor = 5 [(google.api.field_behavior) = OPTIONAL]; 1151} 1152 1153// Models a vehicle in a shipment problem. Solving a shipment problem will 1154// build a route starting from `start_location` and ending at `end_location` 1155// for this vehicle. A route is a sequence of visits (see `ShipmentRoute`). 1156message Vehicle { 1157 // Travel modes which can be used by vehicles. 1158 // 1159 // These should be a subset of the Google Maps Platform Routes Preferred API 1160 // travel modes, see: 1161 // https://developers.google.com/maps/documentation/routes_preferred/reference/rest/Shared.Types/RouteTravelMode. 1162 enum TravelMode { 1163 // Unspecified travel mode, equivalent to `DRIVING`. 1164 TRAVEL_MODE_UNSPECIFIED = 0; 1165 1166 // Travel mode corresponding to driving directions (car, ...). 1167 DRIVING = 1; 1168 1169 // Travel mode corresponding to walking directions. 1170 WALKING = 2; 1171 } 1172 1173 // Policy on how a vehicle can be unloaded. Applies only to shipments having 1174 // both a pickup and a delivery. 1175 // 1176 // Other shipments are free to occur anywhere on the route independent of 1177 // `unloading_policy`. 1178 enum UnloadingPolicy { 1179 // Unspecified unloading policy; deliveries must just occur after their 1180 // corresponding pickups. 1181 UNLOADING_POLICY_UNSPECIFIED = 0; 1182 1183 // Deliveries must occur in reverse order of pickups 1184 LAST_IN_FIRST_OUT = 1; 1185 1186 // Deliveries must occur in the same order as pickups 1187 FIRST_IN_FIRST_OUT = 2; 1188 } 1189 1190 // Defines a load limit applying to a vehicle, e.g. "this truck may only 1191 // carry up to 3500 kg". See 1192 // [load_limits][google.cloud.optimization.v1.Vehicle.load_limits]. 1193 message LoadLimit { 1194 // Interval of acceptable load amounts. 1195 message Interval { 1196 // A minimum acceptable load. Must be ≥ 0. 1197 // If they're both specified, 1198 // [min][google.cloud.optimization.v1.Vehicle.LoadLimit.Interval.min] must 1199 // be ≤ 1200 // [max][google.cloud.optimization.v1.Vehicle.LoadLimit.Interval.max]. 1201 int64 min = 1; 1202 1203 // A maximum acceptable load. Must be ≥ 0. If unspecified, the maximum 1204 // load is unrestricted by this message. 1205 // If they're both specified, 1206 // [min][google.cloud.optimization.v1.Vehicle.LoadLimit.Interval.min] must 1207 // be ≤ 1208 // [max][google.cloud.optimization.v1.Vehicle.LoadLimit.Interval.max]. 1209 optional int64 max = 2; 1210 } 1211 1212 // The maximum acceptable amount of load. 1213 optional int64 max_load = 1; 1214 1215 // A soft limit of the load. See 1216 // [cost_per_unit_above_soft_max][google.cloud.optimization.v1.Vehicle.LoadLimit.cost_per_unit_above_soft_max]. 1217 int64 soft_max_load = 2; 1218 1219 // If the load ever exceeds 1220 // [soft_max_load][google.cloud.optimization.v1.Vehicle.LoadLimit.soft_max_load] 1221 // along this vehicle's route, the following cost penalty applies (only once 1222 // per vehicle): (load - 1223 // [soft_max_load][google.cloud.optimization.v1.Vehicle.LoadLimit.soft_max_load]) 1224 // * [cost_per_unit_above_soft_max][google.cloud.optimization.v1.Vehicle.LoadLimit.cost_per_unit_above_soft_max]. All costs 1225 // add up and must be in the same unit as 1226 // [Shipment.penalty_cost][google.cloud.optimization.v1.Shipment.penalty_cost]. 1227 double cost_per_unit_above_soft_max = 3; 1228 1229 // The acceptable load interval of the vehicle at the start of the route. 1230 Interval start_load_interval = 4; 1231 1232 // The acceptable load interval of the vehicle at the end of the route. 1233 Interval end_load_interval = 5; 1234 } 1235 1236 // A limit defining a maximum duration of the route of a vehicle. It can be 1237 // either hard or soft. 1238 // 1239 // When a soft limit field is defined, both the soft max threshold and its 1240 // associated cost must be defined together. 1241 message DurationLimit { 1242 // A hard limit constraining the duration to be at most max_duration. 1243 google.protobuf.Duration max_duration = 1; 1244 1245 // A soft limit not enforcing a maximum duration limit, but when violated 1246 // makes the route incur a cost. This cost adds up to other costs defined in 1247 // the model, with the same unit. 1248 // 1249 // If defined, `soft_max_duration` must be nonnegative. If max_duration is 1250 // also defined, `soft_max_duration` must be less than max_duration. 1251 google.protobuf.Duration soft_max_duration = 2; 1252 1253 // Cost per hour incurred if the `soft_max_duration` threshold is violated. 1254 // The additional cost is 0 if the duration is under the threshold, 1255 // otherwise the cost depends on the duration as follows: 1256 // ``` 1257 // cost_per_hour_after_soft_max * (duration - soft_max_duration) 1258 // ``` 1259 // The cost must be nonnegative. 1260 optional double cost_per_hour_after_soft_max = 3; 1261 1262 // A soft limit not enforcing a maximum duration limit, but when violated 1263 // makes the route incur a cost, quadratic in the duration. This cost adds 1264 // up to other costs defined in the model, with the same unit. 1265 // 1266 // If defined, `quadratic_soft_max_duration` must be nonnegative. If 1267 // `max_duration` is also defined, `quadratic_soft_max_duration` must be 1268 // less than `max_duration`, and the difference must be no larger than one 1269 // day: 1270 // 1271 // `max_duration - quadratic_soft_max_duration <= 86400 seconds` 1272 google.protobuf.Duration quadratic_soft_max_duration = 4; 1273 1274 // Cost per square hour incurred if the 1275 // `quadratic_soft_max_duration` threshold is violated. 1276 // 1277 // The additional cost is 0 if the duration is under the threshold, 1278 // otherwise the cost depends on the duration as follows: 1279 // 1280 // ``` 1281 // cost_per_square_hour_after_quadratic_soft_max * 1282 // (duration - quadratic_soft_max_duration)^2 1283 // ``` 1284 // 1285 // The cost must be nonnegative. 1286 optional double cost_per_square_hour_after_quadratic_soft_max = 5; 1287 } 1288 1289 // The travel mode which affects the roads usable by the vehicle and its 1290 // speed. See also `travel_duration_multiple`. 1291 TravelMode travel_mode = 1; 1292 1293 // Optional. A set of conditions to satisfy that affect the way routes are 1294 // calculated for the given vehicle. 1295 RouteModifiers route_modifiers = 2 [(google.api.field_behavior) = OPTIONAL]; 1296 1297 // Geographic location where the vehicle starts before picking up any 1298 // shipments. If not specified, the vehicle starts at its first pickup. 1299 // If the shipment model has duration and distance matrices, `start_location` 1300 // must not be specified. 1301 google.type.LatLng start_location = 3; 1302 1303 // Waypoint representing a geographic location where the vehicle starts before 1304 // picking up any shipments. If neither `start_waypoint` nor `start_location` 1305 // is specified, the vehicle starts at its first pickup. 1306 // If the shipment model has duration and distance matrices, `start_waypoint` 1307 // must not be specified. 1308 Waypoint start_waypoint = 4; 1309 1310 // Geographic location where the vehicle ends after it has completed its last 1311 // `VisitRequest`. If not specified the vehicle's `ShipmentRoute` ends 1312 // immediately when it completes its last `VisitRequest`. 1313 // If the shipment model has duration and distance matrices, `end_location` 1314 // must not be specified. 1315 google.type.LatLng end_location = 5; 1316 1317 // Waypoint representing a geographic location where the vehicle ends after 1318 // it has completed its last `VisitRequest`. If neither `end_waypoint` nor 1319 // `end_location` is specified, the vehicle's `ShipmentRoute` ends immediately 1320 // when it completes its last `VisitRequest`. 1321 // If the shipment model has duration and distance matrices, `end_waypoint` 1322 // must not be specified. 1323 Waypoint end_waypoint = 6; 1324 1325 // Specifies tags attached to the start of the vehicle's route. 1326 // 1327 // Empty or duplicate strings are not allowed. 1328 repeated string start_tags = 7; 1329 1330 // Specifies tags attached to the end of the vehicle's route. 1331 // 1332 // Empty or duplicate strings are not allowed. 1333 repeated string end_tags = 8; 1334 1335 // Time windows during which the vehicle may depart its start location. 1336 // They must be within the global time limits (see 1337 // [ShipmentModel.global_*][google.cloud.optimization.v1.ShipmentModel.global_start_time] 1338 // fields). If unspecified, there is no limitation besides those global time 1339 // limits. 1340 // 1341 // Time windows belonging to the same repeated field must be disjoint, i.e. no 1342 // time window can overlap with or be adjacent to another, and they must be in 1343 // chronological order. 1344 // 1345 // `cost_per_hour_after_soft_end_time` and `soft_end_time` can only be set if 1346 // there is a single time window. 1347 repeated TimeWindow start_time_windows = 9; 1348 1349 // Time windows during which the vehicle may arrive at its end location. 1350 // They must be within the global time limits (see 1351 // [ShipmentModel.global_*][google.cloud.optimization.v1.ShipmentModel.global_start_time] 1352 // fields). If unspecified, there is no limitation besides those global time 1353 // limits. 1354 // 1355 // Time windows belonging to the same repeated field must be disjoint, i.e. no 1356 // time window can overlap with or be adjacent to another, and they must be in 1357 // chronological order. 1358 // 1359 // `cost_per_hour_after_soft_end_time` and `soft_end_time` can only be set if 1360 // there is a single time window. 1361 repeated TimeWindow end_time_windows = 10; 1362 1363 // Specifies a multiplicative factor that can be used to increase or decrease 1364 // travel times of this vehicle. For example, setting this to 2.0 means 1365 // that this vehicle is slower and has travel times that are twice what they 1366 // are for standard vehicles. This multiple does not affect visit durations. 1367 // It does affect cost if `cost_per_hour` or `cost_per_traveled_hour` are 1368 // specified. This must be in the range [0.001, 1000.0]. If unset, the vehicle 1369 // is standard, and this multiple is considered 1.0. 1370 // 1371 // WARNING: Travel times will be rounded to the nearest second after this 1372 // multiple is applied but before performing any numerical operations, thus, 1373 // a small multiple may result in a loss of precision. 1374 // 1375 // See also `extra_visit_duration_for_visit_type` below. 1376 optional double travel_duration_multiple = 11; 1377 1378 // Unloading policy enforced on the vehicle. 1379 UnloadingPolicy unloading_policy = 12; 1380 1381 // Capacities of the vehicle (weight, volume, # of pallets for example). 1382 // The keys in the map are the identifiers of the type of load, consistent 1383 // with the keys of the 1384 // [Shipment.load_demands][google.cloud.optimization.v1.Shipment.load_demands] 1385 // field. If a given key is absent from this map, the corresponding capacity 1386 // is considered to be limitless. 1387 map<string, LoadLimit> load_limits = 30; 1388 1389 // Vehicle costs: all costs add up and must be in the same unit as 1390 // [Shipment.penalty_cost][google.cloud.optimization.v1.Shipment.penalty_cost]. 1391 // 1392 // Cost per hour of the vehicle route. This cost is applied to the total time 1393 // taken by the route, and includes travel time, waiting time, and visit time. 1394 // Using `cost_per_hour` instead of just `cost_per_traveled_hour` may result 1395 // in additional latency. 1396 double cost_per_hour = 16; 1397 1398 // Cost per traveled hour of the vehicle route. This cost is applied only to 1399 // travel time taken by the route (i.e., that reported in 1400 // [ShipmentRoute.transitions][google.cloud.optimization.v1.ShipmentRoute.transitions]), 1401 // and excludes waiting time and visit time. 1402 double cost_per_traveled_hour = 17; 1403 1404 // Cost per kilometer of the vehicle route. This cost is applied to the 1405 // distance reported in the 1406 // [ShipmentRoute.transitions][google.cloud.optimization.v1.ShipmentRoute.transitions] 1407 // and does not apply to any distance implicitly traveled from the 1408 // `arrival_location` to the `departure_location` of a single `VisitRequest`. 1409 double cost_per_kilometer = 18; 1410 1411 // Fixed cost applied if this vehicle is used to handle a shipment. 1412 double fixed_cost = 19; 1413 1414 // This field only applies to vehicles when their route does not serve any 1415 // shipments. It indicates if the vehicle should be considered as used or not 1416 // in this case. 1417 // 1418 // If true, the vehicle goes from its start to its end location even if it 1419 // doesn't serve any shipments, and time and distance costs resulting from its 1420 // start --> end travel are taken into account. 1421 // 1422 // Otherwise, it doesn't travel from its start to its end location, and no 1423 // `break_rule` or delay (from `TransitionAttributes`) are scheduled for this 1424 // vehicle. In this case, the vehicle's `ShipmentRoute` doesn't contain any 1425 // information except for the vehicle index and label. 1426 bool used_if_route_is_empty = 20; 1427 1428 // Limit applied to the total duration of the vehicle's route. In a given 1429 // `OptimizeToursResponse`, the route duration of a vehicle is the 1430 // difference between its `vehicle_end_time` and `vehicle_start_time`. 1431 DurationLimit route_duration_limit = 21; 1432 1433 // Limit applied to the travel duration of the vehicle's route. In a given 1434 // `OptimizeToursResponse`, the route travel duration is the sum of all its 1435 // [transitions.travel_duration][google.cloud.optimization.v1.ShipmentRoute.Transition.travel_duration]. 1436 DurationLimit travel_duration_limit = 22; 1437 1438 // Limit applied to the total distance of the vehicle's route. In a given 1439 // `OptimizeToursResponse`, the route distance is the sum of all its 1440 // [transitions.travel_distance_meters][google.cloud.optimization.v1.ShipmentRoute.Transition.travel_distance_meters]. 1441 DistanceLimit route_distance_limit = 23; 1442 1443 // Specifies a map from visit_types strings to durations. The duration is time 1444 // in addition to 1445 // [VisitRequest.duration][google.cloud.optimization.v1.Shipment.VisitRequest.duration] 1446 // to be taken at visits with the specified `visit_types`. This extra visit 1447 // duration adds cost if `cost_per_hour` is specified. Keys (i.e. 1448 // `visit_types`) cannot be empty strings. 1449 // 1450 // If a visit request has multiple types, a duration will be added for each 1451 // type in the map. 1452 map<string, google.protobuf.Duration> extra_visit_duration_for_visit_type = 1453 24; 1454 1455 // Describes the break schedule to be enforced on this vehicle. 1456 // If empty, no breaks will be scheduled for this vehicle. 1457 BreakRule break_rule = 25; 1458 1459 // Specifies a label for this vehicle. This label is reported in the response 1460 // as the `vehicle_label` of the corresponding 1461 // [ShipmentRoute][google.cloud.optimization.v1.ShipmentRoute]. 1462 string label = 27; 1463 1464 // If true, `used_if_route_is_empty` must be false, and this vehicle will 1465 // remain unused. 1466 // 1467 // If a shipment is performed by an ignored vehicle in 1468 // `injected_first_solution_routes`, it is skipped in the first solution but 1469 // is free to be performed in the response. 1470 // 1471 // If a shipment is performed by an ignored vehicle in 1472 // `injected_solution_constraint` and any related pickup/delivery is 1473 // constrained to remain on the vehicle (i.e., not relaxed to level 1474 // `RELAX_ALL_AFTER_THRESHOLD`), it is skipped in the response. 1475 // If a shipment has a non-empty `allowed_vehicle_indices` field and all of 1476 // the allowed vehicles are ignored, it is skipped in the response. 1477 bool ignore = 28; 1478 1479 // Deprecated: No longer used. 1480 // Indices in the `break_rule` field in the source 1481 // [ShipmentModel][google.cloud.optimization.v1.ShipmentModel]. They 1482 // correspond to break rules enforced on the vehicle. 1483 // 1484 // As of 2018/03, at most one rule index per vehicle can be specified. 1485 repeated int32 break_rule_indices = 29 [deprecated = true]; 1486 1487 // Deprecated: Use 1488 // [Vehicle.load_limits][google.cloud.optimization.v1.Vehicle.load_limits] 1489 // instead. 1490 repeated CapacityQuantity capacities = 13 [deprecated = true]; 1491 1492 // Deprecated: Use 1493 // [Vehicle.LoadLimit.start_load_interval][google.cloud.optimization.v1.Vehicle.LoadLimit.start_load_interval] 1494 // instead. 1495 repeated CapacityQuantityInterval start_load_intervals = 14 1496 [deprecated = true]; 1497 1498 // Deprecated: Use 1499 // [Vehicle.LoadLimit.end_load_interval][google.cloud.optimization.v1.Vehicle.LoadLimit.end_load_interval] 1500 // instead. 1501 repeated CapacityQuantityInterval end_load_intervals = 15 [deprecated = true]; 1502} 1503 1504// Time windows constrain the time of an event, such as the arrival time at a 1505// visit, or the start and end time of a vehicle. 1506// 1507// Hard time window bounds, `start_time` and `end_time`, enforce the earliest 1508// and latest time of the event, such that `start_time <= event_time <= 1509// end_time`. The soft time window lower bound, `soft_start_time`, expresses a 1510// preference for the event to happen at or after `soft_start_time` by incurring 1511// a cost proportional to how long before soft_start_time the event occurs. The 1512// soft time window upper bound, `soft_end_time`, expresses a preference for the 1513// event to happen at or before `soft_end_time` by incurring a cost proportional 1514// to how long after `soft_end_time` the event occurs. `start_time`, `end_time`, 1515// `soft_start_time` and `soft_end_time` should be within the global time limits 1516// (see 1517// [ShipmentModel.global_start_time][google.cloud.optimization.v1.ShipmentModel.global_start_time] 1518// and 1519// [ShipmentModel.global_end_time][google.cloud.optimization.v1.ShipmentModel.global_end_time]) 1520// and should respect: 1521// ``` 1522// 0 <= `start_time` <= `soft_start_time` <= `end_time` and 1523// 0 <= `start_time` <= `soft_end_time` <= `end_time`. 1524// ``` 1525message TimeWindow { 1526 // The hard time window start time. If unspecified it will be set to 1527 // `ShipmentModel.global_start_time`. 1528 google.protobuf.Timestamp start_time = 1; 1529 1530 // The hard time window end time. If unspecified it will be set to 1531 // `ShipmentModel.global_end_time`. 1532 google.protobuf.Timestamp end_time = 2; 1533 1534 // The soft start time of the time window. 1535 google.protobuf.Timestamp soft_start_time = 3; 1536 1537 // The soft end time of the time window. 1538 google.protobuf.Timestamp soft_end_time = 4; 1539 1540 // A cost per hour added to other costs in the model if the event occurs 1541 // before soft_start_time, computed as: 1542 // 1543 // ``` 1544 // max(0, soft_start_time - t.seconds) 1545 // * cost_per_hour_before_soft_start_time / 3600, 1546 // t being the time of the event. 1547 // ``` 1548 // 1549 // This cost must be positive, and the field can only be set if 1550 // soft_start_time has been set. 1551 optional double cost_per_hour_before_soft_start_time = 5; 1552 1553 // A cost per hour added to other costs in the model if the event occurs after 1554 // `soft_end_time`, computed as: 1555 // 1556 // ``` 1557 // max(0, t.seconds - soft_end_time.seconds) 1558 // * cost_per_hour_after_soft_end_time / 3600, 1559 // t being the time of the event. 1560 // ``` 1561 // 1562 // This cost must be positive, and the field can only be set if 1563 // `soft_end_time` has been set. 1564 optional double cost_per_hour_after_soft_end_time = 6; 1565} 1566 1567// Deprecated: Use 1568// [Vehicle.LoadLimit.Interval][google.cloud.optimization.v1.Vehicle.LoadLimit.Interval] 1569// instead. 1570message CapacityQuantity { 1571 option deprecated = true; 1572 1573 string type = 1; 1574 1575 int64 value = 2; 1576} 1577 1578// Deprecated: Use 1579// [Vehicle.LoadLimit.Interval][google.cloud.optimization.v1.Vehicle.LoadLimit.Interval] 1580// instead. 1581message CapacityQuantityInterval { 1582 option deprecated = true; 1583 1584 string type = 1; 1585 1586 optional int64 min_value = 2; 1587 1588 optional int64 max_value = 3; 1589} 1590 1591// A limit defining a maximum distance which can be traveled. It can be either 1592// hard or soft. 1593// 1594// If a soft limit is defined, both `soft_max_meters` and 1595// `cost_per_kilometer_above_soft_max` must be defined and be nonnegative. 1596message DistanceLimit { 1597 // A hard limit constraining the distance to be at most max_meters. The limit 1598 // must be nonnegative. 1599 optional int64 max_meters = 1; 1600 1601 // A soft limit not enforcing a maximum distance limit, but when violated 1602 // results in a cost which adds up to other costs defined in the model, 1603 // with the same unit. 1604 // 1605 // If defined soft_max_meters must be less than max_meters and must be 1606 // nonnegative. 1607 optional int64 soft_max_meters = 2; 1608 1609 // Cost per kilometer incurred, increasing up to `soft_max_meters`, with 1610 // formula: 1611 // ``` 1612 // min(distance_meters, soft_max_meters) / 1000.0 * 1613 // cost_per_kilometer_below_soft_max. 1614 // ``` 1615 // This cost is not supported in `route_distance_limit`. 1616 optional double cost_per_kilometer_below_soft_max = 4; 1617 1618 // Cost per kilometer incurred if distance is above `soft_max_meters` limit. 1619 // The additional cost is 0 if the distance is under the limit, otherwise the 1620 // formula used to compute the cost is the following: 1621 // ``` 1622 // (distance_meters - soft_max_meters) / 1000.0 * 1623 // cost_per_kilometer_above_soft_max. 1624 // ``` 1625 // The cost must be nonnegative. 1626 optional double cost_per_kilometer_above_soft_max = 3; 1627} 1628 1629// Specifies attributes of transitions between two consecutive visits on a 1630// route. Several `TransitionAttributes` may apply to the same transition: in 1631// that case, all extra costs add up and the strictest constraint or limit 1632// applies (following natural "AND" semantics). 1633message TransitionAttributes { 1634 // Tags defining the set of (src->dst) transitions these attributes apply to. 1635 // 1636 // A source visit or vehicle start matches iff its 1637 // [VisitRequest.tags][google.cloud.optimization.v1.Shipment.VisitRequest.tags] 1638 // or [Vehicle.start_tags][google.cloud.optimization.v1.Vehicle.start_tags] 1639 // either contains `src_tag` or does not contain `excluded_src_tag` (depending 1640 // on which of these two fields is non-empty). 1641 string src_tag = 1; 1642 1643 // See `src_tag`. Exactly one of `src_tag` and `excluded_src_tag` must be 1644 // non-empty. 1645 string excluded_src_tag = 2; 1646 1647 // A destination visit or vehicle end matches iff its 1648 // [VisitRequest.tags][google.cloud.optimization.v1.Shipment.VisitRequest.tags] 1649 // or [Vehicle.end_tags][google.cloud.optimization.v1.Vehicle.end_tags] either 1650 // contains `dst_tag` or does not contain `excluded_dst_tag` (depending on 1651 // which of these two fields is non-empty). 1652 string dst_tag = 3; 1653 1654 // See `dst_tag`. Exactly one of `dst_tag` and `excluded_dst_tag` must be 1655 // non-empty. 1656 string excluded_dst_tag = 4; 1657 1658 // Specifies a cost for performing this transition. This is in the same unit 1659 // as all other costs in the model and must not be negative. It is applied on 1660 // top of all other existing costs. 1661 double cost = 5; 1662 1663 // Specifies a cost per kilometer applied to the distance traveled while 1664 // performing this transition. It adds up to any 1665 // [Vehicle.cost_per_kilometer][google.cloud.optimization.v1.Vehicle.cost_per_kilometer] 1666 // specified on vehicles. 1667 double cost_per_kilometer = 6; 1668 1669 // Specifies a limit on the distance traveled while performing this 1670 // transition. 1671 // 1672 // As of 2021/06, only soft limits are supported. 1673 DistanceLimit distance_limit = 7; 1674 1675 // Specifies a delay incurred when performing this transition. 1676 // 1677 // This delay always occurs *after* finishing the source visit and *before* 1678 // starting the destination visit. 1679 google.protobuf.Duration delay = 8; 1680} 1681 1682// Encapsulates a waypoint. Waypoints mark arrival and departure locations of 1683// VisitRequests, and start and end locations of Vehicles. 1684message Waypoint { 1685 // Different ways to represent a location. 1686 oneof location_type { 1687 // A point specified using geographic coordinates, including an optional 1688 // heading. 1689 Location location = 1; 1690 1691 // The POI Place ID associated with the waypoint. 1692 string place_id = 2; 1693 } 1694 1695 // Indicates that the location of this waypoint is meant to have a preference 1696 // for the vehicle to stop at a particular side of road. When you set this 1697 // value, the route will pass through the location so that the vehicle can 1698 // stop at the side of road that the location is biased towards from the 1699 // center of the road. This option works only for the 'DRIVING' travel mode, 1700 // and when the 'location_type' is set to 'location'. 1701 bool side_of_road = 3; 1702} 1703 1704// Encapsulates a location (a geographic point, and an optional heading). 1705message Location { 1706 // The waypoint's geographic coordinates. 1707 google.type.LatLng lat_lng = 1; 1708 1709 // The compass heading associated with the direction of the flow of traffic. 1710 // This value is used to specify the side of the road to use for pickup and 1711 // drop-off. Heading values can be from 0 to 360, where 0 specifies a heading 1712 // of due North, 90 specifies a heading of due East, etc. 1713 optional int32 heading = 2; 1714} 1715 1716// Rules to generate time breaks for a vehicle (e.g. lunch breaks). A break 1717// is a contiguous period of time during which the vehicle remains idle at its 1718// current position and cannot perform any visit. A break may occur: 1719// 1720// * during the travel between two visits (which includes the time right 1721// before or right after a visit, but not in the middle of a visit), in 1722// which case it extends the corresponding transit time between the visits, 1723// * or before the vehicle start (the vehicle may not start in the middle of 1724// a break), in which case it does not affect the vehicle start time. 1725// * or after the vehicle end (ditto, with the vehicle end time). 1726message BreakRule { 1727 // The sequence of breaks (i.e. their number and order) that apply to each 1728 // vehicle must be known beforehand. The repeated `BreakRequest`s define 1729 // that sequence, in the order in which they must occur. Their time windows 1730 // (`earliest_start_time` / `latest_start_time`) may overlap, but they must 1731 // be compatible with the order (this is checked). 1732 message BreakRequest { 1733 // Required. Lower bound (inclusive) on the start of the break. 1734 google.protobuf.Timestamp earliest_start_time = 1 1735 [(google.api.field_behavior) = REQUIRED]; 1736 1737 // Required. Upper bound (inclusive) on the start of the break. 1738 google.protobuf.Timestamp latest_start_time = 2 1739 [(google.api.field_behavior) = REQUIRED]; 1740 1741 // Required. Minimum duration of the break. Must be positive. 1742 google.protobuf.Duration min_duration = 3 1743 [(google.api.field_behavior) = REQUIRED]; 1744 } 1745 1746 // One may further constrain the frequency and duration of the breaks 1747 // specified above, by enforcing a minimum break frequency, such as 1748 // "There must be a break of at least 1 hour every 12 hours". Assuming that 1749 // this can be interpreted as "Within any sliding time window of 12h, there 1750 // must be at least one break of at least one hour", that example would 1751 // translate to the following `FrequencyConstraint`: 1752 // ``` 1753 // { 1754 // min_break_duration { seconds: 3600 } # 1 hour. 1755 // max_inter_break_duration { seconds: 39600 } # 11 hours (12 - 1 = 11). 1756 // } 1757 // ``` 1758 // 1759 // The timing and duration of the breaks in the solution will respect all 1760 // such constraints, in addition to the time windows and minimum durations 1761 // already specified in the `BreakRequest`. 1762 // 1763 // A `FrequencyConstraint` may in practice apply to non-consecutive breaks. 1764 // For example, the following schedule honors the "1h every 12h" example: 1765 // ``` 1766 // 04:00 vehicle start 1767 // .. performing travel and visits .. 1768 // 09:00 1 hour break 1769 // 10:00 end of the break 1770 // .. performing travel and visits .. 1771 // 12:00 20-min lunch break 1772 // 12:20 end of the break 1773 // .. performing travel and visits .. 1774 // 21:00 1 hour break 1775 // 22:00 end of the break 1776 // .. performing travel and visits .. 1777 // 23:59 vehicle end 1778 // ``` 1779 message FrequencyConstraint { 1780 // Required. Minimum break duration for this constraint. Nonnegative. 1781 // See description of `FrequencyConstraint`. 1782 google.protobuf.Duration min_break_duration = 1 1783 [(google.api.field_behavior) = REQUIRED]; 1784 1785 // Required. Maximum allowed span of any interval of time in the route that 1786 // does not include at least partially a break of `duration >= 1787 // min_break_duration`. Must be positive. 1788 google.protobuf.Duration max_inter_break_duration = 2 1789 [(google.api.field_behavior) = REQUIRED]; 1790 } 1791 1792 // Sequence of breaks. See the `BreakRequest` message. 1793 repeated BreakRequest break_requests = 1; 1794 1795 // Several `FrequencyConstraint` may apply. They must all be satisfied by 1796 // the `BreakRequest`s of this `BreakRule`. See `FrequencyConstraint`. 1797 repeated FrequencyConstraint frequency_constraints = 2; 1798} 1799 1800// A vehicle's route can be decomposed, along the time axis, like this (we 1801// assume there are n visits): 1802// ``` 1803// | | | | | T[2], | | | 1804// | Transition | Visit #0 | | | V[2], | | | 1805// | #0 | aka | T[1] | V[1] | ... | V[n-1] | T[n] | 1806// | aka T[0] | V[0] | | | V[n-2],| | | 1807// | | | | | T[n-1] | | | 1808// ^ ^ ^ ^ ^ ^ ^ ^ 1809// vehicle V[0].start V[0].end V[1]. V[1]. V[n]. V[n]. vehicle 1810// start (arrival) (departure) start end start end end 1811// ``` 1812// Note that we make a difference between: 1813// 1814// * "punctual events", such as the vehicle start and end and each visit's start 1815// and end (aka arrival and departure). They happen at a given second. 1816// * "time intervals", such as the visits themselves, and the transition between 1817// visits. Though time intervals can sometimes have zero duration, i.e. start 1818// and end at the same second, they often have a positive duration. 1819// 1820// Invariants: 1821// 1822// * If there are n visits, there are n+1 transitions. 1823// * A visit is always surrounded by a transition before it (same index) and a 1824// transition after it (index + 1). 1825// * The vehicle start is always followed by transition #0. 1826// * The vehicle end is always preceded by transition #n. 1827// 1828// Zooming in, here is what happens during a `Transition` and a `Visit`: 1829// ``` 1830// ---+-------------------------------------+-----------------------------+--> 1831// | TRANSITION[i] | VISIT[i] | 1832// | | | 1833// | * TRAVEL: the vehicle moves from | PERFORM the visit: | 1834// | VISIT[i-1].departure_location to | | 1835// | VISIT[i].arrival_location, which | * Spend some time: | 1836// | takes a given travel duration | the "visit duration". | 1837// | and distance | | 1838// | | * Load or unload | 1839// | * BREAKS: the driver may have | some quantities from the | 1840// | breaks (e.g. lunch break). | vehicle: the "demand". | 1841// | | | 1842// | * WAIT: the driver/vehicle does | | 1843// | nothing. This can happen for | | 1844// | many reasons, for example when | | 1845// | the vehicle reaches the next | | 1846// | event's destination before the | | 1847// | start of its time window | | 1848// | | | 1849// | * DELAY: *right before* the next | | 1850// | arrival. E.g. the vehicle and/or | | 1851// | driver spends time unloading. | | 1852// | | | 1853// ---+-------------------------------------+-----------------------------+--> 1854// ^ ^ ^ 1855// V[i-1].end V[i].start V[i].end 1856// ``` 1857// Lastly, here is how the TRAVEL, BREAKS, DELAY and WAIT can be arranged 1858// during a transition. 1859// 1860// * They don't overlap. 1861// * The DELAY is unique and *must* be a contiguous period of time right 1862// before the next visit (or vehicle end). Thus, it suffice to know the 1863// delay duration to know its start and end time. 1864// * The BREAKS are contiguous, non-overlapping periods of time. The 1865// response specifies the start time and duration of each break. 1866// * TRAVEL and WAIT are "preemptable": they can be interrupted several times 1867// during this transition. Clients can assume that travel happens "as soon as 1868// possible" and that "wait" fills the remaining time. 1869// 1870// A (complex) example: 1871// ``` 1872// TRANSITION[i] 1873// --++-----+-----------------------------------------------------------++--> 1874// || | | | | | | || 1875// || T | B | T | | B | | D || 1876// || r | r | r | W | r | W | e || 1877// || a | e | a | a | e | a | l || 1878// || v | a | v | i | a | i | a || 1879// || e | k | e | t | k | t | y || 1880// || l | | l | | | | || 1881// || | | | | | | || 1882// --++-----------------------------------------------------------------++--> 1883// ``` 1884message ShipmentRoute { 1885 // Deprecated: Use 1886 // [ShipmentRoute.Transition.delay_duration][google.cloud.optimization.v1.ShipmentRoute.Transition.delay_duration] 1887 // instead. Time interval spent on the route resulting from a 1888 // [TransitionAttributes.delay][google.cloud.optimization.v1.TransitionAttributes.delay]. 1889 message Delay { 1890 option deprecated = true; 1891 1892 // Start of the delay. 1893 google.protobuf.Timestamp start_time = 1; 1894 1895 // Duration of the delay. 1896 google.protobuf.Duration duration = 2; 1897 } 1898 1899 // A visit performed during a route. This visit corresponds to a pickup or a 1900 // delivery of a `Shipment`. 1901 message Visit { 1902 // Index of the `shipments` field in the source 1903 // [ShipmentModel][google.cloud.optimization.v1.ShipmentModel]. 1904 int32 shipment_index = 1; 1905 1906 // If true the visit corresponds to a pickup of a `Shipment`. Otherwise, it 1907 // corresponds to a delivery. 1908 bool is_pickup = 2; 1909 1910 // Index of `VisitRequest` in either the pickup or delivery field of the 1911 // `Shipment` (see `is_pickup`). 1912 int32 visit_request_index = 3; 1913 1914 // Time at which the visit starts. Note that the vehicle may arrive earlier 1915 // than this at the visit location. Times are consistent with the 1916 // `ShipmentModel`. 1917 google.protobuf.Timestamp start_time = 4; 1918 1919 // Total visit load demand as the sum of the shipment and the visit request 1920 // `load_demands`. The values are negative if the visit is a delivery. 1921 // Demands are reported for the same types as the 1922 // [Transition.loads][google.cloud.optimization.v1.ShipmentRoute.Transition] 1923 // (see this field). 1924 map<string, Shipment.Load> load_demands = 11; 1925 1926 // Extra detour time due to the shipments visited on the route before the 1927 // visit and to the potential waiting time induced by time windows. 1928 // If the visit is a delivery, the detour is computed from the corresponding 1929 // pickup visit and is equal to: 1930 // ``` 1931 // start_time(delivery) - start_time(pickup) 1932 // - (duration(pickup) + travel duration from the pickup location 1933 // to the delivery location). 1934 // ``` 1935 // Otherwise, it is computed from the vehicle `start_location` and is equal 1936 // to: 1937 // ``` 1938 // start_time - vehicle_start_time - travel duration from 1939 // the vehicle's `start_location` to the visit. 1940 // ``` 1941 google.protobuf.Duration detour = 6; 1942 1943 // Copy of the corresponding `Shipment.label`, if specified in the 1944 // `Shipment`. 1945 string shipment_label = 7; 1946 1947 // Copy of the corresponding 1948 // [VisitRequest.label][google.cloud.optimization.v1.Shipment.VisitRequest.label], 1949 // if specified in the `VisitRequest`. 1950 string visit_label = 8; 1951 1952 // Deprecated: Use 1953 // [Transition.vehicle_loads][google.cloud.optimization.v1.ShipmentRoute.Transition.vehicle_loads] 1954 // instead. Vehicle loads upon arrival at the visit location, for each type 1955 // specified in 1956 // [Vehicle.capacities][google.cloud.optimization.v1.Vehicle.capacities], 1957 // `start_load_intervals`, `end_load_intervals` or `demands`. 1958 // 1959 // Exception: we omit loads for quantity types unconstrained by intervals 1960 // and that don't have any non-zero demand on the route. 1961 repeated CapacityQuantity arrival_loads = 9 [deprecated = true]; 1962 1963 // Deprecated: Use 1964 // [ShipmentRoute.Transition.delay_duration][google.cloud.optimization.v1.ShipmentRoute.Transition.delay_duration] 1965 // instead. Delay occurring before the visit starts. 1966 Delay delay_before_start = 10 [deprecated = true]; 1967 1968 // Deprecated: Use 1969 // [Visit.load_demands][google.cloud.optimization.v1.ShipmentRoute.Visit.load_demands] 1970 // instead. 1971 repeated CapacityQuantity demands = 5 [deprecated = true]; 1972 } 1973 1974 // Transition between two events on the route. See the description of 1975 // [ShipmentRoute][google.cloud.optimization.v1.ShipmentRoute]. 1976 // 1977 // If the vehicle does not have a `start_location` and/or `end_location`, the 1978 // corresponding travel metrics are 0. 1979 message Transition { 1980 // Travel duration during this transition. 1981 google.protobuf.Duration travel_duration = 1; 1982 1983 // Distance traveled during the transition. 1984 double travel_distance_meters = 2; 1985 1986 // When traffic is requested via 1987 // [OptimizeToursRequest.consider_road_traffic] 1988 // [google.cloud.optimization.v1.OptimizeToursRequest.consider_road_traffic], 1989 // and the traffic info couldn't be retrieved for a `Transition`, this 1990 // boolean is set to true. This may be temporary (rare hiccup in the 1991 // realtime traffic servers) or permanent (no data for this location). 1992 bool traffic_info_unavailable = 3; 1993 1994 // Sum of the delay durations applied to this transition. If any, the delay 1995 // starts exactly `delay_duration` seconds before the next event (visit or 1996 // vehicle end). See 1997 // [TransitionAttributes.delay][google.cloud.optimization.v1.TransitionAttributes.delay]. 1998 google.protobuf.Duration delay_duration = 4; 1999 2000 // Sum of the duration of the breaks occurring during this transition, if 2001 // any. Details about each break's start time and duration are stored in 2002 // [ShipmentRoute.breaks][google.cloud.optimization.v1.ShipmentRoute.breaks]. 2003 google.protobuf.Duration break_duration = 5; 2004 2005 // Time spent waiting during this transition. Wait duration corresponds to 2006 // idle time and does not include break time. Also note that this wait time 2007 // may be split into several non-contiguous intervals. 2008 google.protobuf.Duration wait_duration = 6; 2009 2010 // Total duration of the transition, provided for convenience. It is equal 2011 // to: 2012 // 2013 // * next visit `start_time` (or `vehicle_end_time` if this is the last 2014 // transition) - this transition's `start_time`; 2015 // * if `ShipmentRoute.has_traffic_infeasibilities` is false, the following 2016 // additionally holds: `total_duration = travel_duration + delay_duration 2017 // + break_duration + wait_duration`. 2018 google.protobuf.Duration total_duration = 7; 2019 2020 // Start time of this transition. 2021 google.protobuf.Timestamp start_time = 8; 2022 2023 // The encoded polyline representation of the route followed during the 2024 // transition. 2025 // This field is only populated if [populate_transition_polylines] 2026 // [google.cloud.optimization.v1.OptimizeToursRequest.populate_transition_polylines] 2027 // is set to true. 2028 EncodedPolyline route_polyline = 9; 2029 2030 // Vehicle loads during this transition, for each type that either appears 2031 // in this vehicle's 2032 // [Vehicle.load_limits][google.cloud.optimization.v1.Vehicle.load_limits], 2033 // or that have non-zero 2034 // [Shipment.load_demands][google.cloud.optimization.v1.Shipment.load_demands] 2035 // on some shipment performed on this route. 2036 // 2037 // The loads during the first transition are the starting loads of the 2038 // vehicle route. Then, after each visit, the visit's `load_demands` are 2039 // either added or subtracted to get the next transition's loads, depending 2040 // on whether the visit was a pickup or a delivery. 2041 map<string, VehicleLoad> vehicle_loads = 11; 2042 2043 // Deprecated: Use 2044 // [Transition.vehicle_loads][google.cloud.optimization.v1.ShipmentRoute.Transition.vehicle_loads] 2045 // instead. 2046 repeated CapacityQuantity loads = 10 [deprecated = true]; 2047 } 2048 2049 // Reports the actual load of the vehicle at some point along the route, 2050 // for a given type (see 2051 // [Transition.vehicle_loads][google.cloud.optimization.v1.ShipmentRoute.Transition.vehicle_loads]). 2052 message VehicleLoad { 2053 // The amount of load on the vehicle, for the given type. The unit of load 2054 // is usually indicated by the type. See 2055 // [Transition.vehicle_loads][google.cloud.optimization.v1.ShipmentRoute.Transition.vehicle_loads]. 2056 int64 amount = 1; 2057 } 2058 2059 // The encoded representation of a polyline. More information on polyline 2060 // encoding can be found here: 2061 // https://developers.google.com/maps/documentation/utilities/polylinealgorithm 2062 // https://developers.google.com/maps/documentation/javascript/reference/geometry#encoding. 2063 message EncodedPolyline { 2064 // String representing encoded points of the polyline. 2065 string points = 1; 2066 } 2067 2068 // Data representing the execution of a break. 2069 message Break { 2070 // Start time of a break. 2071 google.protobuf.Timestamp start_time = 1; 2072 2073 // Duration of a break. 2074 google.protobuf.Duration duration = 2; 2075 } 2076 2077 // Deprecated: Use 2078 // [ShipmentRoute.Transition][google.cloud.optimization.v1.ShipmentRoute.Transition] 2079 // instead. Travel between each visit along the route: from the vehicle's 2080 // `start_location` to the first visit's `arrival_location`, then from the 2081 // first visit's `departure_location` to the second visit's 2082 // `arrival_location`, and so on until the vehicle's `end_location`. This 2083 // accounts only for the actual travel between visits, not counting the 2084 // waiting time, the time spent performing a visit, nor the distance covered 2085 // during a visit. 2086 // 2087 // Invariant: `travel_steps_size() == visits_size() + 1`. 2088 // 2089 // If the vehicle does not have a start_ and/or end_location, the 2090 // corresponding travel metrics are 0 and/or empty. 2091 message TravelStep { 2092 option deprecated = true; 2093 2094 // Duration of the travel step. 2095 google.protobuf.Duration duration = 1; 2096 2097 // Distance traveled during the step. 2098 double distance_meters = 2; 2099 2100 // When traffic is requested via 2101 // [OptimizeToursRequest.consider_road_traffic][google.cloud.optimization.v1.OptimizeToursRequest.consider_road_traffic], 2102 // and the traffic info couldn't be retrieved for a TravelStep, this boolean 2103 // is set to true. This may be temporary (rare hiccup in the realtime 2104 // traffic servers) or permanent (no data for this location). 2105 bool traffic_info_unavailable = 3; 2106 2107 // The encoded polyline representation of the route followed during the 2108 // step. 2109 // 2110 // This field is only populated if 2111 // [OptimizeToursRequest.populate_travel_step_polylines][google.cloud.optimization.v1.OptimizeToursRequest.populate_travel_step_polylines] 2112 // is set to true. 2113 EncodedPolyline route_polyline = 4; 2114 } 2115 2116 // Vehicle performing the route, identified by its index in the source 2117 // `ShipmentModel`. 2118 int32 vehicle_index = 1; 2119 2120 // Label of the vehicle performing this route, equal to 2121 // `ShipmentModel.vehicles(vehicle_index).label`, if specified. 2122 string vehicle_label = 2; 2123 2124 // Time at which the vehicle starts its route. 2125 google.protobuf.Timestamp vehicle_start_time = 5; 2126 2127 // Time at which the vehicle finishes its route. 2128 google.protobuf.Timestamp vehicle_end_time = 6; 2129 2130 // Ordered sequence of visits representing a route. 2131 // visits[i] is the i-th visit in the route. 2132 // If this field is empty, the vehicle is considered as unused. 2133 repeated Visit visits = 7; 2134 2135 // Ordered list of transitions for the route. 2136 repeated Transition transitions = 8; 2137 2138 // When 2139 // [OptimizeToursRequest.consider_road_traffic][google.cloud.optimization.v1.OptimizeToursRequest.consider_road_traffic], 2140 // is set to true, this field indicates that inconsistencies in route timings 2141 // are predicted using traffic-based travel duration estimates. There may be 2142 // insufficient time to complete traffic-adjusted travel, delays, and breaks 2143 // between visits, before the first visit, or after the last visit, while 2144 // still satisfying the visit and vehicle time windows. For example, 2145 // 2146 // ``` 2147 // start_time(previous_visit) + duration(previous_visit) + 2148 // travel_duration(previous_visit, next_visit) > start_time(next_visit) 2149 // ``` 2150 // 2151 // Arrival at next_visit will likely happen later than its current 2152 // time window due the increased estimate of travel time 2153 // `travel_duration(previous_visit, next_visit)` due to traffic. Also, a break 2154 // may be forced to overlap with a visit due to an increase in travel time 2155 // estimates and visit or break time window restrictions. 2156 bool has_traffic_infeasibilities = 9; 2157 2158 // The encoded polyline representation of the route. 2159 // This field is only populated if 2160 // [OptimizeToursRequest.populate_polylines][google.cloud.optimization.v1.OptimizeToursRequest.populate_polylines] 2161 // is set to true. 2162 EncodedPolyline route_polyline = 10; 2163 2164 // Breaks scheduled for the vehicle performing this route. 2165 // The `breaks` sequence represents time intervals, each starting at the 2166 // corresponding `start_time` and lasting `duration` seconds. 2167 repeated Break breaks = 11; 2168 2169 // Duration, distance and load metrics for this route. The fields of 2170 // [AggregatedMetrics][google.cloud.optimization.v1.AggregatedMetrics] are 2171 // summed over all 2172 // [ShipmentRoute.transitions][google.cloud.optimization.v1.ShipmentRoute.transitions] 2173 // or 2174 // [ShipmentRoute.visits][google.cloud.optimization.v1.ShipmentRoute.visits], 2175 // depending on the context. 2176 AggregatedMetrics metrics = 12; 2177 2178 // Cost of the route, broken down by cost-related request fields. 2179 // The keys are proto paths, relative to the input OptimizeToursRequest, e.g. 2180 // "model.shipments.pickups.cost", and the values are the total cost 2181 // generated by the corresponding cost field, aggregated over the whole route. 2182 // In other words, costs["model.shipments.pickups.cost"] is the sum of all 2183 // pickup costs over the route. All costs defined in the model are reported in 2184 // detail here with the exception of costs related to TransitionAttributes 2185 // that are only reported in an aggregated way as of 2022/01. 2186 map<string, double> route_costs = 17; 2187 2188 // Total cost of the route. The sum of all costs in the cost map. 2189 double route_total_cost = 18; 2190 2191 // Deprecated: Use 2192 // [Transition.vehicle_loads][google.cloud.optimization.v1.ShipmentRoute.Transition.vehicle_loads] 2193 // instead. Vehicle loads upon arrival at its end location, for each type 2194 // specified in 2195 // [Vehicle.capacities][google.cloud.optimization.v1.Vehicle.capacities], 2196 // `start_load_intervals`, `end_load_intervals` or demands. Exception: we omit 2197 // loads for quantity types unconstrained by intervals and that don't have any 2198 // non-zero demand on the route. 2199 repeated CapacityQuantity end_loads = 13 [deprecated = true]; 2200 2201 // Deprecated: Use 2202 // [ShipmentRoute.transitions][google.cloud.optimization.v1.ShipmentRoute.transitions] 2203 // instead. Ordered list of travel steps for the route. 2204 repeated TravelStep travel_steps = 14 [deprecated = true]; 2205 2206 // Deprecated: No longer used. 2207 // This field will only be populated at the 2208 // [ShipmentRoute.Visit][google.cloud.optimization.v1.ShipmentRoute.Visit] 2209 // level. 2210 // 2211 // This field is the extra detour time due to the shipments visited on the 2212 // route. 2213 // 2214 // It is equal to `vehicle_end_time` - `vehicle_start_time` - travel duration 2215 // from the vehicle's start_location to its `end_location`. 2216 google.protobuf.Duration vehicle_detour = 15 [deprecated = true]; 2217 2218 // Deprecated: Delay occurring before the vehicle end. See 2219 // [TransitionAttributes.delay][google.cloud.optimization.v1.TransitionAttributes.delay]. 2220 Delay delay_before_vehicle_end = 16 [deprecated = true]; 2221} 2222 2223// Specifies details of unperformed shipments in a solution. For trivial cases 2224// and/or if we are able to identify the cause for skipping, we report the 2225// reason here. 2226message SkippedShipment { 2227 // If we can explain why the shipment was skipped, reasons will be listed 2228 // here. If the reason is not the same for all vehicles, `reason` will have 2229 // more than 1 element. A skipped shipment cannot have duplicate reasons, 2230 // i.e. where all fields are the same except for `example_vehicle_index`. 2231 // Example: 2232 // ``` 2233 // reasons { 2234 // code: DEMAND_EXCEEDS_VEHICLE_CAPACITY 2235 // example_vehicle_index: 1 2236 // example_exceeded_capacity_type: "Apples" 2237 // } 2238 // reasons { 2239 // code: DEMAND_EXCEEDS_VEHICLE_CAPACITY 2240 // example_vehicle_index: 3 2241 // example_exceeded_capacity_type: "Pears" 2242 // } 2243 // reasons { 2244 // code: CANNOT_BE_PERFORMED_WITHIN_VEHICLE_DISTANCE_LIMIT 2245 // example_vehicle_index: 1 2246 // } 2247 // ``` 2248 // The skipped shipment is incompatible with all vehicles. The reasons may 2249 // be different for all vehicles but at least one vehicle's "Apples" 2250 // capacity would be exceeded (including vehicle 1), at least one vehicle's 2251 // "Pears" capacity would be exceeded (including vehicle 3) and at least one 2252 // vehicle's distance limit would be exceeded (including vehicle 1). 2253 message Reason { 2254 // Code identifying the reason type. The order here is meaningless. In 2255 // particular, it gives no indication of whether a given reason will 2256 // appear before another in the solution, if both apply. 2257 enum Code { 2258 // This should never be used. If we are unable to understand why a 2259 // shipment was skipped, we simply return an empty set of reasons. 2260 CODE_UNSPECIFIED = 0; 2261 2262 // There is no vehicle in the model making all shipments infeasible. 2263 NO_VEHICLE = 1; 2264 2265 // The demand of the shipment exceeds a vehicle's capacity for some 2266 // capacity types, one of which is `example_exceeded_capacity_type`. 2267 DEMAND_EXCEEDS_VEHICLE_CAPACITY = 2; 2268 2269 // The minimum distance necessary to perform this shipment, i.e. from 2270 // the vehicle's `start_location` to the shipment's pickup and/or delivery 2271 // locations and to the vehicle's end location exceeds the vehicle's 2272 // `route_distance_limit`. 2273 // 2274 // Note that for this computation we use the geodesic distances. 2275 CANNOT_BE_PERFORMED_WITHIN_VEHICLE_DISTANCE_LIMIT = 3; 2276 2277 // The minimum time necessary to perform this shipment, including travel 2278 // time, wait time and service time exceeds the vehicle's 2279 // `route_duration_limit`. 2280 // 2281 // Note: travel time is computed in the best-case scenario, namely as 2282 // geodesic distance x 36 m/s (roughly 130 km/hour). 2283 CANNOT_BE_PERFORMED_WITHIN_VEHICLE_DURATION_LIMIT = 4; 2284 2285 // Same as above but we only compare minimum travel time and the 2286 // vehicle's `travel_duration_limit`. 2287 CANNOT_BE_PERFORMED_WITHIN_VEHICLE_TRAVEL_DURATION_LIMIT = 5; 2288 2289 // The vehicle cannot perform this shipment in the best-case scenario 2290 // (see `CANNOT_BE_PERFORMED_WITHIN_VEHICLE_DURATION_LIMIT` for time 2291 // computation) if it starts at its earliest start time: the total time 2292 // would make the vehicle end after its latest end time. 2293 CANNOT_BE_PERFORMED_WITHIN_VEHICLE_TIME_WINDOWS = 6; 2294 2295 // The `allowed_vehicle_indices` field of the shipment is not empty and 2296 // this vehicle does not belong to it. 2297 VEHICLE_NOT_ALLOWED = 7; 2298 } 2299 2300 // Refer to the comments of Code. 2301 Code code = 1; 2302 2303 // If the reason is related to a shipment-vehicle incompatibility, this 2304 // field provides the index of one relevant vehicle. 2305 optional int32 example_vehicle_index = 2; 2306 2307 // If the reason code is `DEMAND_EXCEEDS_VEHICLE_CAPACITY`, documents one 2308 // capacity type that is exceeded. 2309 string example_exceeded_capacity_type = 3; 2310 } 2311 2312 // The index corresponds to the index of the shipment in the source 2313 // `ShipmentModel`. 2314 int32 index = 1; 2315 2316 // Copy of the corresponding 2317 // [Shipment.label][google.cloud.optimization.v1.Shipment.label], if specified 2318 // in the `Shipment`. 2319 string label = 2; 2320 2321 // A list of reasons that explain why the shipment was skipped. See comment 2322 // above `Reason`. 2323 repeated Reason reasons = 3; 2324} 2325 2326// Aggregated metrics for 2327// [ShipmentRoute][google.cloud.optimization.v1.ShipmentRoute] (resp. for 2328// [OptimizeToursResponse][google.cloud.optimization.v1.OptimizeToursResponse] 2329// over all [Transition][google.cloud.optimization.v1.ShipmentRoute.Transition] 2330// and/or [Visit][google.cloud.optimization.v1.ShipmentRoute.Visit] (resp. over 2331// all [ShipmentRoute][google.cloud.optimization.v1.ShipmentRoute]) elements. 2332message AggregatedMetrics { 2333 // Number of shipments performed. Note that a pickup and delivery pair only 2334 // counts once. 2335 int32 performed_shipment_count = 1; 2336 2337 // Total travel duration for a route or a solution. 2338 google.protobuf.Duration travel_duration = 2; 2339 2340 // Total wait duration for a route or a solution. 2341 google.protobuf.Duration wait_duration = 3; 2342 2343 // Total delay duration for a route or a solution. 2344 google.protobuf.Duration delay_duration = 4; 2345 2346 // Total break duration for a route or a solution. 2347 google.protobuf.Duration break_duration = 5; 2348 2349 // Total visit duration for a route or a solution. 2350 google.protobuf.Duration visit_duration = 6; 2351 2352 // The total duration should be equal to the sum of all durations above. 2353 // For routes, it also corresponds to: 2354 // [ShipmentRoute.vehicle_end_time][google.cloud.optimization.v1.ShipmentRoute.vehicle_end_time] 2355 // `-` 2356 // [ShipmentRoute.vehicle_start_time][google.cloud.optimization.v1.ShipmentRoute.vehicle_start_time] 2357 google.protobuf.Duration total_duration = 7; 2358 2359 // Total travel distance for a route or a solution. 2360 double travel_distance_meters = 8; 2361 2362 // Maximum load achieved over the entire route (resp. solution), for each of 2363 // the quantities on this route (resp. solution), computed as the maximum over 2364 // all 2365 // [Transition.vehicle_loads][google.cloud.optimization.v1.ShipmentRoute.Transition.vehicle_loads] 2366 // (resp. 2367 // [ShipmentRoute.metrics.max_loads][google.cloud.optimization.v1.AggregatedMetrics.max_loads]. 2368 map<string, ShipmentRoute.VehicleLoad> max_loads = 9; 2369 2370 // Deprecated: Use 2371 // [ShipmentRoute.route_costs][google.cloud.optimization.v1.ShipmentRoute.route_costs] 2372 // and 2373 // [OptimizeToursResponse.Metrics.costs][google.cloud.optimization.v1.OptimizeToursResponse.Metrics.costs] 2374 // instead. 2375 map<string, double> costs = 10 [deprecated = true]; 2376 2377 // Deprecated: Use 2378 // [ShipmentRoute.route_total_cost][google.cloud.optimization.v1.ShipmentRoute.route_total_cost] 2379 // and 2380 // [OptimizeToursResponse.Metrics.total_cost][google.cloud.optimization.v1.OptimizeToursResponse.Metrics.total_cost] 2381 // instead. 2382 double total_cost = 11 [deprecated = true]; 2383} 2384 2385// Solution injected in the request including information about which visits 2386// must be constrained and how they must be constrained. 2387message InjectedSolutionConstraint { 2388 // For a group of vehicles, specifies at what threshold(s) constraints on 2389 // visits will be relaxed and to which level. Shipments listed in 2390 // the `skipped_shipment` field are constrained to be skipped; i.e., they 2391 // cannot be performed. 2392 message ConstraintRelaxation { 2393 // If `relaxations` is empty, the start time and sequence of all visits 2394 // on `routes` are fully constrained and no new visits may be inserted or 2395 // added to those routes. Also, a vehicle's start and end time in 2396 // `routes` is fully constrained, unless the vehicle is empty (i.e., has no 2397 // visits and has `used_if_route_is_empty` set to false in the model). 2398 // 2399 // `relaxations(i).level` specifies the constraint relaxation level applied 2400 // to a visit #j that satisfies: 2401 // 2402 // * `route.visits(j).start_time >= relaxations(i).threshold_time` AND 2403 // * `j + 1 >= relaxations(i).threshold_visit_count` 2404 // 2405 // Similarly, the vehicle start is relaxed to `relaxations(i).level` if it 2406 // satisfies: 2407 // 2408 // * `vehicle_start_time >= relaxations(i).threshold_time` AND 2409 // * `relaxations(i).threshold_visit_count == 0` 2410 // and the vehicle end is relaxed to `relaxations(i).level` if it satisfies: 2411 // * `vehicle_end_time >= relaxations(i).threshold_time` AND 2412 // * `route.visits_size() + 1 >= relaxations(i).threshold_visit_count` 2413 // 2414 // To apply a relaxation level if a visit meets the `threshold_visit_count` 2415 // OR the `threshold_time` add two `relaxations` with the same `level`: 2416 // one with only `threshold_visit_count` set and the other with only 2417 // `threshold_time` set. If a visit satisfies the conditions of multiple 2418 // `relaxations`, the most relaxed level applies. As a result, from the 2419 // vehicle start through the route visits in order to the vehicle end, the 2420 // relaxation level becomes more relaxed: i.e., the relaxation level is 2421 // non-decreasing as the route progresses. 2422 // 2423 // The timing and sequence of route visits that do not satisfy the 2424 // threshold conditions of any `relaxations` are fully constrained 2425 // and no visits may be inserted into these sequences. Also, if a 2426 // vehicle start or end does not satisfy the conditions of any 2427 // relaxation the time is fixed, unless the vehicle is empty. 2428 message Relaxation { 2429 // Expresses the different constraint relaxation levels, which are 2430 // applied for a visit and those that follow when it satisfies the 2431 // threshold conditions. 2432 // 2433 // The enumeration below is in order of increasing relaxation. 2434 enum Level { 2435 // Implicit default relaxation level: no constraints are relaxed, 2436 // i.e., all visits are fully constrained. 2437 // 2438 // This value must not be explicitly used in `level`. 2439 LEVEL_UNSPECIFIED = 0; 2440 2441 // Visit start times and vehicle start/end times will be relaxed, but 2442 // each visit remains bound to the same vehicle and the visit sequence 2443 // must be observed: no visit can be inserted between them or before 2444 // them. 2445 RELAX_VISIT_TIMES_AFTER_THRESHOLD = 1; 2446 2447 // Same as `RELAX_VISIT_TIMES_AFTER_THRESHOLD`, but the visit sequence 2448 // is also relaxed: visits can only be performed by this vehicle, but 2449 // can potentially become unperformed. 2450 RELAX_VISIT_TIMES_AND_SEQUENCE_AFTER_THRESHOLD = 2; 2451 2452 // Same as `RELAX_VISIT_TIMES_AND_SEQUENCE_AFTER_THRESHOLD`, but the 2453 // vehicle is also relaxed: visits are completely free at or after the 2454 // threshold time and can potentially become unperformed. 2455 RELAX_ALL_AFTER_THRESHOLD = 3; 2456 } 2457 2458 // The constraint relaxation level that applies when the conditions 2459 // at or after `threshold_time` AND at least `threshold_visit_count` are 2460 // satisfied. 2461 Level level = 1; 2462 2463 // The time at or after which the relaxation `level` may be applied. 2464 google.protobuf.Timestamp threshold_time = 2; 2465 2466 // The number of visits at or after which the relaxation `level` may be 2467 // applied. If `threshold_visit_count` is 0 (or unset), the `level` may be 2468 // applied directly at the vehicle start. 2469 // 2470 // If it is `route.visits_size() + 1`, the `level` may only be applied to 2471 // the vehicle end. If it is more than `route.visits_size() + 1`, 2472 // `level` is not applied at all for that route. 2473 int32 threshold_visit_count = 3; 2474 } 2475 2476 // All the visit constraint relaxations that will apply to visits on 2477 // routes with vehicles in `vehicle_indices`. 2478 repeated Relaxation relaxations = 1; 2479 2480 // Specifies the vehicle indices to which the visit constraint 2481 // `relaxations` apply. If empty, this is considered the default and the 2482 // `relaxations` apply to all vehicles that are not specified in other 2483 // `constraint_relaxations`. There can be at most one default, i.e., at 2484 // most one constraint relaxation field is allowed empty 2485 // `vehicle_indices`. A vehicle index can only be listed once, even within 2486 // several `constraint_relaxations`. 2487 // 2488 // A vehicle index is mapped the same as 2489 // [ShipmentRoute.vehicle_index][google.cloud.optimization.v1.ShipmentRoute.vehicle_index], 2490 // if `interpret_injected_solutions_using_labels` is true (see `fields` 2491 // comment). 2492 repeated int32 vehicle_indices = 2; 2493 } 2494 2495 // Routes of the solution to inject. Some routes may be omitted from the 2496 // original solution. The routes and skipped shipments must satisfy the basic 2497 // validity assumptions listed for `injected_first_solution_routes`. 2498 repeated ShipmentRoute routes = 1; 2499 2500 // Skipped shipments of the solution to inject. Some may be omitted from the 2501 // original solution. See the `routes` field. 2502 repeated SkippedShipment skipped_shipments = 2; 2503 2504 // For zero or more groups of vehicles, specifies when and how much to relax 2505 // constraints. If this field is empty, all non-empty vehicle routes are 2506 // fully constrained. 2507 repeated ConstraintRelaxation constraint_relaxations = 3; 2508} 2509 2510// Describes an error encountered when validating an `OptimizeToursRequest`. 2511message OptimizeToursValidationError { 2512 // Specifies a context for the validation error. A `FieldReference` always 2513 // refers to a given field in this file and follows the same hierarchical 2514 // structure. For example, we may specify element #2 of `start_time_windows` 2515 // of vehicle #5 using: 2516 // ``` 2517 // name: "vehicles" index: 5 sub_field { name: "end_time_windows" index: 2 } 2518 // ``` 2519 // We however omit top-level entities such as `OptimizeToursRequest` or 2520 // `ShipmentModel` to avoid crowding the message. 2521 message FieldReference { 2522 // Name of the field, e.g., "vehicles". 2523 string name = 1; 2524 2525 oneof index_or_key { 2526 // Index of the field if repeated. 2527 int32 index = 2; 2528 2529 // Key if the field is a map. 2530 string key = 4; 2531 } 2532 2533 // Recursively nested sub-field, if needed. 2534 FieldReference sub_field = 3; 2535 } 2536 2537 // A validation error is defined by the pair (`code`, `display_name`) which 2538 // are always present. 2539 // 2540 // Other fields (below) provide more context about the error. 2541 // 2542 // *MULTIPLE ERRORS*: 2543 // When there are multiple errors, the validation process tries to output 2544 // several of them. Much like a compiler, this is an imperfect process. Some 2545 // validation errors will be "fatal", meaning that they stop the entire 2546 // validation process. This is the case for `display_name="UNSPECIFIED"` 2547 // errors, among others. Some may cause the validation process to skip other 2548 // errors. 2549 // 2550 // *STABILITY*: 2551 // `code` and `display_name` should be very stable. But new codes and 2552 // display names may appear over time, which may cause a given (invalid) 2553 // request to yield a different (`code`, `display_name`) pair because the new 2554 // error hid the old one (see "MULTIPLE ERRORS"). 2555 // 2556 // *REFERENCE*: A list of all (code, name) pairs: 2557 // 2558 // * UNSPECIFIED = 0; 2559 // * VALIDATION_TIMEOUT_ERROR = 10; Validation couldn't be completed within 2560 // the deadline. 2561 // 2562 // * REQUEST_OPTIONS_ERROR = 12; 2563 // * REQUEST_OPTIONS_INVALID_SOLVING_MODE = 1201; 2564 // * REQUEST_OPTIONS_INVALID_MAX_VALIDATION_ERRORS = 1203; 2565 // * REQUEST_OPTIONS_INVALID_GEODESIC_METERS_PER_SECOND = 1204; 2566 // * REQUEST_OPTIONS_GEODESIC_METERS_PER_SECOND_TOO_SMALL = 1205; 2567 // * REQUEST_OPTIONS_MISSING_GEODESIC_METERS_PER_SECOND = 1206; 2568 // * REQUEST_OPTIONS_POPULATE_PATHFINDER_TRIPS_AND_GEODESIC_DISTANCE 2569 // = 1207; 2570 // * REQUEST_OPTIONS_COST_MODEL_OPTIONS_AND_GEODESIC_DISTANCE = 1208; 2571 // * REQUEST_OPTIONS_TRAVEL_MODE_INCOMPATIBLE_WITH_TRAFFIC = 1211; 2572 // * REQUEST_OPTIONS_MULTIPLE_TRAFFIC_FLAVORS = 1212; 2573 // * REQUEST_OPTIONS_INVALID_TRAFFIC_FLAVOR = 1213; 2574 // * REQUEST_OPTIONS_TRAFFIC_ENABLED_WITHOUT_GLOBAL_START_TIME = 1214; 2575 // * REQUEST_OPTIONS_TRAFFIC_ENABLED_WITH_PRECEDENCES = 1215; 2576 // * REQUEST_OPTIONS_TRAFFIC_PREFILL_MODE_INVALID = 1216; 2577 // * REQUEST_OPTIONS_TRAFFIC_PREFILL_ENABLED_WITHOUT_TRAFFIC = 1217; 2578 // * INJECTED_SOLUTION_ERROR = 20; 2579 // * INJECTED_SOLUTION_MISSING_LABEL = 2000; 2580 // * INJECTED_SOLUTION_DUPLICATE_LABEL = 2001; 2581 // * INJECTED_SOLUTION_AMBIGUOUS_INDEX = 2002; 2582 // * INJECTED_SOLUTION_INFEASIBLE_AFTER_GETTING_TRAVEL_TIMES = 2003; 2583 // * INJECTED_SOLUTION_TRANSITION_INCONSISTENT_WITH_ACTUAL_TRAVEL = 2004; 2584 // * INJECTED_SOLUTION_CONCURRENT_SOLUTION_TYPES = 2005; 2585 // * INJECTED_SOLUTION_MORE_THAN_ONE_PER_TYPE = 2006; 2586 // * INJECTED_SOLUTION_REFRESH_WITHOUT_POPULATE = 2008; 2587 // * INJECTED_SOLUTION_CONSTRAINED_ROUTE_PORTION_INFEASIBLE = 2010; 2588 // * SHIPMENT_MODEL_ERROR = 22; 2589 // * SHIPMENT_MODEL_TOO_LARGE = 2200; 2590 // * SHIPMENT_MODEL_TOO_MANY_CAPACITY_TYPES = 2201; 2591 // * SHIPMENT_MODEL_GLOBAL_START_TIME_NEGATIVE_OR_NAN = 2202; 2592 // * SHIPMENT_MODEL_GLOBAL_END_TIME_TOO_LARGE_OR_NAN = 2203; 2593 // * SHIPMENT_MODEL_GLOBAL_START_TIME_AFTER_GLOBAL_END_TIME = 2204; 2594 // * SHIPMENT_MODEL_GLOBAL_DURATION_TOO_LONG = 2205; 2595 // * SHIPMENT_MODEL_MAX_ACTIVE_VEHICLES_NOT_POSITIVE = 2206; 2596 // * SHIPMENT_MODEL_DURATION_MATRIX_TOO_LARGE = 2207; 2597 // * INDEX_ERROR = 24; 2598 // * TAG_ERROR = 26; 2599 // * TIME_WINDOW_ERROR = 28; 2600 // * TIME_WINDOW_INVALID_START_TIME = 2800; 2601 // * TIME_WINDOW_INVALID_END_TIME = 2801; 2602 // * TIME_WINDOW_INVALID_SOFT_START_TIME = 2802; 2603 // * TIME_WINDOW_INVALID_SOFT_END_TIME = 2803; 2604 // * TIME_WINDOW_OUTSIDE_GLOBAL_TIME_WINDOW = 2804; 2605 // * TIME_WINDOW_START_TIME_AFTER_END_TIME = 2805; 2606 // * TIME_WINDOW_INVALID_COST_PER_HOUR_BEFORE_SOFT_START_TIME = 2806; 2607 // * TIME_WINDOW_INVALID_COST_PER_HOUR_AFTER_SOFT_END_TIME = 2807; 2608 // * TIME_WINDOW_COST_BEFORE_SOFT_START_TIME_WITHOUT_SOFT_START_TIME 2609 // = 2808; 2610 // * TIME_WINDOW_COST_AFTER_SOFT_END_TIME_WITHOUT_SOFT_END_TIME = 2809; 2611 // * TIME_WINDOW_SOFT_START_TIME_WITHOUT_COST_BEFORE_SOFT_START_TIME 2612 // = 2810; 2613 // * TIME_WINDOW_SOFT_END_TIME_WITHOUT_COST_AFTER_SOFT_END_TIME = 2811; 2614 // * TIME_WINDOW_OVERLAPPING_ADJACENT_OR_EARLIER_THAN_PREVIOUS = 2812; 2615 // * TIME_WINDOW_START_TIME_AFTER_SOFT_START_TIME = 2813; 2616 // * TIME_WINDOW_SOFT_START_TIME_AFTER_END_TIME = 2814; 2617 // * TIME_WINDOW_START_TIME_AFTER_SOFT_END_TIME = 2815; 2618 // * TIME_WINDOW_SOFT_END_TIME_AFTER_END_TIME = 2816; 2619 // * TIME_WINDOW_COST_BEFORE_SOFT_START_TIME_SET_AND_MULTIPLE_WINDOWS 2620 // = 2817; 2621 // * TIME_WINDOW_COST_AFTER_SOFT_END_TIME_SET_AND_MULTIPLE_WINDOWS = 2818; 2622 // * TRANSITION_ATTRIBUTES_ERROR = 30; 2623 // * TRANSITION_ATTRIBUTES_INVALID_COST = 3000; 2624 // * TRANSITION_ATTRIBUTES_INVALID_COST_PER_KILOMETER = 3001; 2625 // * TRANSITION_ATTRIBUTES_DUPLICATE_TAG_PAIR = 3002; 2626 // * TRANSITION_ATTRIBUTES_DISTANCE_LIMIT_MAX_METERS_UNSUPPORTED = 3003; 2627 // * TRANSITION_ATTRIBUTES_UNSPECIFIED_SOURCE_TAGS = 3004; 2628 // * TRANSITION_ATTRIBUTES_CONFLICTING_SOURCE_TAGS_FIELDS = 3005; 2629 // * TRANSITION_ATTRIBUTES_UNSPECIFIED_DESTINATION_TAGS = 3006; 2630 // * TRANSITION_ATTRIBUTES_CONFLICTING_DESTINATION_TAGS_FIELDS = 3007; 2631 // * TRANSITION_ATTRIBUTES_DELAY_DURATION_NEGATIVE_OR_NAN = 3008; 2632 // * TRANSITION_ATTRIBUTES_DELAY_DURATION_EXCEEDS_GLOBAL_DURATION = 3009; 2633 // * AMOUNT_ERROR = 31; 2634 // * AMOUNT_NEGATIVE_VALUE = 3100; 2635 // * LOAD_LIMIT_ERROR = 33; 2636 // * LOAD_LIMIT_INVALID_COST_ABOVE_SOFT_MAX = 3303; 2637 // * LOAD_LIMIT_SOFT_MAX_WITHOUT_COST_ABOVE_SOFT_MAX = 3304; 2638 // * LOAD_LIMIT_COST_ABOVE_SOFT_MAX_WITHOUT_SOFT_MAX = 3305; 2639 // * LOAD_LIMIT_NEGATIVE_SOFT_MAX = 3306; 2640 // * LOAD_LIMIT_MIXED_DEMAND_TYPE = 3307; 2641 // * LOAD_LIMIT_MAX_LOAD_NEGATIVE_VALUE = 3308; 2642 // * LOAD_LIMIT_SOFT_MAX_ABOVE_MAX = 3309; 2643 // * INTERVAL_ERROR = 34; 2644 // * INTERVAL_MIN_EXCEEDS_MAX = 3401; 2645 // * INTERVAL_NEGATIVE_MIN = 3402; 2646 // * INTERVAL_NEGATIVE_MAX = 3403; 2647 // * INTERVAL_MIN_EXCEEDS_CAPACITY = 3404; 2648 // * INTERVAL_MAX_EXCEEDS_CAPACITY = 3405; 2649 // * DISTANCE_LIMIT_ERROR = 36; 2650 // * DISTANCE_LIMIT_INVALID_COST_AFTER_SOFT_MAX = 3601; 2651 // * DISTANCE_LIMIT_SOFT_MAX_WITHOUT_COST_AFTER_SOFT_MAX = 3602; 2652 // * DISTANCE_LIMIT_COST_AFTER_SOFT_MAX_WITHOUT_SOFT_MAX = 3603; 2653 // * DISTANCE_LIMIT_NEGATIVE_MAX = 3604; 2654 // * DISTANCE_LIMIT_NEGATIVE_SOFT_MAX = 3605; 2655 // * DISTANCE_LIMIT_SOFT_MAX_LARGER_THAN_MAX = 3606; 2656 // * DURATION_LIMIT_ERROR = 38; 2657 // * DURATION_LIMIT_MAX_DURATION_NEGATIVE_OR_NAN = 3800; 2658 // * DURATION_LIMIT_SOFT_MAX_DURATION_NEGATIVE_OR_NAN = 3801; 2659 // * DURATION_LIMIT_INVALID_COST_PER_HOUR_AFTER_SOFT_MAX = 3802; 2660 // * DURATION_LIMIT_SOFT_MAX_WITHOUT_COST_AFTER_SOFT_MAX = 3803; 2661 // * DURATION_LIMIT_COST_AFTER_SOFT_MAX_WITHOUT_SOFT_MAX = 3804; 2662 // * DURATION_LIMIT_QUADRATIC_SOFT_MAX_DURATION_NEGATIVE_OR_NAN = 3805; 2663 // * DURATION_LIMIT_INVALID_COST_AFTER_QUADRATIC_SOFT_MAX = 3806; 2664 // * DURATION_LIMIT_QUADRATIC_SOFT_MAX_WITHOUT_COST_PER_SQUARE_HOUR 2665 // = 3807; 2666 // * DURATION_LIMIT_COST_PER_SQUARE_HOUR_WITHOUT_QUADRATIC_SOFT_MAX 2667 // = 3808; 2668 // * DURATION_LIMIT_QUADRATIC_SOFT_MAX_WITHOUT_MAX = 3809; 2669 // * DURATION_LIMIT_SOFT_MAX_LARGER_THAN_MAX = 3810; 2670 // * DURATION_LIMIT_QUADRATIC_SOFT_MAX_LARGER_THAN_MAX = 3811; 2671 // * DURATION_LIMIT_DIFF_BETWEEN_MAX_AND_QUADRATIC_SOFT_MAX_TOO_LARGE 2672 // = 3812; 2673 // * DURATION_LIMIT_MAX_DURATION_EXCEEDS_GLOBAL_DURATION = 3813; 2674 // * DURATION_LIMIT_SOFT_MAX_DURATION_EXCEEDS_GLOBAL_DURATION = 3814; 2675 // * DURATION_LIMIT_QUADRATIC_SOFT_MAX_DURATION_EXCEEDS_GLOBAL_DURATION 2676 // = 3815; 2677 // * SHIPMENT_ERROR = 40; 2678 // * SHIPMENT_PD_LIMIT_WITHOUT_PICKUP_AND_DELIVERY = 4014; 2679 // * SHIPMENT_PD_ABSOLUTE_DETOUR_LIMIT_DURATION_NEGATIVE_OR_NAN = 4000; 2680 // * SHIPMENT_PD_ABSOLUTE_DETOUR_LIMIT_DURATION_EXCEEDS_GLOBAL_DURATION 2681 // = 4001; 2682 // * SHIPMENT_PD_RELATIVE_DETOUR_LIMIT_INVALID = 4015; 2683 // * SHIPMENT_PD_DETOUR_LIMIT_AND_EXTRA_VISIT_DURATION = 4016; 2684 // * SHIPMENT_PD_TIME_LIMIT_DURATION_NEGATIVE_OR_NAN = 4002; 2685 // * SHIPMENT_PD_TIME_LIMIT_DURATION_EXCEEDS_GLOBAL_DURATION = 4003; 2686 // * SHIPMENT_EMPTY_SHIPMENT_TYPE = 4004; 2687 // * SHIPMENT_NO_PICKUP_NO_DELIVERY = 4005; 2688 // * SHIPMENT_INVALID_PENALTY_COST = 4006; 2689 // * SHIPMENT_ALLOWED_VEHICLE_INDEX_OUT_OF_BOUNDS = 4007; 2690 // * SHIPMENT_DUPLICATE_ALLOWED_VEHICLE_INDEX = 4008; 2691 // * SHIPMENT_INCONSISTENT_COST_FOR_VEHICLE_SIZE_WITHOUT_INDEX = 4009; 2692 // * SHIPMENT_INCONSISTENT_COST_FOR_VEHICLE_SIZE_WITH_INDEX = 4010; 2693 // * SHIPMENT_INVALID_COST_FOR_VEHICLE = 4011; 2694 // * SHIPMENT_COST_FOR_VEHICLE_INDEX_OUT_OF_BOUNDS = 4012; 2695 // * SHIPMENT_DUPLICATE_COST_FOR_VEHICLE_INDEX = 4013; 2696 // * VEHICLE_ERROR = 42; 2697 // * VEHICLE_EMPTY_REQUIRED_OPERATOR_TYPE = 4200; 2698 // * VEHICLE_DUPLICATE_REQUIRED_OPERATOR_TYPE = 4201; 2699 // * VEHICLE_NO_OPERATOR_WITH_REQUIRED_OPERATOR_TYPE = 4202; 2700 // * VEHICLE_EMPTY_START_TAG = 4203; 2701 // * VEHICLE_DUPLICATE_START_TAG = 4204; 2702 // * VEHICLE_EMPTY_END_TAG = 4205; 2703 // * VEHICLE_DUPLICATE_END_TAG = 4206; 2704 // * VEHICLE_EXTRA_VISIT_DURATION_NEGATIVE_OR_NAN = 4207; 2705 // * VEHICLE_EXTRA_VISIT_DURATION_EXCEEDS_GLOBAL_DURATION = 4208; 2706 // * VEHICLE_EXTRA_VISIT_DURATION_EMPTY_KEY = 4209; 2707 // * VEHICLE_FIRST_SHIPMENT_INDEX_OUT_OF_BOUNDS = 4210; 2708 // * VEHICLE_FIRST_SHIPMENT_IGNORED = 4211; 2709 // * VEHICLE_FIRST_SHIPMENT_NOT_BOUND = 4212; 2710 // * VEHICLE_LAST_SHIPMENT_INDEX_OUT_OF_BOUNDS = 4213; 2711 // * VEHICLE_LAST_SHIPMENT_IGNORED = 4214; 2712 // * VEHICLE_LAST_SHIPMENT_NOT_BOUND = 4215; 2713 // * VEHICLE_IGNORED_WITH_USED_IF_ROUTE_IS_EMPTY = 4216; 2714 // * VEHICLE_INVALID_COST_PER_KILOMETER = 4217; 2715 // * VEHICLE_INVALID_COST_PER_HOUR = 4218; 2716 // * VEHICLE_INVALID_COST_PER_TRAVELED_HOUR = 4219; 2717 // * VEHICLE_INVALID_FIXED_COST = 4220; 2718 // * VEHICLE_INVALID_TRAVEL_DURATION_MULTIPLE = 4221; 2719 // * VEHICLE_TRAVEL_DURATION_MULTIPLE_WITH_SHIPMENT_PD_DETOUR_LIMITS 2720 // = 4223; 2721 // * VEHICLE_MATRIX_INDEX_WITH_SHIPMENT_PD_DETOUR_LIMITS = 4224; 2722 // * VEHICLE_MINIMUM_DURATION_LONGER_THAN_DURATION_LIMIT = 4222; 2723 // * VISIT_REQUEST_ERROR = 44; 2724 // * VISIT_REQUEST_EMPTY_TAG = 4400; 2725 // * VISIT_REQUEST_DUPLICATE_TAG = 4401; 2726 // * VISIT_REQUEST_DURATION_NEGATIVE_OR_NAN = 4404; 2727 // * VISIT_REQUEST_DURATION_EXCEEDS_GLOBAL_DURATION = 4405; 2728 // * PRECEDENCE_ERROR = 46; 2729 // * PRECEDENCE_RULE_MISSING_FIRST_INDEX = 4600; 2730 // * PRECEDENCE_RULE_MISSING_SECOND_INDEX = 4601; 2731 // * PRECEDENCE_RULE_FIRST_INDEX_OUT_OF_BOUNDS = 4602; 2732 // * PRECEDENCE_RULE_SECOND_INDEX_OUT_OF_BOUNDS = 4603; 2733 // * PRECEDENCE_RULE_DUPLICATE_INDEX = 4604; 2734 // * PRECEDENCE_RULE_INEXISTENT_FIRST_VISIT_REQUEST = 4605; 2735 // * PRECEDENCE_RULE_INEXISTENT_SECOND_VISIT_REQUEST = 4606; 2736 // * BREAK_ERROR = 48; 2737 // * BREAK_RULE_EMPTY = 4800; 2738 // * BREAK_REQUEST_UNSPECIFIED_DURATION = 4801; 2739 // * BREAK_REQUEST_UNSPECIFIED_EARLIEST_START_TIME = 4802; 2740 // * BREAK_REQUEST_UNSPECIFIED_LATEST_START_TIME = 4803; 2741 // * BREAK_REQUEST_DURATION_NEGATIVE_OR_NAN = 4804; = 4804; 2742 // * BREAK_REQUEST_LATEST_START_TIME_BEFORE_EARLIEST_START_TIME = 4805; 2743 // * BREAK_REQUEST_EARLIEST_START_TIME_BEFORE_GLOBAL_START_TIME = 4806; 2744 // * BREAK_REQUEST_LATEST_END_TIME_AFTER_GLOBAL_END_TIME = 4807; 2745 // * BREAK_REQUEST_NON_SCHEDULABLE = 4808; 2746 // * BREAK_FREQUENCY_MAX_INTER_BREAK_DURATION_NEGATIVE_OR_NAN = 4809; 2747 // * BREAK_FREQUENCY_MIN_BREAK_DURATION_NEGATIVE_OR_NAN = 4810; 2748 // * BREAK_FREQUENCY_MIN_BREAK_DURATION_EXCEEDS_GLOBAL_DURATION = 4811; 2749 // * BREAK_FREQUENCY_MAX_INTER_BREAK_DURATION_EXCEEDS_GLOBAL_DURATION 2750 // = 4812; 2751 // * BREAK_REQUEST_DURATION_EXCEEDS_GLOBAL_DURATION = 4813; 2752 // * BREAK_FREQUENCY_MISSING_MAX_INTER_BREAK_DURATION = 4814; 2753 // * BREAK_FREQUENCY_MISSING_MIN_BREAK_DURATION = 4815; 2754 // * SHIPMENT_TYPE_INCOMPATIBILITY_ERROR = 50; 2755 // * SHIPMENT_TYPE_INCOMPATIBILITY_EMPTY_TYPE = 5001; 2756 // * SHIPMENT_TYPE_INCOMPATIBILITY_LESS_THAN_TWO_TYPES = 5002; 2757 // * SHIPMENT_TYPE_INCOMPATIBILITY_DUPLICATE_TYPE = 5003; 2758 // * SHIPMENT_TYPE_INCOMPATIBILITY_INVALID_INCOMPATIBILITY_MODE = 5004; 2759 // * SHIPMENT_TYPE_INCOMPATIBILITY_TOO_MANY_INCOMPATIBILITIES = 5005; 2760 // * SHIPMENT_TYPE_REQUIREMENT_ERROR = 52; 2761 // * SHIPMENT_TYPE_REQUIREMENT_NO_REQUIRED_TYPE = 52001; 2762 // * SHIPMENT_TYPE_REQUIREMENT_NO_DEPENDENT_TYPE = 52002; 2763 // * SHIPMENT_TYPE_REQUIREMENT_INVALID_REQUIREMENT_MODE = 52003; 2764 // * SHIPMENT_TYPE_REQUIREMENT_TOO_MANY_REQUIREMENTS = 52004; 2765 // * SHIPMENT_TYPE_REQUIREMENT_EMPTY_REQUIRED_TYPE = 52005; 2766 // * SHIPMENT_TYPE_REQUIREMENT_DUPLICATE_REQUIRED_TYPE = 52006; 2767 // * SHIPMENT_TYPE_REQUIREMENT_NO_REQUIRED_TYPE_FOUND = 52007; 2768 // * SHIPMENT_TYPE_REQUIREMENT_EMPTY_DEPENDENT_TYPE = 52008; 2769 // * SHIPMENT_TYPE_REQUIREMENT_DUPLICATE_DEPENDENT_TYPE = 52009; 2770 // * SHIPMENT_TYPE_REQUIREMENT_SELF_DEPENDENT_TYPE = 52010; 2771 // * SHIPMENT_TYPE_REQUIREMENT_GRAPH_HAS_CYCLES = 52011; 2772 // * VEHICLE_OPERATOR_ERROR = 54; 2773 // * VEHICLE_OPERATOR_EMPTY_TYPE = 5400; 2774 // * VEHICLE_OPERATOR_MULTIPLE_START_TIME_WINDOWS = 5401; 2775 // * VEHICLE_OPERATOR_SOFT_START_TIME_WINDOW = 5402; 2776 // * VEHICLE_OPERATOR_MULTIPLE_END_TIME_WINDOWS = 5403; 2777 // * VEHICLE_OPERATOR_SOFT_END_TIME_WINDOW = 5404; 2778 // * DURATION_SECONDS_MATRIX_ERROR = 56; 2779 // * DURATION_SECONDS_MATRIX_DURATION_NEGATIVE_OR_NAN = 5600; 2780 // * DURATION_SECONDS_MATRIX_DURATION_EXCEEDS_GLOBAL_DURATION = 5601; 2781 int32 code = 1; 2782 2783 // The error display name. 2784 string display_name = 2; 2785 2786 // An error context may involve 0, 1 (most of the time) or more fields. For 2787 // example, referring to vehicle #4 and shipment #2's first pickup can be 2788 // done as follows: 2789 // ``` 2790 // fields { name: "vehicles" index: 4} 2791 // fields { name: "shipments" index: 2 sub_field {name: "pickups" index: 0} } 2792 // ``` 2793 // Note, however, that the cardinality of `fields` should not change for a 2794 // given error code. 2795 repeated FieldReference fields = 3; 2796 2797 // Human-readable string describing the error. There is a 1:1 mapping 2798 // between `code` and `error_message` (when code != "UNSPECIFIED"). 2799 // 2800 // *STABILITY*: Not stable: the error message associated to a given `code` may 2801 // change (hopefully to clarify it) over time. Please rely on the 2802 // `display_name` and `code` instead. 2803 string error_message = 4; 2804 2805 // May contain the value(s) of the field(s). This is not always available. You 2806 // should absolutely not rely on it and use it only for manual model 2807 // debugging. 2808 string offending_values = 5; 2809} 2810