update notebooks
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -132,7 +132,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
126
examples/notebook/algorithms/set_cover.ipynb
Normal file
126
examples/notebook/algorithms/set_cover.ipynb
Normal file
@@ -0,0 +1,126 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "apache",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"you may not use this file except in compliance with the License.\n",
|
||||
"You may obtain a copy of the License at\n",
|
||||
"\n",
|
||||
" http://www.apache.org/licenses/LICENSE-2.0\n",
|
||||
"\n",
|
||||
"Unless required by applicable law or agreed to in writing, software\n",
|
||||
"distributed under the License is distributed on an \"AS IS\" BASIS,\n",
|
||||
"WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"See the License for the specific language governing permissions and\n",
|
||||
"limitations under the License.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "basename",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# set_cover"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "link",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<table align=\"left\">\n",
|
||||
"<td>\n",
|
||||
"<a href=\"https://colab.research.google.com/github/google/or-tools/blob/main/examples/notebook/algorithms/set_cover.ipynb\"><img src=\"https://raw.githubusercontent.com/google/or-tools/main/tools/colab_32px.png\"/>Run in Google Colab</a>\n",
|
||||
"</td>\n",
|
||||
"<td>\n",
|
||||
"<a href=\"https://github.com/google/or-tools/blob/main/ortools/algorithms/samples/set_cover.py\"><img src=\"https://raw.githubusercontent.com/google/or-tools/main/tools/github_32px.png\"/>View source on GitHub</a>\n",
|
||||
"</td>\n",
|
||||
"</table>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "doc",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"First, you must install [ortools](https://pypi.org/project/ortools/) package in this colab."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "install",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%pip install ortools"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "description",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n",
|
||||
"A simple set-covering problem.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "code",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from ortools.algorithms.python import set_cover\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def main():\n",
|
||||
" model = set_cover.SetCoverModel()\n",
|
||||
" model.add_empty_subset(2.0)\n",
|
||||
" model.add_element_to_last_subset(0)\n",
|
||||
" model.add_empty_subset(2.0)\n",
|
||||
" model.add_element_to_last_subset(1)\n",
|
||||
" model.add_empty_subset(1.0)\n",
|
||||
" model.add_element_to_last_subset(0)\n",
|
||||
" model.add_element_to_last_subset(1)\n",
|
||||
"\n",
|
||||
" inv = set_cover.SetCoverInvariant(model)\n",
|
||||
" greedy = set_cover.GreedySolutionGenerator(inv)\n",
|
||||
" has_found = greedy.next_solution()\n",
|
||||
" if not has_found:\n",
|
||||
" print(\"No solution found by the greedy heuristic.\")\n",
|
||||
" return\n",
|
||||
" solution = inv.export_solution_as_proto()\n",
|
||||
"\n",
|
||||
" print(f\"Total cost: {solution.cost}\") # == inv.cost()\n",
|
||||
" print(f\"Total number of selected subsets: {solution.num_subsets}\")\n",
|
||||
" print(\"Chosen subsets:\")\n",
|
||||
" for subset in solution.subset:\n",
|
||||
" print(f\" {subset}\")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"main()\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -119,7 +119,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -91,6 +91,7 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def main():\n",
|
||||
" # Constraint programming engine\n",
|
||||
" solver = pywrapcp.Solver(\"CP is fun!\")\n",
|
||||
@@ -155,7 +156,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -74,31 +74,31 @@
|
||||
"source": [
|
||||
"Capacitated Vehicle Routing Problem (CVRP).\n",
|
||||
"\n",
|
||||
" This is a sample using the routing library python wrapper to solve a CVRP\n",
|
||||
" problem while allowing multiple trips, i.e., vehicles can return to a depot\n",
|
||||
" to reset their load (\"reload\").\n",
|
||||
"This is a sample using the routing library python wrapper to solve a CVRP\n",
|
||||
"problem while allowing multiple trips, i.e., vehicles can return to a depot\n",
|
||||
"to reset their load (\"reload\").\n",
|
||||
"\n",
|
||||
" A description of the CVRP problem can be found here:\n",
|
||||
" http://en.wikipedia.org/wiki/Vehicle_routing_problem.\n",
|
||||
"A description of the CVRP problem can be found here:\n",
|
||||
"http://en.wikipedia.org/wiki/Vehicle_routing_problem.\n",
|
||||
"\n",
|
||||
" Distances are in meters.\n",
|
||||
"Distances are in meters.\n",
|
||||
"\n",
|
||||
" In order to implement multiple trips, new nodes are introduced at the same\n",
|
||||
" locations of the original depots. These additional nodes can be dropped\n",
|
||||
" from the schedule at 0 cost.\n",
|
||||
"In order to implement multiple trips, new nodes are introduced at the same\n",
|
||||
"locations of the original depots. These additional nodes can be dropped\n",
|
||||
"from the schedule at 0 cost.\n",
|
||||
"\n",
|
||||
" The max_slack parameter associated to the capacity constraints of all nodes\n",
|
||||
" can be set to be the maximum of the vehicles' capacities, rather than 0 like\n",
|
||||
" in a traditional CVRP. Slack is required since before a solution is found,\n",
|
||||
" it is not known how much capacity will be transferred at the new nodes. For\n",
|
||||
" all the other (original) nodes, the slack is then re-set to 0.\n",
|
||||
"The max_slack parameter associated to the capacity constraints of all nodes\n",
|
||||
"can be set to be the maximum of the vehicles' capacities, rather than 0 like\n",
|
||||
"in a traditional CVRP. Slack is required since before a solution is found,\n",
|
||||
"it is not known how much capacity will be transferred at the new nodes. For\n",
|
||||
"all the other (original) nodes, the slack is then re-set to 0.\n",
|
||||
"\n",
|
||||
" The above two considerations are implemented in `add_capacity_constraints()`.\n",
|
||||
"The above two considerations are implemented in `add_capacity_constraints()`.\n",
|
||||
"\n",
|
||||
" Last, it is useful to set a large distance between the initial depot and the\n",
|
||||
" new nodes introduced, to avoid schedules having spurious transits through\n",
|
||||
" those new nodes unless it's necessary to reload. This consideration is taken\n",
|
||||
" into account in `create_distance_evaluator()`.\n",
|
||||
"Last, it is useful to set a large distance between the initial depot and the\n",
|
||||
"new nodes introduced, to avoid schedules having spurious transits through\n",
|
||||
"those new nodes unless it's necessary to reload. This consideration is taken\n",
|
||||
"into account in `create_distance_evaluator()`.\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
@@ -145,52 +145,69 @@
|
||||
" (3, 7),\n",
|
||||
" (6, 7),\n",
|
||||
" (0, 8),\n",
|
||||
" (7, 8)\n",
|
||||
" (7, 8),\n",
|
||||
" ]\n",
|
||||
" # Compute locations in meters using the block dimension defined as follow\n",
|
||||
" # Manhattan average block: 750ft x 264ft -> 228m x 80m\n",
|
||||
" # here we use: 114m x 80m city block\n",
|
||||
" # src: https://nyti.ms/2GDoRIe 'NY Times: Know Your distance'\n",
|
||||
" data['locations'] = [(l[0] * 114, l[1] * 80) for l in _locations]\n",
|
||||
" data['num_locations'] = len(data['locations'])\n",
|
||||
" data['demands'] = \\\n",
|
||||
" [0, # depot\n",
|
||||
" -_capacity, # unload depot_first\n",
|
||||
" -_capacity, # unload depot_second\n",
|
||||
" -_capacity, # unload depot_third\n",
|
||||
" -_capacity, # unload depot_fourth\n",
|
||||
" -_capacity, # unload depot_fifth\n",
|
||||
" 3, 3, # 1, 2\n",
|
||||
" 3, 4, # 3, 4\n",
|
||||
" 3, 4, # 5, 6\n",
|
||||
" 8, 8, # 7, 8\n",
|
||||
" 3, 3, # 9,10\n",
|
||||
" 3, 3, # 11,12\n",
|
||||
" 4, 4, # 13, 14\n",
|
||||
" 8, 8] # 15, 16\n",
|
||||
" data['time_per_demand_unit'] = 5 # 5 minutes/unit\n",
|
||||
" data['time_windows'] = \\\n",
|
||||
" [(0, 0), # depot\n",
|
||||
" (0, 1000), # unload depot_first\n",
|
||||
" (0, 1000), # unload depot_second\n",
|
||||
" (0, 1000), # unload depot_third\n",
|
||||
" (0, 1000), # unload depot_fourth\n",
|
||||
" (0, 1000), # unload depot_fifth\n",
|
||||
" (75, 850), (75, 850), # 1, 2\n",
|
||||
" (60, 700), (45, 550), # 3, 4\n",
|
||||
" (0, 800), (50, 600), # 5, 6\n",
|
||||
" (0, 1000), (10, 200), # 7, 8\n",
|
||||
" (0, 1000), (75, 850), # 9, 10\n",
|
||||
" (85, 950), (5, 150), # 11, 12\n",
|
||||
" (15, 250), (10, 200), # 13, 14\n",
|
||||
" (45, 550), (30, 400)] # 15, 16\n",
|
||||
" data['num_vehicles'] = 3\n",
|
||||
" data['vehicle_capacity'] = _capacity\n",
|
||||
" data['vehicle_max_distance'] = 10_000\n",
|
||||
" data['vehicle_max_time'] = 1_500\n",
|
||||
" data[\n",
|
||||
" 'vehicle_speed'] = 5 * 60 / 3.6 # Travel speed: 5km/h to convert in m/min\n",
|
||||
" data['depot'] = 0\n",
|
||||
" data[\"locations\"] = [(l[0] * 114, l[1] * 80) for l in _locations]\n",
|
||||
" data[\"num_locations\"] = len(data[\"locations\"])\n",
|
||||
" data[\"demands\"] = [\n",
|
||||
" 0, # depot\n",
|
||||
" -_capacity, # unload depot_first\n",
|
||||
" -_capacity, # unload depot_second\n",
|
||||
" -_capacity, # unload depot_third\n",
|
||||
" -_capacity, # unload depot_fourth\n",
|
||||
" -_capacity, # unload depot_fifth\n",
|
||||
" 3,\n",
|
||||
" 3, # 1, 2\n",
|
||||
" 3,\n",
|
||||
" 4, # 3, 4\n",
|
||||
" 3,\n",
|
||||
" 4, # 5, 6\n",
|
||||
" 8,\n",
|
||||
" 8, # 7, 8\n",
|
||||
" 3,\n",
|
||||
" 3, # 9,10\n",
|
||||
" 3,\n",
|
||||
" 3, # 11,12\n",
|
||||
" 4,\n",
|
||||
" 4, # 13, 14\n",
|
||||
" 8,\n",
|
||||
" 8,\n",
|
||||
" ] # 15, 16\n",
|
||||
" data[\"time_per_demand_unit\"] = 5 # 5 minutes/unit\n",
|
||||
" data[\"time_windows\"] = [\n",
|
||||
" (0, 0), # depot\n",
|
||||
" (0, 1000), # unload depot_first\n",
|
||||
" (0, 1000), # unload depot_second\n",
|
||||
" (0, 1000), # unload depot_third\n",
|
||||
" (0, 1000), # unload depot_fourth\n",
|
||||
" (0, 1000), # unload depot_fifth\n",
|
||||
" (75, 850),\n",
|
||||
" (75, 850), # 1, 2\n",
|
||||
" (60, 700),\n",
|
||||
" (45, 550), # 3, 4\n",
|
||||
" (0, 800),\n",
|
||||
" (50, 600), # 5, 6\n",
|
||||
" (0, 1000),\n",
|
||||
" (10, 200), # 7, 8\n",
|
||||
" (0, 1000),\n",
|
||||
" (75, 850), # 9, 10\n",
|
||||
" (85, 950),\n",
|
||||
" (5, 150), # 11, 12\n",
|
||||
" (15, 250),\n",
|
||||
" (10, 200), # 13, 14\n",
|
||||
" (45, 550),\n",
|
||||
" (30, 400),\n",
|
||||
" ] # 15, 16\n",
|
||||
" data[\"num_vehicles\"] = 3\n",
|
||||
" data[\"vehicle_capacity\"] = _capacity\n",
|
||||
" data[\"vehicle_max_distance\"] = 10_000\n",
|
||||
" data[\"vehicle_max_time\"] = 1_500\n",
|
||||
" data[\"vehicle_speed\"] = 5 * 60 / 3.6 # Travel speed: 5km/h to convert in m/min\n",
|
||||
" data[\"depot\"] = 0\n",
|
||||
" return data\n",
|
||||
"\n",
|
||||
"\n",
|
||||
@@ -199,30 +216,29 @@
|
||||
"#######################\n",
|
||||
"def manhattan_distance(position_1, position_2):\n",
|
||||
" \"\"\"Computes the Manhattan distance between two points\"\"\"\n",
|
||||
" return (abs(position_1[0] - position_2[0]) +\n",
|
||||
" abs(position_1[1] - position_2[1]))\n",
|
||||
" return abs(position_1[0] - position_2[0]) + abs(position_1[1] - position_2[1])\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_distance_evaluator(data):\n",
|
||||
" \"\"\"Creates callback to return distance between points.\"\"\"\n",
|
||||
" _distances = {}\n",
|
||||
" # precompute distance between location to have distance callback in O(1)\n",
|
||||
" for from_node in range(data['num_locations']):\n",
|
||||
" for from_node in range(data[\"num_locations\"]):\n",
|
||||
" _distances[from_node] = {}\n",
|
||||
" for to_node in range(data['num_locations']):\n",
|
||||
" for to_node in range(data[\"num_locations\"]):\n",
|
||||
" if from_node == to_node:\n",
|
||||
" _distances[from_node][to_node] = 0\n",
|
||||
" # Forbid start/end/reload node to be consecutive.\n",
|
||||
" elif from_node in range(6) and to_node in range(6):\n",
|
||||
" _distances[from_node][to_node] = data['vehicle_max_distance']\n",
|
||||
" _distances[from_node][to_node] = data[\"vehicle_max_distance\"]\n",
|
||||
" else:\n",
|
||||
" _distances[from_node][to_node] = (manhattan_distance(\n",
|
||||
" data['locations'][from_node], data['locations'][to_node]))\n",
|
||||
" _distances[from_node][to_node] = manhattan_distance(\n",
|
||||
" data[\"locations\"][from_node], data[\"locations\"][to_node]\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" def distance_evaluator(manager, from_node, to_node):\n",
|
||||
" \"\"\"Returns the manhattan distance between the two nodes\"\"\"\n",
|
||||
" return _distances[manager.IndexToNode(from_node)][manager.IndexToNode(\n",
|
||||
" to_node)]\n",
|
||||
" return _distances[manager.IndexToNode(from_node)][manager.IndexToNode(to_node)]\n",
|
||||
"\n",
|
||||
" return distance_evaluator\n",
|
||||
"\n",
|
||||
@@ -230,13 +246,14 @@
|
||||
"def add_distance_dimension(routing, manager, data, distance_evaluator_index):\n",
|
||||
" \"\"\"Add Global Span constraint\"\"\"\n",
|
||||
" del manager\n",
|
||||
" distance = 'Distance'\n",
|
||||
" distance = \"Distance\"\n",
|
||||
" routing.AddDimension(\n",
|
||||
" distance_evaluator_index,\n",
|
||||
" 0, # null slack\n",
|
||||
" data['vehicle_max_distance'], # maximum distance per vehicle\n",
|
||||
" data[\"vehicle_max_distance\"], # maximum distance per vehicle\n",
|
||||
" True, # start cumul to zero\n",
|
||||
" distance)\n",
|
||||
" distance,\n",
|
||||
" )\n",
|
||||
" distance_dimension = routing.GetDimensionOrDie(distance)\n",
|
||||
" # Try to minimize the max distance among vehicles.\n",
|
||||
" # /!\\ It doesn't mean the standard deviation is minimized\n",
|
||||
@@ -245,7 +262,7 @@
|
||||
"\n",
|
||||
"def create_demand_evaluator(data):\n",
|
||||
" \"\"\"Creates callback to get demands at each location.\"\"\"\n",
|
||||
" _demands = data['demands']\n",
|
||||
" _demands = data[\"demands\"]\n",
|
||||
"\n",
|
||||
" def demand_evaluator(manager, from_node):\n",
|
||||
" \"\"\"Returns the demand of the current node\"\"\"\n",
|
||||
@@ -256,14 +273,15 @@
|
||||
"\n",
|
||||
"def add_capacity_constraints(routing, manager, data, demand_evaluator_index):\n",
|
||||
" \"\"\"Adds capacity constraint\"\"\"\n",
|
||||
" vehicle_capacity = data['vehicle_capacity']\n",
|
||||
" capacity = 'Capacity'\n",
|
||||
" vehicle_capacity = data[\"vehicle_capacity\"]\n",
|
||||
" capacity = \"Capacity\"\n",
|
||||
" routing.AddDimension(\n",
|
||||
" demand_evaluator_index,\n",
|
||||
" vehicle_capacity,\n",
|
||||
" vehicle_capacity,\n",
|
||||
" True, # start cumul to zero\n",
|
||||
" capacity)\n",
|
||||
" capacity,\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" # Add Slack for reseting to zero unload depot nodes.\n",
|
||||
" # e.g. vehicle with load 10/15 arrives at node 1 (depot unload)\n",
|
||||
@@ -275,7 +293,7 @@
|
||||
" routing.AddDisjunction([node_index], 0)\n",
|
||||
"\n",
|
||||
" # Allow to drop regular node with a cost.\n",
|
||||
" for node in range(6, len(data['demands'])):\n",
|
||||
" for node in range(6, len(data[\"demands\"])):\n",
|
||||
" node_index = manager.NodeToIndex(node)\n",
|
||||
" capacity_dimension.SlackVar(node_index).SetValue(0)\n",
|
||||
" routing.AddDisjunction([node_index], 100_000)\n",
|
||||
@@ -286,52 +304,56 @@
|
||||
"\n",
|
||||
" def service_time(data, node):\n",
|
||||
" \"\"\"Gets the service time for the specified location.\"\"\"\n",
|
||||
" return abs(data['demands'][node]) * data['time_per_demand_unit']\n",
|
||||
" return abs(data[\"demands\"][node]) * data[\"time_per_demand_unit\"]\n",
|
||||
"\n",
|
||||
" def travel_time(data, from_node, to_node):\n",
|
||||
" \"\"\"Gets the travel times between two locations.\"\"\"\n",
|
||||
" if from_node == to_node:\n",
|
||||
" travel_time = 0\n",
|
||||
" else:\n",
|
||||
" travel_time = manhattan_distance(\n",
|
||||
" data['locations'][from_node],\n",
|
||||
" data['locations'][to_node]) / data['vehicle_speed']\n",
|
||||
" travel_time = (\n",
|
||||
" manhattan_distance(\n",
|
||||
" data[\"locations\"][from_node], data[\"locations\"][to_node]\n",
|
||||
" )\n",
|
||||
" / data[\"vehicle_speed\"]\n",
|
||||
" )\n",
|
||||
" return travel_time\n",
|
||||
"\n",
|
||||
" _total_time = {}\n",
|
||||
" # precompute total time to have time callback in O(1)\n",
|
||||
" for from_node in range(data['num_locations']):\n",
|
||||
" for from_node in range(data[\"num_locations\"]):\n",
|
||||
" _total_time[from_node] = {}\n",
|
||||
" for to_node in range(data['num_locations']):\n",
|
||||
" for to_node in range(data[\"num_locations\"]):\n",
|
||||
" if from_node == to_node:\n",
|
||||
" _total_time[from_node][to_node] = 0\n",
|
||||
" else:\n",
|
||||
" _total_time[from_node][to_node] = int(\n",
|
||||
" service_time(data, from_node) +\n",
|
||||
" travel_time(data, from_node, to_node))\n",
|
||||
" service_time(data, from_node)\n",
|
||||
" + travel_time(data, from_node, to_node)\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" def time_evaluator(manager, from_node, to_node):\n",
|
||||
" \"\"\"Returns the total time between the two nodes\"\"\"\n",
|
||||
" return _total_time[manager.IndexToNode(from_node)][manager.IndexToNode(\n",
|
||||
" to_node)]\n",
|
||||
" return _total_time[manager.IndexToNode(from_node)][manager.IndexToNode(to_node)]\n",
|
||||
"\n",
|
||||
" return time_evaluator\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def add_time_window_constraints(routing, manager, data, time_evaluator):\n",
|
||||
" \"\"\"Add Time windows constraint\"\"\"\n",
|
||||
" time = 'Time'\n",
|
||||
" max_time = data['vehicle_max_time']\n",
|
||||
" time = \"Time\"\n",
|
||||
" max_time = data[\"vehicle_max_time\"]\n",
|
||||
" routing.AddDimension(\n",
|
||||
" time_evaluator,\n",
|
||||
" max_time, # allow waiting time\n",
|
||||
" max_time, # maximum time per vehicle\n",
|
||||
" False, # don't force start cumul to zero since we are giving TW to start nodes\n",
|
||||
" time)\n",
|
||||
" time,\n",
|
||||
" )\n",
|
||||
" time_dimension = routing.GetDimensionOrDie(time)\n",
|
||||
" # Add time window constraints for each location except depot\n",
|
||||
" # and 'copy' the slack var in the solution object (aka Assignment) to print it\n",
|
||||
" for location_idx, time_window in enumerate(data['time_windows']):\n",
|
||||
" for location_idx, time_window in enumerate(data[\"time_windows\"]):\n",
|
||||
" if location_idx == 0:\n",
|
||||
" continue\n",
|
||||
" index = manager.NodeToIndex(location_idx)\n",
|
||||
@@ -339,70 +361,80 @@
|
||||
" routing.AddToAssignment(time_dimension.SlackVar(index))\n",
|
||||
" # Add time window constraints for each vehicle start node\n",
|
||||
" # and 'copy' the slack var in the solution object (aka Assignment) to print it\n",
|
||||
" for vehicle_id in range(data['num_vehicles']):\n",
|
||||
" for vehicle_id in range(data[\"num_vehicles\"]):\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" time_dimension.CumulVar(index).SetRange(data['time_windows'][0][0],\n",
|
||||
" data['time_windows'][0][1])\n",
|
||||
" time_dimension.CumulVar(index).SetRange(\n",
|
||||
" data[\"time_windows\"][0][0], data[\"time_windows\"][0][1]\n",
|
||||
" )\n",
|
||||
" routing.AddToAssignment(time_dimension.SlackVar(index))\n",
|
||||
" # Warning: Slack var is not defined for vehicle's end node\n",
|
||||
" #routing.AddToAssignment(time_dimension.SlackVar(self.routing.End(vehicle_id)))\n",
|
||||
" # routing.AddToAssignment(time_dimension.SlackVar(self.routing.End(vehicle_id)))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"###########\n",
|
||||
"# Printer #\n",
|
||||
"###########\n",
|
||||
"def print_solution(data, manager, routing, assignment): # pylint:disable=too-many-locals\n",
|
||||
"def print_solution(\n",
|
||||
" data, manager, routing, assignment\n",
|
||||
"): # pylint:disable=too-many-locals\n",
|
||||
" \"\"\"Prints assignment on console\"\"\"\n",
|
||||
" print(f'Objective: {assignment.ObjectiveValue()}')\n",
|
||||
" print(f\"Objective: {assignment.ObjectiveValue()}\")\n",
|
||||
" total_distance = 0\n",
|
||||
" total_load = 0\n",
|
||||
" total_time = 0\n",
|
||||
" capacity_dimension = routing.GetDimensionOrDie('Capacity')\n",
|
||||
" time_dimension = routing.GetDimensionOrDie('Time')\n",
|
||||
" capacity_dimension = routing.GetDimensionOrDie(\"Capacity\")\n",
|
||||
" time_dimension = routing.GetDimensionOrDie(\"Time\")\n",
|
||||
" distance_dimension = routing.GetDimensionOrDie(\"Distance\")\n",
|
||||
" dropped = []\n",
|
||||
" for order in range(6, routing.nodes()):\n",
|
||||
" index = manager.NodeToIndex(order)\n",
|
||||
" if assignment.Value(routing.NextVar(index)) == index:\n",
|
||||
" dropped.append(order)\n",
|
||||
" print(f'dropped orders: {dropped}')\n",
|
||||
" print(f\"dropped orders: {dropped}\")\n",
|
||||
" dropped = []\n",
|
||||
" for reload in range(1, 6):\n",
|
||||
" index = manager.NodeToIndex(reload)\n",
|
||||
" if assignment.Value(routing.NextVar(index)) == index:\n",
|
||||
" dropped.append(reload)\n",
|
||||
" print(f'dropped reload stations: {dropped}')\n",
|
||||
" print(f\"dropped reload stations: {dropped}\")\n",
|
||||
"\n",
|
||||
" for vehicle_id in range(data['num_vehicles']):\n",
|
||||
" for vehicle_id in range(data[\"num_vehicles\"]):\n",
|
||||
" if not routing.IsVehicleUsed(assignment, vehicle_id):\n",
|
||||
" continue\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = f'Route for vehicle {vehicle_id}:\\n'\n",
|
||||
" plan_output = f\"Route for vehicle {vehicle_id}:\\n\"\n",
|
||||
" load_value = 0\n",
|
||||
" distance = 0\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
" load_var = capacity_dimension.CumulVar(index)\n",
|
||||
" time_var = time_dimension.CumulVar(index)\n",
|
||||
" plan_output += (\n",
|
||||
" f' {manager.IndexToNode(index)} '\n",
|
||||
" f'Load({assignment.Min(load_var)}) '\n",
|
||||
" f'Time({assignment.Min(time_var)},{assignment.Max(time_var)}) ->'\n",
|
||||
" f\" {manager.IndexToNode(index)} \"\n",
|
||||
" f\"Load({assignment.Min(capacity_dimension.CumulVar(index))}) \"\n",
|
||||
" f\"Time({assignment.Min(time_var)},{assignment.Max(time_var)}) ->\"\n",
|
||||
" )\n",
|
||||
" previous_index = index\n",
|
||||
" index = assignment.Value(routing.NextVar(index))\n",
|
||||
" distance += routing.GetArcCostForVehicle(previous_index, index,\n",
|
||||
" vehicle_id)\n",
|
||||
" load_var = capacity_dimension.CumulVar(index)\n",
|
||||
" distance += distance_dimension.GetTransitValue(previous_index, index, vehicle_id)\n",
|
||||
" # capacity dimension TransitVar is negative at reload stations during replenishment\n",
|
||||
" # don't want to consider those values when calculating the total load of the route\n",
|
||||
" # hence only considering the positive values\n",
|
||||
" load_value += max(0, capacity_dimension.GetTransitValue(previous_index, index, vehicle_id))\n",
|
||||
" time_var = time_dimension.CumulVar(index)\n",
|
||||
" plan_output += (\n",
|
||||
" f' {manager.IndexToNode(index)} '\n",
|
||||
" f'Load({assignment.Min(load_var)}) '\n",
|
||||
" f'Time({assignment.Min(time_var)},{assignment.Max(time_var)})\\n')\n",
|
||||
" plan_output += f'Distance of the route: {distance}m\\n'\n",
|
||||
" plan_output += f'Load of the route: {assignment.Min(load_var)}\\n'\n",
|
||||
" plan_output += f'Time of the route: {assignment.Min(time_var)}min\\n'\n",
|
||||
" f\" {manager.IndexToNode(index)} \"\n",
|
||||
" f\"Load({assignment.Min(capacity_dimension.CumulVar(index))}) \"\n",
|
||||
" f\"Time({assignment.Min(time_var)},{assignment.Max(time_var)})\\n\"\n",
|
||||
" )\n",
|
||||
" plan_output += f\"Distance of the route: {distance}m\\n\"\n",
|
||||
" plan_output += f\"Load of the route: {load_value}\\n\"\n",
|
||||
" plan_output += f\"Time of the route: {assignment.Min(time_var)}min\\n\"\n",
|
||||
" print(plan_output)\n",
|
||||
" total_distance += distance\n",
|
||||
" total_load += assignment.Min(load_var)\n",
|
||||
" total_load += load_value\n",
|
||||
" total_time += assignment.Min(time_var)\n",
|
||||
" print(f'Total Distance of all routes: {total_distance}m')\n",
|
||||
" print(f'Total Load of all routes: {total_load}')\n",
|
||||
" print(f'Total Time of all routes: {total_time}min')\n",
|
||||
" print(f\"Total Distance of all routes: {total_distance}m\")\n",
|
||||
" print(f\"Total Load of all routes: {total_load}\")\n",
|
||||
" print(f\"Total Time of all routes: {total_time}min\")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"########\n",
|
||||
@@ -414,15 +446,17 @@
|
||||
" data = create_data_model()\n",
|
||||
"\n",
|
||||
" # Create the routing index manager\n",
|
||||
" manager = pywrapcp.RoutingIndexManager(data['num_locations'],\n",
|
||||
" data['num_vehicles'], data['depot'])\n",
|
||||
" manager = pywrapcp.RoutingIndexManager(\n",
|
||||
" data[\"num_locations\"], data[\"num_vehicles\"], data[\"depot\"]\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" # Create Routing Model\n",
|
||||
" routing = pywrapcp.RoutingModel(manager)\n",
|
||||
"\n",
|
||||
" # Define weight of each edge\n",
|
||||
" distance_evaluator_index = routing.RegisterTransitCallback(\n",
|
||||
" partial(create_distance_evaluator(data), manager))\n",
|
||||
" partial(create_distance_evaluator(data), manager)\n",
|
||||
" )\n",
|
||||
" routing.SetArcCostEvaluatorOfAllVehicles(distance_evaluator_index)\n",
|
||||
"\n",
|
||||
" # Add Distance constraint to minimize the longuest route\n",
|
||||
@@ -430,20 +464,24 @@
|
||||
"\n",
|
||||
" # Add Capacity constraint\n",
|
||||
" demand_evaluator_index = routing.RegisterUnaryTransitCallback(\n",
|
||||
" partial(create_demand_evaluator(data), manager))\n",
|
||||
" partial(create_demand_evaluator(data), manager)\n",
|
||||
" )\n",
|
||||
" add_capacity_constraints(routing, manager, data, demand_evaluator_index)\n",
|
||||
"\n",
|
||||
" # Add Time Window constraint\n",
|
||||
" time_evaluator_index = routing.RegisterTransitCallback(\n",
|
||||
" partial(create_time_evaluator(data), manager))\n",
|
||||
" partial(create_time_evaluator(data), manager)\n",
|
||||
" )\n",
|
||||
" add_time_window_constraints(routing, manager, data, time_evaluator_index)\n",
|
||||
"\n",
|
||||
" # Setting first solution heuristic (cheapest addition).\n",
|
||||
" search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n",
|
||||
" search_parameters.first_solution_strategy = (\n",
|
||||
" routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) # pylint: disable=no-member\n",
|
||||
" routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC\n",
|
||||
" ) # pylint: disable=no-member\n",
|
||||
" search_parameters.local_search_metaheuristic = (\n",
|
||||
" routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)\n",
|
||||
" routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH\n",
|
||||
" )\n",
|
||||
" search_parameters.time_limit.FromSeconds(3)\n",
|
||||
"\n",
|
||||
" # Solve the problem.\n",
|
||||
@@ -459,7 +497,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -75,12 +75,12 @@
|
||||
"\n",
|
||||
"Capacitated Vehicle Routing Problem with Time Windows (CVRPTW).\n",
|
||||
"\n",
|
||||
" This is a sample using the routing library python wrapper to solve a CVRPTW\n",
|
||||
" problem.\n",
|
||||
" A description of the problem can be found here:\n",
|
||||
" http://en.wikipedia.org/wiki/Vehicle_routing_problem.\n",
|
||||
"This is a sample using the routing library python wrapper to solve a CVRPTW\n",
|
||||
"problem.\n",
|
||||
"A description of the problem can be found here:\n",
|
||||
"http://en.wikipedia.org/wiki/Vehicle_routing_problem.\n",
|
||||
"\n",
|
||||
" Distances are in meters and time in minutes.\n",
|
||||
"Distances are in meters and time in minutes.\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
@@ -96,6 +96,7 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_data_model():\n",
|
||||
" \"\"\"Stores the data for the problem.\"\"\"\n",
|
||||
" data = {}\n",
|
||||
@@ -303,6 +304,8 @@
|
||||
" capacity_dimension = routing.GetDimensionOrDie(\"Capacity\")\n",
|
||||
" time_dimension = routing.GetDimensionOrDie(\"Time\")\n",
|
||||
" for vehicle_id in range(data[\"num_vehicles\"]):\n",
|
||||
" if not routing.IsVehicleUsed(assignment, vehicle_id):\n",
|
||||
" continue\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = f\"Route for vehicle {vehicle_id}:\\n\"\n",
|
||||
" distance = 0\n",
|
||||
@@ -386,7 +389,11 @@
|
||||
" vehicle_break = data[\"breaks\"][v]\n",
|
||||
" break_intervals[v] = [\n",
|
||||
" routing.solver().FixedDurationIntervalVar(\n",
|
||||
" 15, 100, vehicle_break[0], vehicle_break[1], f\"Break for vehicle {v}\"\n",
|
||||
" 15,\n",
|
||||
" 100,\n",
|
||||
" vehicle_break[0],\n",
|
||||
" vehicle_break[1],\n",
|
||||
" f\"Break for vehicle {v}\",\n",
|
||||
" )\n",
|
||||
" ]\n",
|
||||
" time_dimension.SetBreakIntervalsOfVehicle(\n",
|
||||
@@ -414,7 +421,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -87,6 +87,7 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def main(board_size):\n",
|
||||
" # Creates the solver.\n",
|
||||
" solver = pywrapcp.Solver(\"n-queens\")\n",
|
||||
@@ -139,7 +140,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -86,6 +86,7 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def main():\n",
|
||||
" \"\"\"Entry point of the program.\"\"\"\n",
|
||||
" # Instantiate the solver.\n",
|
||||
@@ -128,7 +129,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -87,6 +87,7 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def main():\n",
|
||||
" \"\"\"Entry point of the program.\"\"\"\n",
|
||||
" # Instantiate the data problem.\n",
|
||||
@@ -142,7 +143,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -91,6 +91,7 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_data_model():\n",
|
||||
" \"\"\"Stores the data for the problem.\"\"\"\n",
|
||||
" data = {}\n",
|
||||
@@ -195,7 +196,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -88,6 +88,7 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_data_model():\n",
|
||||
" \"\"\"Stores the data for the problem.\"\"\"\n",
|
||||
" data = {}\n",
|
||||
@@ -226,7 +227,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -87,6 +87,7 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_data_model():\n",
|
||||
" \"\"\"Stores the data for the problem.\"\"\"\n",
|
||||
" data = {}\n",
|
||||
@@ -122,8 +123,8 @@
|
||||
" index = solution.Value(routing.NextVar(index))\n",
|
||||
" route_distance += routing.GetArcCostForVehicle(previous_index, index, 0)\n",
|
||||
" plan_output += f\" {manager.IndexToNode(index)}\\n\"\n",
|
||||
" print(plan_output)\n",
|
||||
" plan_output += f\"Route distance: {route_distance}miles\\n\"\n",
|
||||
" print(plan_output)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def main():\n",
|
||||
@@ -171,7 +172,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -87,6 +87,7 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_data_model():\n",
|
||||
" \"\"\"Stores the data for the problem.\"\"\"\n",
|
||||
" data = {}\n",
|
||||
@@ -177,7 +178,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -75,12 +75,12 @@
|
||||
"\n",
|
||||
"Simple Vehicles Routing Problem (VRP).\n",
|
||||
"\n",
|
||||
" This is a sample using the routing library python wrapper to solve a VRP\n",
|
||||
" problem.\n",
|
||||
" A description of the problem can be found here:\n",
|
||||
" http://en.wikipedia.org/wiki/Vehicle_routing_problem.\n",
|
||||
"This is a sample using the routing library python wrapper to solve a VRP\n",
|
||||
"problem.\n",
|
||||
"A description of the problem can be found here:\n",
|
||||
"http://en.wikipedia.org/wiki/Vehicle_routing_problem.\n",
|
||||
"\n",
|
||||
" Distances are in meters.\n",
|
||||
"Distances are in meters.\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
@@ -95,6 +95,7 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_data_model():\n",
|
||||
" \"\"\"Stores the data for the problem.\"\"\"\n",
|
||||
" data = {}\n",
|
||||
@@ -128,16 +129,18 @@
|
||||
" \"\"\"Prints solution on console.\"\"\"\n",
|
||||
" print(f\"Objective: {solution.ObjectiveValue()}\")\n",
|
||||
" total_distance = 0\n",
|
||||
" for vehicle_id in range(data[\"num_vehicles\"]):\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = f\"Route for vehicle {vehicle_id}:\\n\"\n",
|
||||
" for vehicle_index in range(manager.GetNumberOfVehicles()):\n",
|
||||
" if not routing.IsVehicleUsed(solution, vehicle_index):\n",
|
||||
" continue\n",
|
||||
" index = routing.Start(vehicle_index)\n",
|
||||
" plan_output = f\"Route for vehicle {vehicle_index}:\\n\"\n",
|
||||
" route_distance = 0\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
" plan_output += f\" {manager.IndexToNode(index)} ->\"\n",
|
||||
" previous_index = index\n",
|
||||
" index = solution.Value(routing.NextVar(index))\n",
|
||||
" route_distance += routing.GetArcCostForVehicle(\n",
|
||||
" previous_index, index, vehicle_id\n",
|
||||
" previous_index, index, vehicle_index\n",
|
||||
" )\n",
|
||||
" plan_output += f\" {manager.IndexToNode(index)}\\n\"\n",
|
||||
" plan_output += f\"Distance of the route: {route_distance}m\\n\"\n",
|
||||
@@ -194,7 +197,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -95,6 +95,7 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_data_model():\n",
|
||||
" \"\"\"Stores the data for the problem.\"\"\"\n",
|
||||
" data = {}\n",
|
||||
@@ -145,6 +146,8 @@
|
||||
" time_dimension = routing.GetDimensionOrDie(\"Time\")\n",
|
||||
" total_time = 0\n",
|
||||
" for vehicle_id in range(manager.GetNumberOfVehicles()):\n",
|
||||
" if not routing.IsVehicleUsed(solution, vehicle_id):\n",
|
||||
" continue\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = f\"Route for vehicle {vehicle_id}:\\n\"\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
@@ -247,7 +250,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -73,14 +73,15 @@
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Vehicles Routing Problem (VRP) with breaks relative to the vehicle start time.\n",
|
||||
" Each vehicles start at T:15min, T:30min, T:45min and T:60min respectively.\n",
|
||||
"\n",
|
||||
" Each vehicle must perform a break lasting 5 minutes,\n",
|
||||
" starting between 25 and 45 minutes after route start.\n",
|
||||
" e.g. vehicle 2 starting a T:45min must start a 5min breaks\n",
|
||||
" between [45+25,45+45] i.e. in the range [70, 90].\n",
|
||||
"Each vehicles start at T:15min, T:30min, T:45min and T:60min respectively.\n",
|
||||
"\n",
|
||||
" Durations are in minutes.\n",
|
||||
"Each vehicle must perform a break lasting 5 minutes,\n",
|
||||
"starting between 25 and 45 minutes after route start.\n",
|
||||
"e.g. vehicle 2 starting a T:45min must start a 5min breaks\n",
|
||||
"between [45+25,45+45] i.e. in the range [70, 90].\n",
|
||||
"\n",
|
||||
"Durations are in minutes.\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
@@ -95,12 +96,13 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_data_model():\n",
|
||||
" \"\"\"Stores the data for the problem.\"\"\"\n",
|
||||
" data = {}\n",
|
||||
" data['num_vehicles'] = 4\n",
|
||||
" data['depot'] = 0\n",
|
||||
" data['time_matrix'] = [\n",
|
||||
" data[\"num_vehicles\"] = 4\n",
|
||||
" data[\"depot\"] = 0\n",
|
||||
" data[\"time_matrix\"] = [\n",
|
||||
" [0, 27, 38, 34, 29, 13, 25, 9, 15, 9, 26, 25, 19, 17, 23, 38, 33],\n",
|
||||
" [27, 0, 34, 15, 9, 25, 36, 17, 34, 37, 54, 29, 24, 33, 50, 43, 60],\n",
|
||||
" [38, 34, 0, 49, 43, 25, 13, 40, 23, 37, 20, 63, 58, 56, 39, 77, 37],\n",
|
||||
@@ -120,46 +122,50 @@
|
||||
" [33, 60, 37, 67, 62, 35, 24, 42, 25, 23, 17, 42, 36, 26, 9, 39, 0],\n",
|
||||
" ]\n",
|
||||
" # 15 min of service time\n",
|
||||
" data['service_time'] = [15] * len(data['time_matrix'])\n",
|
||||
" data['service_time'][data['depot']] = 0\n",
|
||||
" assert len(data['time_matrix']) == len(data['service_time'])\n",
|
||||
" data[\"service_time\"] = [15] * len(data[\"time_matrix\"])\n",
|
||||
" data[\"service_time\"][data[\"depot\"]] = 0\n",
|
||||
" assert len(data[\"time_matrix\"]) == len(data[\"service_time\"])\n",
|
||||
" return data\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def print_solution(manager, routing, solution):\n",
|
||||
" \"\"\"Prints solution on console.\"\"\"\n",
|
||||
" print(f'Objective: {solution.ObjectiveValue()}')\n",
|
||||
" print(f\"Objective: {solution.ObjectiveValue()}\")\n",
|
||||
"\n",
|
||||
" print('Breaks:')\n",
|
||||
" print(\"Breaks:\")\n",
|
||||
" intervals = solution.IntervalVarContainer()\n",
|
||||
" for i in range(intervals.Size()):\n",
|
||||
" brk = intervals.Element(i)\n",
|
||||
" if brk.PerformedValue() == 1:\n",
|
||||
" print(f'{brk.Var().Name()}: ' +\n",
|
||||
" f'Start({brk.StartValue()}) Duration({brk.DurationValue()})')\n",
|
||||
" print(\n",
|
||||
" f\"{brk.Var().Name()}: \"\n",
|
||||
" + f\"Start({brk.StartValue()}) Duration({brk.DurationValue()})\"\n",
|
||||
" )\n",
|
||||
" else:\n",
|
||||
" print(f'{brk.Var().Name()}: Unperformed')\n",
|
||||
" print(f\"{brk.Var().Name()}: Unperformed\")\n",
|
||||
"\n",
|
||||
" time_dimension = routing.GetDimensionOrDie('Time')\n",
|
||||
" time_dimension = routing.GetDimensionOrDie(\"Time\")\n",
|
||||
" total_time = 0\n",
|
||||
" for vehicle_id in range(manager.GetNumberOfVehicles()):\n",
|
||||
" if not routing.IsVehicleUsed(solution, vehicle_id):\n",
|
||||
" continue\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = f'Route for vehicle {vehicle_id}:\\n'\n",
|
||||
" plan_output = f\"Route for vehicle {vehicle_id}:\\n\"\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
" time_var = time_dimension.CumulVar(index)\n",
|
||||
" if routing.IsStart(index):\n",
|
||||
" start_time = solution.Value(time_var)\n",
|
||||
" plan_output += f'{manager.IndexToNode(index)} '\n",
|
||||
" plan_output += f'Time({solution.Value(time_var)}) -> '\n",
|
||||
" plan_output += f\"{manager.IndexToNode(index)} \"\n",
|
||||
" plan_output += f\"Time({solution.Value(time_var)}) -> \"\n",
|
||||
" index = solution.Value(routing.NextVar(index))\n",
|
||||
" time_var = time_dimension.CumulVar(index)\n",
|
||||
" plan_output += f'{manager.IndexToNode(index)} '\n",
|
||||
" plan_output += f'Time({solution.Value(time_var)})'\n",
|
||||
" plan_output += f\"{manager.IndexToNode(index)} \"\n",
|
||||
" plan_output += f\"Time({solution.Value(time_var)})\"\n",
|
||||
" print(plan_output)\n",
|
||||
" route_time = solution.Value(time_var) - start_time\n",
|
||||
" print(f'Time of the route: {route_time}min\\n')\n",
|
||||
" print(f\"Time of the route: {route_time}min\\n\")\n",
|
||||
" total_time += route_time\n",
|
||||
" print(f'Total time of all routes: {total_time}min')\n",
|
||||
" print(f\"Total time of all routes: {total_time}min\")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def main():\n",
|
||||
@@ -168,20 +174,20 @@
|
||||
" data = create_data_model()\n",
|
||||
"\n",
|
||||
" # Create the routing index manager.\n",
|
||||
" manager = pywrapcp.RoutingIndexManager(len(data['time_matrix']),\n",
|
||||
" data['num_vehicles'], data['depot'])\n",
|
||||
" manager = pywrapcp.RoutingIndexManager(\n",
|
||||
" len(data[\"time_matrix\"]), data[\"num_vehicles\"], data[\"depot\"]\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" # Create Routing Model.\n",
|
||||
" routing = pywrapcp.RoutingModel(manager)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" # Create and register a transit callback.\n",
|
||||
" def time_callback(from_index, to_index):\n",
|
||||
" \"\"\"Returns the travel time between the two nodes.\"\"\"\n",
|
||||
" # Convert from routing variable Index to time matrix NodeIndex.\n",
|
||||
" from_node = manager.IndexToNode(from_index)\n",
|
||||
" to_node = manager.IndexToNode(to_index)\n",
|
||||
" return data['time_matrix'][from_node][to_node]\n",
|
||||
" return data[\"time_matrix\"][from_node][to_node]\n",
|
||||
"\n",
|
||||
" transit_callback_index = routing.RegisterTransitCallback(time_callback)\n",
|
||||
"\n",
|
||||
@@ -189,13 +195,14 @@
|
||||
" routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n",
|
||||
"\n",
|
||||
" # Add Time Windows constraint.\n",
|
||||
" time = 'Time'\n",
|
||||
" time = \"Time\"\n",
|
||||
" routing.AddDimension(\n",
|
||||
" transit_callback_index,\n",
|
||||
" 10, # need optional waiting time to place break\n",
|
||||
" 180, # maximum time per vehicle\n",
|
||||
" False, # Don't force start cumul to zero.\n",
|
||||
" time)\n",
|
||||
" time,\n",
|
||||
" )\n",
|
||||
" time_dimension = routing.GetDimensionOrDie(time)\n",
|
||||
" time_dimension.SetGlobalSpanCostCoefficient(10)\n",
|
||||
"\n",
|
||||
@@ -209,27 +216,30 @@
|
||||
" node_visit_transit = [0] * routing.Size()\n",
|
||||
" for index in range(routing.Size()):\n",
|
||||
" node = manager.IndexToNode(index)\n",
|
||||
" node_visit_transit[index] = data['service_time'][node]\n",
|
||||
" node_visit_transit[index] = data[\"service_time\"][node]\n",
|
||||
"\n",
|
||||
" # Add a break lasting 5 minutes, start between 25 and 45 minutes after route start\n",
|
||||
" for v in range(manager.GetNumberOfVehicles()):\n",
|
||||
" start_var = time_dimension.CumulVar(routing.Start(v))\n",
|
||||
" break_start = routing.solver().Sum(\n",
|
||||
" [routing.solver().IntVar(25, 45), start_var])\n",
|
||||
" break_start = routing.solver().Sum([routing.solver().IntVar(25, 45), start_var])\n",
|
||||
"\n",
|
||||
" break_intervals = [\n",
|
||||
" routing.solver().FixedDurationIntervalVar(break_start, 5,\n",
|
||||
" f'Break for vehicle {v}')\n",
|
||||
" routing.solver().FixedDurationIntervalVar(\n",
|
||||
" break_start, 5, f\"Break for vehicle {v}\"\n",
|
||||
" )\n",
|
||||
" ]\n",
|
||||
" time_dimension.SetBreakIntervalsOfVehicle(break_intervals, v,\n",
|
||||
" node_visit_transit)\n",
|
||||
" time_dimension.SetBreakIntervalsOfVehicle(\n",
|
||||
" break_intervals, v, node_visit_transit\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" # Setting first solution heuristic.\n",
|
||||
" search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n",
|
||||
" search_parameters.first_solution_strategy = (\n",
|
||||
" routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n",
|
||||
" routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC\n",
|
||||
" )\n",
|
||||
" search_parameters.local_search_metaheuristic = (\n",
|
||||
" routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)\n",
|
||||
" routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH\n",
|
||||
" )\n",
|
||||
" # search_parameters.log_search = True\n",
|
||||
" search_parameters.time_limit.FromSeconds(2)\n",
|
||||
"\n",
|
||||
@@ -240,7 +250,7 @@
|
||||
" if solution:\n",
|
||||
" print_solution(manager, routing, solution)\n",
|
||||
" else:\n",
|
||||
" print('No solution found !')\n",
|
||||
" print(\"No solution found !\")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"main()\n",
|
||||
@@ -248,7 +258,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -87,6 +87,7 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_data_model():\n",
|
||||
" \"\"\"Stores the data for the problem.\"\"\"\n",
|
||||
" data = {}\n",
|
||||
@@ -124,6 +125,8 @@
|
||||
" total_distance = 0\n",
|
||||
" total_load = 0\n",
|
||||
" for vehicle_id in range(data[\"num_vehicles\"]):\n",
|
||||
" if not routing.IsVehicleUsed(solution, vehicle_id):\n",
|
||||
" continue\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = f\"Route for vehicle {vehicle_id}:\\n\"\n",
|
||||
" route_distance = 0\n",
|
||||
@@ -212,7 +215,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -87,6 +87,7 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_data_model():\n",
|
||||
" \"\"\"Stores the data for the problem.\"\"\"\n",
|
||||
" data = {}\n",
|
||||
@@ -133,6 +134,8 @@
|
||||
" total_distance = 0\n",
|
||||
" total_load = 0\n",
|
||||
" for vehicle_id in range(data[\"num_vehicles\"]):\n",
|
||||
" if not routing.IsVehicleUsed(assignment, vehicle_id):\n",
|
||||
" continue\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = f\"Route for vehicle {vehicle_id}:\\n\"\n",
|
||||
" route_distance = 0\n",
|
||||
@@ -225,7 +228,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -75,12 +75,12 @@
|
||||
"\n",
|
||||
"Simple Vehicles Routing Problem (VRP).\n",
|
||||
"\n",
|
||||
" This is a sample using the routing library python wrapper to solve a VRP\n",
|
||||
" problem.\n",
|
||||
" A description of the problem can be found here:\n",
|
||||
" http://en.wikipedia.org/wiki/Vehicle_routing_problem.\n",
|
||||
"This is a sample using the routing library python wrapper to solve a VRP\n",
|
||||
"problem.\n",
|
||||
"A description of the problem can be found here:\n",
|
||||
"http://en.wikipedia.org/wiki/Vehicle_routing_problem.\n",
|
||||
"\n",
|
||||
" Distances are in meters.\n",
|
||||
"Distances are in meters.\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
@@ -95,6 +95,7 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_data_model():\n",
|
||||
" \"\"\"Stores the data for the problem.\"\"\"\n",
|
||||
" data = {}\n",
|
||||
@@ -129,6 +130,8 @@
|
||||
" print(f\"Objective: {solution.ObjectiveValue()}\")\n",
|
||||
" max_route_distance = 0\n",
|
||||
" for vehicle_id in range(data[\"num_vehicles\"]):\n",
|
||||
" if not routing.IsVehicleUsed(solution, vehicle_id):\n",
|
||||
" continue\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = f\"Route for vehicle {vehicle_id}:\\n\"\n",
|
||||
" route_distance = 0\n",
|
||||
@@ -206,7 +209,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -87,6 +87,7 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_data_model():\n",
|
||||
" \"\"\"Stores the data for the problem.\"\"\"\n",
|
||||
" data = {}\n",
|
||||
@@ -129,6 +130,8 @@
|
||||
" print(f\"Objective: {solution.ObjectiveValue()}\")\n",
|
||||
" max_route_distance = 0\n",
|
||||
" for vehicle_id in range(data[\"num_vehicles\"]):\n",
|
||||
" if not routing.IsVehicleUsed(solution, vehicle_id):\n",
|
||||
" continue\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = f\"Route for vehicle {vehicle_id}:\\n\"\n",
|
||||
" route_distance = 0\n",
|
||||
@@ -220,7 +223,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -73,9 +73,9 @@
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Vehicles Routing Problem (VRP) for delivering items from any suppliers.\n",
|
||||
"Description:\n",
|
||||
"Need to deliver some item X and Y at end nodes (at least 11 X and 13 Y).\n",
|
||||
"Several locations provide them and even few provide both.\n",
|
||||
"\n",
|
||||
"Description: Need to deliver some item X and Y at end nodes (at least 11 X and\n",
|
||||
"13 Y). Several locations provide them and even few provide both.\n",
|
||||
"\n",
|
||||
"fleet:\n",
|
||||
" * vehicles: 2\n",
|
||||
@@ -101,14 +101,14 @@
|
||||
"def create_data_model():\n",
|
||||
" \"\"\"Stores the data for the problem.\"\"\"\n",
|
||||
" data = {}\n",
|
||||
" data['num_vehicles'] = 2\n",
|
||||
" data['starts'] = [0] * data['num_vehicles']\n",
|
||||
" data['ends'] = [1] * data['num_vehicles']\n",
|
||||
" assert len(data['starts']) == data['num_vehicles']\n",
|
||||
" assert len(data['ends']) == data['num_vehicles']\n",
|
||||
" data[\"num_vehicles\"] = 2\n",
|
||||
" data[\"starts\"] = [0] * data[\"num_vehicles\"]\n",
|
||||
" data[\"ends\"] = [1] * data[\"num_vehicles\"]\n",
|
||||
" assert len(data[\"starts\"]) == data[\"num_vehicles\"]\n",
|
||||
" assert len(data[\"ends\"]) == data[\"num_vehicles\"]\n",
|
||||
"\n",
|
||||
" # Need 11 X and 13 Y\n",
|
||||
" data['providers_x'] = [\n",
|
||||
" data[\"providers_x\"] = [\n",
|
||||
" 0, # start\n",
|
||||
" -11, # end\n",
|
||||
" 2, # X supply 1\n",
|
||||
@@ -127,7 +127,7 @@
|
||||
" 0, # Y supply 5\n",
|
||||
" 0, # Y supply 6\n",
|
||||
" ]\n",
|
||||
" data['providers_y'] = [\n",
|
||||
" data[\"providers_y\"] = [\n",
|
||||
" 0, # start\n",
|
||||
" -13, # ends\n",
|
||||
" 0, # X supply 1\n",
|
||||
@@ -146,127 +146,384 @@
|
||||
" 3, # Y supply 5\n",
|
||||
" 5, # Y supply 6\n",
|
||||
" ]\n",
|
||||
" data['vehicle_capacities_x'] = [15] * data['num_vehicles']\n",
|
||||
" data['vehicle_capacities_y'] = [15] * data['num_vehicles']\n",
|
||||
" assert len(data['vehicle_capacities_x']) == data['num_vehicles']\n",
|
||||
" assert len(data['vehicle_capacities_y']) == data['num_vehicles']\n",
|
||||
" data['distance_matrix'] = [\n",
|
||||
" data[\"vehicle_capacities_x\"] = [15] * data[\"num_vehicles\"]\n",
|
||||
" data[\"vehicle_capacities_y\"] = [15] * data[\"num_vehicles\"]\n",
|
||||
" assert len(data[\"vehicle_capacities_x\"]) == data[\"num_vehicles\"]\n",
|
||||
" assert len(data[\"vehicle_capacities_y\"]) == data[\"num_vehicles\"]\n",
|
||||
" data[\"distance_matrix\"] = [\n",
|
||||
" [\n",
|
||||
" 0, 548, 776, 696, 582, 274, 502, 194, 308, 194, 536, 502, 388, 354,\n",
|
||||
" 468, 776, 662\n",
|
||||
" 0,\n",
|
||||
" 548,\n",
|
||||
" 776,\n",
|
||||
" 696,\n",
|
||||
" 582,\n",
|
||||
" 274,\n",
|
||||
" 502,\n",
|
||||
" 194,\n",
|
||||
" 308,\n",
|
||||
" 194,\n",
|
||||
" 536,\n",
|
||||
" 502,\n",
|
||||
" 388,\n",
|
||||
" 354,\n",
|
||||
" 468,\n",
|
||||
" 776,\n",
|
||||
" 662,\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 548, 0, 684, 308, 194, 502, 730, 354, 696, 742, 1084, 594, 480, 674,\n",
|
||||
" 1016, 868, 1210\n",
|
||||
" 548,\n",
|
||||
" 0,\n",
|
||||
" 684,\n",
|
||||
" 308,\n",
|
||||
" 194,\n",
|
||||
" 502,\n",
|
||||
" 730,\n",
|
||||
" 354,\n",
|
||||
" 696,\n",
|
||||
" 742,\n",
|
||||
" 1084,\n",
|
||||
" 594,\n",
|
||||
" 480,\n",
|
||||
" 674,\n",
|
||||
" 1016,\n",
|
||||
" 868,\n",
|
||||
" 1210,\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 776, 684, 0, 992, 878, 502, 274, 810, 468, 742, 400, 1278, 1164,\n",
|
||||
" 1130, 788, 1552, 754\n",
|
||||
" 776,\n",
|
||||
" 684,\n",
|
||||
" 0,\n",
|
||||
" 992,\n",
|
||||
" 878,\n",
|
||||
" 502,\n",
|
||||
" 274,\n",
|
||||
" 810,\n",
|
||||
" 468,\n",
|
||||
" 742,\n",
|
||||
" 400,\n",
|
||||
" 1278,\n",
|
||||
" 1164,\n",
|
||||
" 1130,\n",
|
||||
" 788,\n",
|
||||
" 1552,\n",
|
||||
" 754,\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 696, 308, 992, 0, 114, 650, 878, 502, 844, 890, 1232, 514, 628, 822,\n",
|
||||
" 1164, 560, 1358\n",
|
||||
" 696,\n",
|
||||
" 308,\n",
|
||||
" 992,\n",
|
||||
" 0,\n",
|
||||
" 114,\n",
|
||||
" 650,\n",
|
||||
" 878,\n",
|
||||
" 502,\n",
|
||||
" 844,\n",
|
||||
" 890,\n",
|
||||
" 1232,\n",
|
||||
" 514,\n",
|
||||
" 628,\n",
|
||||
" 822,\n",
|
||||
" 1164,\n",
|
||||
" 560,\n",
|
||||
" 1358,\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 582, 194, 878, 114, 0, 536, 764, 388, 730, 776, 1118, 400, 514, 708,\n",
|
||||
" 1050, 674, 1244\n",
|
||||
" 582,\n",
|
||||
" 194,\n",
|
||||
" 878,\n",
|
||||
" 114,\n",
|
||||
" 0,\n",
|
||||
" 536,\n",
|
||||
" 764,\n",
|
||||
" 388,\n",
|
||||
" 730,\n",
|
||||
" 776,\n",
|
||||
" 1118,\n",
|
||||
" 400,\n",
|
||||
" 514,\n",
|
||||
" 708,\n",
|
||||
" 1050,\n",
|
||||
" 674,\n",
|
||||
" 1244,\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 274, 502, 502, 650, 536, 0, 228, 308, 194, 240, 582, 776, 662, 628,\n",
|
||||
" 514, 1050, 708\n",
|
||||
" 274,\n",
|
||||
" 502,\n",
|
||||
" 502,\n",
|
||||
" 650,\n",
|
||||
" 536,\n",
|
||||
" 0,\n",
|
||||
" 228,\n",
|
||||
" 308,\n",
|
||||
" 194,\n",
|
||||
" 240,\n",
|
||||
" 582,\n",
|
||||
" 776,\n",
|
||||
" 662,\n",
|
||||
" 628,\n",
|
||||
" 514,\n",
|
||||
" 1050,\n",
|
||||
" 708,\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 502, 730, 274, 878, 764, 228, 0, 536, 194, 468, 354, 1004, 890, 856,\n",
|
||||
" 514, 1278, 480\n",
|
||||
" 502,\n",
|
||||
" 730,\n",
|
||||
" 274,\n",
|
||||
" 878,\n",
|
||||
" 764,\n",
|
||||
" 228,\n",
|
||||
" 0,\n",
|
||||
" 536,\n",
|
||||
" 194,\n",
|
||||
" 468,\n",
|
||||
" 354,\n",
|
||||
" 1004,\n",
|
||||
" 890,\n",
|
||||
" 856,\n",
|
||||
" 514,\n",
|
||||
" 1278,\n",
|
||||
" 480,\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 194, 354, 810, 502, 388, 308, 536, 0, 342, 388, 730, 468, 354, 320,\n",
|
||||
" 662, 742, 856\n",
|
||||
" 194,\n",
|
||||
" 354,\n",
|
||||
" 810,\n",
|
||||
" 502,\n",
|
||||
" 388,\n",
|
||||
" 308,\n",
|
||||
" 536,\n",
|
||||
" 0,\n",
|
||||
" 342,\n",
|
||||
" 388,\n",
|
||||
" 730,\n",
|
||||
" 468,\n",
|
||||
" 354,\n",
|
||||
" 320,\n",
|
||||
" 662,\n",
|
||||
" 742,\n",
|
||||
" 856,\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 308, 696, 468, 844, 730, 194, 194, 342, 0, 274, 388, 810, 696, 662,\n",
|
||||
" 320, 1084, 514\n",
|
||||
" 308,\n",
|
||||
" 696,\n",
|
||||
" 468,\n",
|
||||
" 844,\n",
|
||||
" 730,\n",
|
||||
" 194,\n",
|
||||
" 194,\n",
|
||||
" 342,\n",
|
||||
" 0,\n",
|
||||
" 274,\n",
|
||||
" 388,\n",
|
||||
" 810,\n",
|
||||
" 696,\n",
|
||||
" 662,\n",
|
||||
" 320,\n",
|
||||
" 1084,\n",
|
||||
" 514,\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 194, 742, 742, 890, 776, 240, 468, 388, 274, 0, 342, 536, 422, 388,\n",
|
||||
" 274, 810, 468\n",
|
||||
" 194,\n",
|
||||
" 742,\n",
|
||||
" 742,\n",
|
||||
" 890,\n",
|
||||
" 776,\n",
|
||||
" 240,\n",
|
||||
" 468,\n",
|
||||
" 388,\n",
|
||||
" 274,\n",
|
||||
" 0,\n",
|
||||
" 342,\n",
|
||||
" 536,\n",
|
||||
" 422,\n",
|
||||
" 388,\n",
|
||||
" 274,\n",
|
||||
" 810,\n",
|
||||
" 468,\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 536, 1084, 400, 1232, 1118, 582, 354, 730, 388, 342, 0, 878, 764,\n",
|
||||
" 730, 388, 1152, 354\n",
|
||||
" 536,\n",
|
||||
" 1084,\n",
|
||||
" 400,\n",
|
||||
" 1232,\n",
|
||||
" 1118,\n",
|
||||
" 582,\n",
|
||||
" 354,\n",
|
||||
" 730,\n",
|
||||
" 388,\n",
|
||||
" 342,\n",
|
||||
" 0,\n",
|
||||
" 878,\n",
|
||||
" 764,\n",
|
||||
" 730,\n",
|
||||
" 388,\n",
|
||||
" 1152,\n",
|
||||
" 354,\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 502, 594, 1278, 514, 400, 776, 1004, 468, 810, 536, 878, 0, 114,\n",
|
||||
" 308, 650, 274, 844\n",
|
||||
" 502,\n",
|
||||
" 594,\n",
|
||||
" 1278,\n",
|
||||
" 514,\n",
|
||||
" 400,\n",
|
||||
" 776,\n",
|
||||
" 1004,\n",
|
||||
" 468,\n",
|
||||
" 810,\n",
|
||||
" 536,\n",
|
||||
" 878,\n",
|
||||
" 0,\n",
|
||||
" 114,\n",
|
||||
" 308,\n",
|
||||
" 650,\n",
|
||||
" 274,\n",
|
||||
" 844,\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 388, 480, 1164, 628, 514, 662, 890, 354, 696, 422, 764, 114, 0, 194,\n",
|
||||
" 536, 388, 730\n",
|
||||
" 388,\n",
|
||||
" 480,\n",
|
||||
" 1164,\n",
|
||||
" 628,\n",
|
||||
" 514,\n",
|
||||
" 662,\n",
|
||||
" 890,\n",
|
||||
" 354,\n",
|
||||
" 696,\n",
|
||||
" 422,\n",
|
||||
" 764,\n",
|
||||
" 114,\n",
|
||||
" 0,\n",
|
||||
" 194,\n",
|
||||
" 536,\n",
|
||||
" 388,\n",
|
||||
" 730,\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 354, 674, 1130, 822, 708, 628, 856, 320, 662, 388, 730, 308, 194, 0,\n",
|
||||
" 342, 422, 536\n",
|
||||
" 354,\n",
|
||||
" 674,\n",
|
||||
" 1130,\n",
|
||||
" 822,\n",
|
||||
" 708,\n",
|
||||
" 628,\n",
|
||||
" 856,\n",
|
||||
" 320,\n",
|
||||
" 662,\n",
|
||||
" 388,\n",
|
||||
" 730,\n",
|
||||
" 308,\n",
|
||||
" 194,\n",
|
||||
" 0,\n",
|
||||
" 342,\n",
|
||||
" 422,\n",
|
||||
" 536,\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 468, 1016, 788, 1164, 1050, 514, 514, 662, 320, 274, 388, 650, 536,\n",
|
||||
" 342, 0, 764, 194\n",
|
||||
" 468,\n",
|
||||
" 1016,\n",
|
||||
" 788,\n",
|
||||
" 1164,\n",
|
||||
" 1050,\n",
|
||||
" 514,\n",
|
||||
" 514,\n",
|
||||
" 662,\n",
|
||||
" 320,\n",
|
||||
" 274,\n",
|
||||
" 388,\n",
|
||||
" 650,\n",
|
||||
" 536,\n",
|
||||
" 342,\n",
|
||||
" 0,\n",
|
||||
" 764,\n",
|
||||
" 194,\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 776, 868, 1552, 560, 674, 1050, 1278, 742, 1084, 810, 1152, 274,\n",
|
||||
" 388, 422, 764, 0, 798\n",
|
||||
" 776,\n",
|
||||
" 868,\n",
|
||||
" 1552,\n",
|
||||
" 560,\n",
|
||||
" 674,\n",
|
||||
" 1050,\n",
|
||||
" 1278,\n",
|
||||
" 742,\n",
|
||||
" 1084,\n",
|
||||
" 810,\n",
|
||||
" 1152,\n",
|
||||
" 274,\n",
|
||||
" 388,\n",
|
||||
" 422,\n",
|
||||
" 764,\n",
|
||||
" 0,\n",
|
||||
" 798,\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 662, 1210, 754, 1358, 1244, 708, 480, 856, 514, 468, 354, 844, 730,\n",
|
||||
" 536, 194, 798, 0\n",
|
||||
" 662,\n",
|
||||
" 1210,\n",
|
||||
" 754,\n",
|
||||
" 1358,\n",
|
||||
" 1244,\n",
|
||||
" 708,\n",
|
||||
" 480,\n",
|
||||
" 856,\n",
|
||||
" 514,\n",
|
||||
" 468,\n",
|
||||
" 354,\n",
|
||||
" 844,\n",
|
||||
" 730,\n",
|
||||
" 536,\n",
|
||||
" 194,\n",
|
||||
" 798,\n",
|
||||
" 0,\n",
|
||||
" ],\n",
|
||||
" ]\n",
|
||||
" assert len(data['providers_x']) == len(data['distance_matrix'])\n",
|
||||
" assert len(data['providers_y']) == len(data['distance_matrix'])\n",
|
||||
" assert len(data[\"providers_x\"]) == len(data[\"distance_matrix\"])\n",
|
||||
" assert len(data[\"providers_y\"]) == len(data[\"distance_matrix\"])\n",
|
||||
" return data\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def print_solution(data, manager, routing, assignment):\n",
|
||||
" \"\"\"Prints assignment on console.\"\"\"\n",
|
||||
" print(f'Objective: {assignment.ObjectiveValue()}')\n",
|
||||
" print(f\"Objective: {assignment.ObjectiveValue()}\")\n",
|
||||
" # Display dropped nodes.\n",
|
||||
" dropped_nodes = 'Dropped nodes:'\n",
|
||||
" dropped_nodes = \"Dropped nodes:\"\n",
|
||||
" for node in range(routing.Size()):\n",
|
||||
" if routing.IsStart(node) or routing.IsEnd(node):\n",
|
||||
" continue\n",
|
||||
" if assignment.Value(routing.NextVar(node)) == node:\n",
|
||||
" dropped_nodes += f' {manager.IndexToNode(node)}'\n",
|
||||
" dropped_nodes += f\" {manager.IndexToNode(node)}\"\n",
|
||||
" print(dropped_nodes)\n",
|
||||
" # Display routes\n",
|
||||
" total_distance = 0\n",
|
||||
" total_load_x = 0\n",
|
||||
" total_load_y = 0\n",
|
||||
" for vehicle_id in range(manager.GetNumberOfVehicles()):\n",
|
||||
" if not routing.IsVehicleUsed(assignment, vehicle_id):\n",
|
||||
" continue\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = f'Route for vehicle {vehicle_id}:\\n'\n",
|
||||
" plan_output = f\"Route for vehicle {vehicle_id}:\\n\"\n",
|
||||
" route_distance = 0\n",
|
||||
" route_load_x = 0\n",
|
||||
" route_load_y = 0\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
" node_index = manager.IndexToNode(index)\n",
|
||||
" route_load_x += data['providers_x'][node_index]\n",
|
||||
" route_load_y += data['providers_y'][node_index]\n",
|
||||
" plan_output += f' {node_index} Load(X:{route_load_x}, Y:{route_load_y}) -> '\n",
|
||||
" route_load_x += data[\"providers_x\"][node_index]\n",
|
||||
" route_load_y += data[\"providers_y\"][node_index]\n",
|
||||
" plan_output += f\" {node_index} Load(X:{route_load_x}, Y:{route_load_y}) -> \"\n",
|
||||
" previous_index = index\n",
|
||||
" previous_node_index = node_index\n",
|
||||
" index = assignment.Value(routing.NextVar(index))\n",
|
||||
" node_index = manager.IndexToNode(index)\n",
|
||||
" #route_distance += routing.GetArcCostForVehicle(previous_index, index, vehicle_id)\n",
|
||||
" route_distance += data['distance_matrix'][previous_node_index][node_index]\n",
|
||||
" # route_distance += routing.GetArcCostForVehicle(previous_index, index, vehicle_id)\n",
|
||||
" route_distance += data[\"distance_matrix\"][previous_node_index][node_index]\n",
|
||||
" node_index = manager.IndexToNode(index)\n",
|
||||
" plan_output += f' {node_index} Load({route_load_x}, {route_load_y})\\n'\n",
|
||||
" plan_output += f'Distance of the route: {route_distance}m\\n'\n",
|
||||
" plan_output += f'Load of the route: X:{route_load_x}, Y:{route_load_y}\\n'\n",
|
||||
" plan_output += f\" {node_index} Load({route_load_x}, {route_load_y})\\n\"\n",
|
||||
" plan_output += f\"Distance of the route: {route_distance}m\\n\"\n",
|
||||
" plan_output += f\"Load of the route: X:{route_load_x}, Y:{route_load_y}\\n\"\n",
|
||||
" print(plan_output)\n",
|
||||
" total_distance += route_distance\n",
|
||||
" total_load_x += route_load_x\n",
|
||||
" total_load_y += route_load_y\n",
|
||||
" print(f'Total Distance of all routes: {total_distance}m')\n",
|
||||
" print(f'Total load of all routes: X:{total_load_x}, Y:{total_load_y}')\n",
|
||||
" print(f\"Total Distance of all routes: {total_distance}m\")\n",
|
||||
" print(f\"Total load of all routes: X:{total_load_x}, Y:{total_load_y}\")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def main():\n",
|
||||
@@ -275,9 +532,12 @@
|
||||
" data = create_data_model()\n",
|
||||
"\n",
|
||||
" # Create the routing index manager.\n",
|
||||
" manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),\n",
|
||||
" data['num_vehicles'], data['starts'],\n",
|
||||
" data['ends'])\n",
|
||||
" manager = pywrapcp.RoutingIndexManager(\n",
|
||||
" len(data[\"distance_matrix\"]),\n",
|
||||
" data[\"num_vehicles\"],\n",
|
||||
" data[\"starts\"],\n",
|
||||
" data[\"ends\"],\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" # Create Routing Model.\n",
|
||||
" routing = pywrapcp.RoutingModel(manager)\n",
|
||||
@@ -289,7 +549,7 @@
|
||||
" # Convert from routing variable Index to distance matrix NodeIndex.\n",
|
||||
" from_node = manager.IndexToNode(from_index)\n",
|
||||
" to_node = manager.IndexToNode(to_index)\n",
|
||||
" return data['distance_matrix'][from_node][to_node]\n",
|
||||
" return data[\"distance_matrix\"][from_node][to_node]\n",
|
||||
"\n",
|
||||
" transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n",
|
||||
"\n",
|
||||
@@ -297,13 +557,14 @@
|
||||
" routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n",
|
||||
"\n",
|
||||
" # Add Distance constraint.\n",
|
||||
" dimension_name = 'Distance'\n",
|
||||
" dimension_name = \"Distance\"\n",
|
||||
" routing.AddDimension(\n",
|
||||
" transit_callback_index,\n",
|
||||
" 0, # no slack\n",
|
||||
" 2000, # vehicle maximum travel distance\n",
|
||||
" True, # start cumul to zero\n",
|
||||
" dimension_name)\n",
|
||||
" dimension_name,\n",
|
||||
" )\n",
|
||||
" distance_dimension = routing.GetDimensionOrDie(dimension_name)\n",
|
||||
" # Minimize the longest road\n",
|
||||
" distance_dimension.SetGlobalSpanCostCoefficient(100)\n",
|
||||
@@ -314,63 +575,67 @@
|
||||
" \"\"\"Returns the demand of the node.\"\"\"\n",
|
||||
" # Convert from routing variable Index to demands NodeIndex.\n",
|
||||
" from_node = manager.IndexToNode(from_index)\n",
|
||||
" return data['providers_x'][from_node]\n",
|
||||
" return data[\"providers_x\"][from_node]\n",
|
||||
"\n",
|
||||
" demand_callback_x_index = routing.RegisterUnaryTransitCallback(\n",
|
||||
" demand_callback_x)\n",
|
||||
" demand_callback_x_index = routing.RegisterUnaryTransitCallback(demand_callback_x)\n",
|
||||
" routing.AddDimensionWithVehicleCapacity(\n",
|
||||
" demand_callback_x_index,\n",
|
||||
" 0, # null capacity slack\n",
|
||||
" data['vehicle_capacities_x'], # vehicle maximum capacities\n",
|
||||
" data[\"vehicle_capacities_x\"], # vehicle maximum capacities\n",
|
||||
" True, # start cumul to zero\n",
|
||||
" 'Load_x')\n",
|
||||
" \"Load_x\",\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" def demand_callback_y(from_index):\n",
|
||||
" \"\"\"Returns the demand of the node.\"\"\"\n",
|
||||
" # Convert from routing variable Index to demands NodeIndex.\n",
|
||||
" from_node = manager.IndexToNode(from_index)\n",
|
||||
" return data['providers_y'][from_node]\n",
|
||||
" return data[\"providers_y\"][from_node]\n",
|
||||
"\n",
|
||||
" demand_callback_y_index = routing.RegisterUnaryTransitCallback(\n",
|
||||
" demand_callback_y)\n",
|
||||
" demand_callback_y_index = routing.RegisterUnaryTransitCallback(demand_callback_y)\n",
|
||||
" routing.AddDimensionWithVehicleCapacity(\n",
|
||||
" demand_callback_y_index,\n",
|
||||
" 0, # null capacity slack\n",
|
||||
" data['vehicle_capacities_y'], # vehicle maximum capacities\n",
|
||||
" data[\"vehicle_capacities_y\"], # vehicle maximum capacities\n",
|
||||
" True, # start cumul to zero\n",
|
||||
" 'Load_y')\n",
|
||||
" \"Load_y\",\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" # Add constraint at end\n",
|
||||
" solver = routing.solver()\n",
|
||||
" load_x_dim = routing.GetDimensionOrDie('Load_x')\n",
|
||||
" load_y_dim = routing.GetDimensionOrDie('Load_y')\n",
|
||||
" load_x_dim = routing.GetDimensionOrDie(\"Load_x\")\n",
|
||||
" load_y_dim = routing.GetDimensionOrDie(\"Load_y\")\n",
|
||||
" ends = []\n",
|
||||
" for v in range(manager.GetNumberOfVehicles()):\n",
|
||||
" ends.append(routing.End(v))\n",
|
||||
"\n",
|
||||
" node_end = data['ends'][0]\n",
|
||||
" node_end = data[\"ends\"][0]\n",
|
||||
" solver.Add(\n",
|
||||
" solver.Sum([load_x_dim.CumulVar(l)\n",
|
||||
" for l in ends]) >= -data['providers_x'][node_end])\n",
|
||||
" solver.Sum([load_x_dim.CumulVar(l) for l in ends])\n",
|
||||
" >= -data[\"providers_x\"][node_end]\n",
|
||||
" )\n",
|
||||
" solver.Add(\n",
|
||||
" solver.Sum([load_y_dim.CumulVar(l)\n",
|
||||
" for l in ends]) >= -data['providers_y'][node_end])\n",
|
||||
" #solver.Add(load_y_dim.CumulVar(end) >= -data['providers_y'][node_end])\n",
|
||||
" solver.Sum([load_y_dim.CumulVar(l) for l in ends])\n",
|
||||
" >= -data[\"providers_y\"][node_end]\n",
|
||||
" )\n",
|
||||
" # solver.Add(load_y_dim.CumulVar(end) >= -data['providers_y'][node_end])\n",
|
||||
"\n",
|
||||
" # Allow to freely drop any nodes.\n",
|
||||
" penalty = 0\n",
|
||||
" for node in range(0, len(data['distance_matrix'])):\n",
|
||||
" if node not in data['starts'] and node not in data['ends']:\n",
|
||||
" for node in range(0, len(data[\"distance_matrix\"])):\n",
|
||||
" if node not in data[\"starts\"] and node not in data[\"ends\"]:\n",
|
||||
" routing.AddDisjunction([manager.NodeToIndex(node)], penalty)\n",
|
||||
"\n",
|
||||
" # Setting first solution heuristic.\n",
|
||||
" search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n",
|
||||
" search_parameters.first_solution_strategy = (\n",
|
||||
" routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n",
|
||||
" routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC\n",
|
||||
" )\n",
|
||||
" search_parameters.local_search_metaheuristic = (\n",
|
||||
" routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)\n",
|
||||
" routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH\n",
|
||||
" )\n",
|
||||
" # Sets a time limit; default is 100 milliseconds.\n",
|
||||
" #search_parameters.log_search = True\n",
|
||||
" # search_parameters.log_search = True\n",
|
||||
" search_parameters.time_limit.FromSeconds(1)\n",
|
||||
"\n",
|
||||
" # Solve the problem.\n",
|
||||
@@ -380,7 +645,7 @@
|
||||
" if solution:\n",
|
||||
" print_solution(data, manager, routing, solution)\n",
|
||||
" else:\n",
|
||||
" print('no solution found !')\n",
|
||||
" print(\"no solution found !\")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"main()\n",
|
||||
@@ -388,7 +653,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -91,6 +91,7 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_data_model():\n",
|
||||
" \"\"\"Stores the data for the problem.\"\"\"\n",
|
||||
" data = {}\n",
|
||||
@@ -149,6 +150,8 @@
|
||||
" dim_two = routing.GetDimensionOrDie(\"Two\")\n",
|
||||
"\n",
|
||||
" for vehicle_id in range(data[\"num_vehicles\"]):\n",
|
||||
" if not routing.IsVehicleUsed(solution, vehicle_id):\n",
|
||||
" continue\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = f\"Route for vehicle {vehicle_id}:\\n\"\n",
|
||||
" route_distance = 0\n",
|
||||
@@ -315,7 +318,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -78,11 +78,15 @@
|
||||
"the relation between nodes and indices.\n",
|
||||
"\n",
|
||||
"Things to notice:\n",
|
||||
"* Since we have two duplicates (node 5 and node 4) solver need 2 extra indices to have an unique index for each vehicle start/stop and locations.\n",
|
||||
"* Solver needs to \"create\" an index for a vehicle 1 start since solver need an unique start index per vehicle.\n",
|
||||
"* Since we have two duplicates (node 5 and node 4) solver need 2 extra indices\n",
|
||||
"to have an unique index for each vehicle start/stop and locations.\n",
|
||||
"* Solver needs to \"create\" an index for a vehicle 1 start since solver need an\n",
|
||||
"unique start index per vehicle.\n",
|
||||
"* All end nodes are moved to the end of the index list aka [15, 16, 17, 18].\n",
|
||||
"* routing.Size() return the number of node which are not end nodes (here 15 aka [0-14])\n",
|
||||
"note: using the two properties above, we know that any index in range(routing.Size()) is not a vehicle end node.\n",
|
||||
"* routing.Size() return the number of node which are not end nodes (here 15 aka\n",
|
||||
"[0-14])\n",
|
||||
"note: using the two properties above, we know that any index in\n",
|
||||
"range(routing.Size()) is not a vehicle end node.\n",
|
||||
"\n",
|
||||
"* Since end nodes are moved to the end, their respective \"empty\" node index are\n",
|
||||
"reused so all locations indices are \"shifted\"\n",
|
||||
@@ -91,9 +95,11 @@
|
||||
"e.g. start node 7 mapped to index 4\n",
|
||||
"\n",
|
||||
"Takeaway:\n",
|
||||
"* Allways use routing.Start(), routing.End(), manager.IndexToNode() or manager.NodeToIndex().\n",
|
||||
"* Allways use routing.Start(), routing.End(), manager.IndexToNode() or\n",
|
||||
"manager.NodeToIndex().\n",
|
||||
"* Location node is not necessarily equal to its index.\n",
|
||||
"* To loop through ALL indices use manager.GetNumberOfIndices() (Python) or manager::num_indices() (C++)\n",
|
||||
"* To loop through ALL indices use manager.GetNumberOfIndices() (Python) or\n",
|
||||
"manager::num_indices() (C++)\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
@@ -119,57 +125,61 @@
|
||||
" manager = pywrapcp.RoutingIndexManager(locations, vehicles, starts, ends)\n",
|
||||
" routing = pywrapcp.RoutingModel(manager)\n",
|
||||
"\n",
|
||||
" print('Starts/Ends:')\n",
|
||||
" header = '| |'\n",
|
||||
" separator = '|---|'\n",
|
||||
" v_starts = '| start |'\n",
|
||||
" v_ends = '| end |'\n",
|
||||
" print(\"Starts/Ends:\")\n",
|
||||
" header = \"| |\"\n",
|
||||
" separator = \"|---|\"\n",
|
||||
" v_starts = \"| start |\"\n",
|
||||
" v_ends = \"| end |\"\n",
|
||||
" for v in range(manager.GetNumberOfVehicles()):\n",
|
||||
" header += f' vehicle {v} |'\n",
|
||||
" separator += '---|'\n",
|
||||
" v_starts += f' {starts[v]} |'\n",
|
||||
" v_ends += f' {ends[v]} |'\n",
|
||||
" header += f\" vehicle {v} |\"\n",
|
||||
" separator += \"---|\"\n",
|
||||
" v_starts += f\" {starts[v]} |\"\n",
|
||||
" v_ends += f\" {ends[v]} |\"\n",
|
||||
" print(header)\n",
|
||||
" print(separator)\n",
|
||||
" print(v_starts)\n",
|
||||
" print(v_ends)\n",
|
||||
"\n",
|
||||
" print('\\nNodes:')\n",
|
||||
" print(\"\\nNodes:\")\n",
|
||||
" print(\n",
|
||||
" '| locations | manager.GetNumberOfNodes | manager.GetNumberOfIndices | routing.nodes | routing.Size |'\n",
|
||||
" \"| locations | manager.GetNumberOfNodes | manager.GetNumberOfIndices |\"\n",
|
||||
" \" routing.nodes | routing.Size |\"\n",
|
||||
" )\n",
|
||||
" print('|---|---|---|---|---|')\n",
|
||||
" print(\"|---|---|---|---|---|\")\n",
|
||||
" print(\n",
|
||||
" f'| {locations} | {manager.GetNumberOfNodes()} | {manager.GetNumberOfIndices()} | {routing.nodes()} | {routing.Size()} |'\n",
|
||||
" f\"| {locations} | {manager.GetNumberOfNodes()} |\"\n",
|
||||
" f\" {manager.GetNumberOfIndices()} | {routing.nodes()} |\"\n",
|
||||
" f\" {routing.Size()} |\"\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" print('\\nLocations:')\n",
|
||||
" print('| node | index | routing.IsStart | routing.IsEnd |')\n",
|
||||
" print('|---|---|---|---|')\n",
|
||||
" print(\"\\nLocations:\")\n",
|
||||
" print(\"| node | index | routing.IsStart | routing.IsEnd |\")\n",
|
||||
" print(\"|---|---|---|---|\")\n",
|
||||
" for node in range(manager.GetNumberOfNodes()):\n",
|
||||
" if node in starts or node in ends:\n",
|
||||
" continue\n",
|
||||
" index = manager.NodeToIndex(node)\n",
|
||||
" print(\n",
|
||||
" f'| {node} | {index} | {routing.IsStart(index)} | {routing.IsEnd(index)} |'\n",
|
||||
" f\"| {node} | {index} | {routing.IsStart(index)} |\"\n",
|
||||
" f\" {routing.IsEnd(index)} |\"\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" print('\\nStart/End:')\n",
|
||||
" print(\n",
|
||||
" '| vehicle | Start/end | node | index | routing.IsStart | routing.IsEnd |'\n",
|
||||
" )\n",
|
||||
" print('|---|---|---|---|---|---|')\n",
|
||||
" print(\"\\nStart/End:\")\n",
|
||||
" print(\"| vehicle | Start/end | node | index | routing.IsStart | routing.IsEnd |\")\n",
|
||||
" print(\"|---|---|---|---|---|---|\")\n",
|
||||
" for v in range(manager.GetNumberOfVehicles()):\n",
|
||||
" start_index = routing.Start(v)\n",
|
||||
" start_node = manager.IndexToNode(start_index)\n",
|
||||
" print(\n",
|
||||
" f'| {v} | start | {start_node} | {start_index} | {routing.IsStart(start_index)} | {routing.IsEnd(start_index)} |'\n",
|
||||
" f\"| {v} | start | {start_node} | {start_index} |\"\n",
|
||||
" f\" {routing.IsStart(start_index)} | {routing.IsEnd(start_index)} |\"\n",
|
||||
" )\n",
|
||||
" for v in range(manager.GetNumberOfVehicles()):\n",
|
||||
" end_index = routing.End(v)\n",
|
||||
" end_node = manager.IndexToNode(end_index)\n",
|
||||
" print(\n",
|
||||
" f'| {v} | end | {end_node} | {end_index} | {routing.IsStart(end_index)} | {routing.IsEnd(end_index)} |'\n",
|
||||
" f\"| {v} | end | {end_node} | {end_index} |\"\n",
|
||||
" f\" {routing.IsStart(end_index)} | {routing.IsEnd(end_index)} |\"\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
"\n",
|
||||
@@ -178,7 +188,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -87,6 +87,7 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_data_model():\n",
|
||||
" \"\"\"Stores the data for the problem.\"\"\"\n",
|
||||
" data = {}\n",
|
||||
@@ -131,6 +132,8 @@
|
||||
" print(f\"Objective: {solution.ObjectiveValue()}\")\n",
|
||||
" total_distance = 0\n",
|
||||
" for vehicle_id in range(data[\"num_vehicles\"]):\n",
|
||||
" if not routing.IsVehicleUsed(solution, vehicle_id):\n",
|
||||
" continue\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = f\"Route for vehicle {vehicle_id}:\\n\"\n",
|
||||
" route_distance = 0\n",
|
||||
@@ -217,7 +220,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -87,6 +87,7 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_data_model():\n",
|
||||
" \"\"\"Stores the data for the problem.\"\"\"\n",
|
||||
" data = {}\n",
|
||||
@@ -131,6 +132,8 @@
|
||||
" print(f\"Objective: {assignment.ObjectiveValue()}\")\n",
|
||||
" total_distance = 0\n",
|
||||
" for vehicle_id in range(data[\"num_vehicles\"]):\n",
|
||||
" if not routing.IsVehicleUsed(assignment, vehicle_id):\n",
|
||||
" continue\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = f\"Route for vehicle {vehicle_id}:\\n\"\n",
|
||||
" route_distance = 0\n",
|
||||
@@ -220,7 +223,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -87,6 +87,7 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_data_model():\n",
|
||||
" \"\"\"Stores the data for the problem.\"\"\"\n",
|
||||
" data = {}\n",
|
||||
@@ -131,6 +132,8 @@
|
||||
" print(f\"Objective: {assignment.ObjectiveValue()}\")\n",
|
||||
" total_distance = 0\n",
|
||||
" for vehicle_id in range(data[\"num_vehicles\"]):\n",
|
||||
" if not routing.IsVehicleUsed(assignment, vehicle_id):\n",
|
||||
" continue\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = f\"Route for vehicle {vehicle_id}:\\n\"\n",
|
||||
" route_distance = 0\n",
|
||||
@@ -220,7 +223,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -87,6 +87,7 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_data_model():\n",
|
||||
" \"\"\"Stores the data for the problem.\"\"\"\n",
|
||||
" data = {}\n",
|
||||
@@ -142,6 +143,8 @@
|
||||
" time_dimension = routing.GetDimensionOrDie(\"Time\")\n",
|
||||
" total_time = 0\n",
|
||||
" for vehicle_id in range(data[\"num_vehicles\"]):\n",
|
||||
" if not routing.IsVehicleUsed(solution, vehicle_id):\n",
|
||||
" continue\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = f\"Route for vehicle {vehicle_id}:\\n\"\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
@@ -266,7 +269,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -75,12 +75,12 @@
|
||||
"\n",
|
||||
"Simple Vehicles Routing Problem (VRP).\n",
|
||||
"\n",
|
||||
" This is a sample using the routing library python wrapper to solve a VRP\n",
|
||||
" problem.\n",
|
||||
"This is a sample using the routing library python wrapper to solve a VRP\n",
|
||||
"problem.\n",
|
||||
"\n",
|
||||
" The solver stop after improving its solution 15 times or after 5 seconds.\n",
|
||||
"The solver stop after improving its solution 15 times or after 5 seconds.\n",
|
||||
"\n",
|
||||
" Distances are in meters.\n",
|
||||
"Distances are in meters.\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
@@ -97,6 +97,7 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_data_model():\n",
|
||||
" \"\"\"Stores the data for the problem.\"\"\"\n",
|
||||
" data = {}\n",
|
||||
@@ -135,6 +136,8 @@
|
||||
" total_distance = 0\n",
|
||||
" for vehicle_id in range(routing_manager.GetNumberOfVehicles()):\n",
|
||||
" index = routing_model.Start(vehicle_id)\n",
|
||||
" if routing_model.IsEnd(routing_model.NextVar(index).Value()):\n",
|
||||
" continue\n",
|
||||
" plan_output = f\"Route for vehicle {vehicle_id}:\\n\"\n",
|
||||
" route_distance = 0\n",
|
||||
" while not routing_model.IsEnd(index):\n",
|
||||
@@ -169,7 +172,9 @@
|
||||
" self.objectives = []\n",
|
||||
"\n",
|
||||
" def __call__(self):\n",
|
||||
" objective = int(self._routing_model_ref().CostVar().Value())\n",
|
||||
" objective = int(\n",
|
||||
" self._routing_model_ref().CostVar().Value()\n",
|
||||
" ) # pytype: disable=attribute-error\n",
|
||||
" if not self.objectives or objective < self.objectives[-1]:\n",
|
||||
" self.objectives.append(objective)\n",
|
||||
" print_solution(self._routing_manager_ref(), self._routing_model_ref())\n",
|
||||
@@ -179,6 +184,7 @@
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def main():\n",
|
||||
" \"\"\"Entry point of the program.\"\"\"\n",
|
||||
" # Instantiate the data problem.\n",
|
||||
@@ -247,7 +253,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -87,6 +87,7 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_data_model():\n",
|
||||
" \"\"\"Stores the data for the problem.\"\"\"\n",
|
||||
" data = {}\n",
|
||||
@@ -122,6 +123,8 @@
|
||||
" print(f\"Objective: {solution.ObjectiveValue()}\")\n",
|
||||
" max_route_distance = 0\n",
|
||||
" for vehicle_id in range(data[\"num_vehicles\"]):\n",
|
||||
" if not routing.IsVehicleUsed(solution, vehicle_id):\n",
|
||||
" continue\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = f\"Route for vehicle {vehicle_id}:\\n\"\n",
|
||||
" route_distance = 0\n",
|
||||
@@ -196,7 +199,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -87,6 +87,7 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_data_model():\n",
|
||||
" \"\"\"Stores the data for the problem.\"\"\"\n",
|
||||
" data = {}\n",
|
||||
@@ -139,6 +140,8 @@
|
||||
" time_dimension = routing.GetDimensionOrDie(\"Time\")\n",
|
||||
" total_time = 0\n",
|
||||
" for vehicle_id in range(data[\"num_vehicles\"]):\n",
|
||||
" if not routing.IsVehicleUsed(solution, vehicle_id):\n",
|
||||
" continue\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = f\"Route for vehicle {vehicle_id}:\\n\"\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
@@ -236,7 +239,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -74,19 +74,19 @@
|
||||
"source": [
|
||||
"Vehicles Routing Problem (VRP) with Time Window (TW) per vehicle.\n",
|
||||
"\n",
|
||||
" All time are in minutes using 0am as origin\n",
|
||||
" e.g. 8am = 480, 11am = 660, 1pm = 780 ...\n",
|
||||
"All time are in minutes using 0am as origin\n",
|
||||
"e.g. 8am = 480, 11am = 660, 1pm = 780 ...\n",
|
||||
"\n",
|
||||
" We have 1 depot (0) and 16 locations (1-16).\n",
|
||||
" We have a fleet of 4 vehicles (0-3) whose working time is [480, 1020] (8am-5pm)\n",
|
||||
" We have the distance matrix between these locations and depot.\n",
|
||||
" We have a service time of 25min at each location.\n",
|
||||
"We have 1 depot (0) and 16 locations (1-16).\n",
|
||||
"We have a fleet of 4 vehicles (0-3) whose working time is [480, 1020] (8am-5pm)\n",
|
||||
"We have the distance matrix between these locations and depot.\n",
|
||||
"We have a service time of 25min at each location.\n",
|
||||
"\n",
|
||||
" Locations are duplicated so we can simulate a TW per vehicle.\n",
|
||||
" location: [01-16] vehicle: 0 TW: [540, 660] (9am-11am)\n",
|
||||
" location: [17-32] vehicle: 1 TW: [660, 780] (11am-1pm)\n",
|
||||
" location: [33-48] vehicle: 2 TW: [780, 900] (1pm-3pm)\n",
|
||||
" location: [49-64] vehicle: 3 TW: [900, 1020] (3pm-5pm)\n",
|
||||
"Locations are duplicated so we can simulate a TW per vehicle.\n",
|
||||
"location: [01-16] vehicle: 0 TW: [540, 660] (9am-11am)\n",
|
||||
"location: [17-32] vehicle: 1 TW: [660, 780] (11am-1pm)\n",
|
||||
"location: [33-48] vehicle: 2 TW: [780, 900] (1pm-3pm)\n",
|
||||
"location: [49-64] vehicle: 3 TW: [900, 1020] (3pm-5pm)\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
@@ -101,10 +101,11 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_data_model():\n",
|
||||
" \"\"\"Stores the data for the problem.\"\"\"\n",
|
||||
" data = {}\n",
|
||||
" data['time_matrix'] = [\n",
|
||||
" data[\"time_matrix\"] = [\n",
|
||||
" [0, 6, 9, 8, 7, 3, 6, 2, 3, 2, 6, 6, 4, 4, 5, 9, 7],\n",
|
||||
" [6, 0, 8, 3, 2, 6, 8, 4, 8, 8, 13, 7, 5, 8, 12, 10, 14],\n",
|
||||
" [9, 8, 0, 11, 10, 6, 3, 9, 5, 8, 4, 15, 14, 13, 9, 18, 9],\n",
|
||||
@@ -123,16 +124,16 @@
|
||||
" [9, 10, 18, 6, 8, 12, 15, 8, 13, 9, 13, 3, 4, 5, 9, 0, 9],\n",
|
||||
" [7, 14, 9, 16, 14, 8, 5, 10, 6, 5, 4, 10, 8, 6, 2, 9, 0],\n",
|
||||
" ]\n",
|
||||
" data['num_vehicles'] = 4\n",
|
||||
" data['depot'] = 0\n",
|
||||
" data[\"num_vehicles\"] = 4\n",
|
||||
" data[\"depot\"] = 0\n",
|
||||
" return data\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def print_solution(manager, routing, assignment):\n",
|
||||
" \"\"\"Prints solution on console.\"\"\"\n",
|
||||
" print(f'Objective: {assignment.ObjectiveValue()}')\n",
|
||||
" print(f\"Objective: {assignment.ObjectiveValue()}\")\n",
|
||||
" # Display dropped nodes.\n",
|
||||
" dropped_nodes = 'Dropped nodes:'\n",
|
||||
" dropped_nodes = \"Dropped nodes:\"\n",
|
||||
" for index in range(routing.Size()):\n",
|
||||
" if routing.IsStart(index) or routing.IsEnd(index):\n",
|
||||
" continue\n",
|
||||
@@ -142,15 +143,17 @@
|
||||
" original = node\n",
|
||||
" while original > 16:\n",
|
||||
" original = original - 16\n",
|
||||
" dropped_nodes += f' {node}({original})'\n",
|
||||
" dropped_nodes += f\" {node}({original})\"\n",
|
||||
" else:\n",
|
||||
" dropped_nodes += f' {node}'\n",
|
||||
" dropped_nodes += f\" {node}\"\n",
|
||||
" print(dropped_nodes)\n",
|
||||
" # Display routes\n",
|
||||
" time_dimension = routing.GetDimensionOrDie('Time')\n",
|
||||
" time_dimension = routing.GetDimensionOrDie(\"Time\")\n",
|
||||
" total_time = 0\n",
|
||||
" for vehicle_id in range(manager.GetNumberOfVehicles()):\n",
|
||||
" plan_output = f'Route for vehicle {vehicle_id}:\\n'\n",
|
||||
" if not routing.IsVehicleUsed(assignment, vehicle_id):\n",
|
||||
" continue\n",
|
||||
" plan_output = f\"Route for vehicle {vehicle_id}:\\n\"\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" start_time = 0\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
@@ -160,22 +163,22 @@
|
||||
" original = node\n",
|
||||
" while original > 16:\n",
|
||||
" original = original - 16\n",
|
||||
" plan_output += f'{node}({original})'\n",
|
||||
" plan_output += f\"{node}({original})\"\n",
|
||||
" else:\n",
|
||||
" plan_output += f'{node}'\n",
|
||||
" plan_output += f' Time:{assignment.Value(time_var)} -> '\n",
|
||||
" plan_output += f\"{node}\"\n",
|
||||
" plan_output += f\" Time:{assignment.Value(time_var)} -> \"\n",
|
||||
" if start_time == 0:\n",
|
||||
" start_time = assignment.Value(time_var)\n",
|
||||
" index = assignment.Value(routing.NextVar(index))\n",
|
||||
" time_var = time_dimension.CumulVar(index)\n",
|
||||
" node = manager.IndexToNode(index)\n",
|
||||
" plan_output += f'{node} Time:{assignment.Value(time_var)}\\n'\n",
|
||||
" plan_output += f\"{node} Time:{assignment.Value(time_var)}\\n\"\n",
|
||||
" end_time = assignment.Value(time_var)\n",
|
||||
" duration = end_time - start_time\n",
|
||||
" plan_output += f'Duration of the route:{duration}min\\n'\n",
|
||||
" plan_output += f\"Duration of the route:{duration}min\\n\"\n",
|
||||
" print(plan_output)\n",
|
||||
" total_time += duration\n",
|
||||
" print(f'Total duration of all routes: {total_time}min')\n",
|
||||
" print(f\"Total duration of all routes: {total_time}min\")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def main():\n",
|
||||
@@ -185,9 +188,8 @@
|
||||
"\n",
|
||||
" # Create the routing index manager.\n",
|
||||
" manager = pywrapcp.RoutingIndexManager(\n",
|
||||
" 1 + 16 * 4, # number of locations\n",
|
||||
" data['num_vehicles'],\n",
|
||||
" data['depot'])\n",
|
||||
" 1 + 16 * 4, data[\"num_vehicles\"], data[\"depot\"] # number of locations\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" # Create Routing Model.\n",
|
||||
" routing = pywrapcp.RoutingModel(manager)\n",
|
||||
@@ -207,9 +209,9 @@
|
||||
" to_node = to_node - 16\n",
|
||||
" # add service of 25min for each location (except depot)\n",
|
||||
" service_time = 0\n",
|
||||
" if from_node != data['depot']:\n",
|
||||
" if from_node != data[\"depot\"]:\n",
|
||||
" service_time = 25\n",
|
||||
" return data['time_matrix'][from_node][to_node] + service_time\n",
|
||||
" return data[\"time_matrix\"][from_node][to_node] + service_time\n",
|
||||
"\n",
|
||||
" transit_callback_index = routing.RegisterTransitCallback(time_callback)\n",
|
||||
"\n",
|
||||
@@ -217,17 +219,18 @@
|
||||
" routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n",
|
||||
"\n",
|
||||
" # Add Time Windows constraint.\n",
|
||||
" time = 'Time'\n",
|
||||
" time = \"Time\"\n",
|
||||
" routing.AddDimension(\n",
|
||||
" transit_callback_index,\n",
|
||||
" 0, # allow waiting time (0 min)\n",
|
||||
" 1020, # maximum time per vehicle (9 hours)\n",
|
||||
" False, # Don't force start cumul to zero.\n",
|
||||
" time)\n",
|
||||
" time,\n",
|
||||
" )\n",
|
||||
" time_dimension = routing.GetDimensionOrDie(time)\n",
|
||||
" # Add time window constraints for each location except depot.\n",
|
||||
" for location_idx in range(17):\n",
|
||||
" if location_idx == data['depot']:\n",
|
||||
" if location_idx == data[\"depot\"]:\n",
|
||||
" continue\n",
|
||||
" # Vehicle 0 location TW: [9am, 11am]\n",
|
||||
" index_0 = manager.NodeToIndex(location_idx)\n",
|
||||
@@ -254,30 +257,32 @@
|
||||
" routing.AddDisjunction([index_0, index_1, index_2, index_3], penalty, 1)\n",
|
||||
"\n",
|
||||
" # Add time window constraints for each vehicle start node.\n",
|
||||
" depot_idx = data['depot']\n",
|
||||
" for vehicle_id in range(data['num_vehicles']):\n",
|
||||
" depot_idx = data[\"depot\"]\n",
|
||||
" for vehicle_id in range(data[\"num_vehicles\"]):\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" time_dimension.CumulVar(index).SetRange(480, 1020) # (8am, 5pm)\n",
|
||||
"\n",
|
||||
" # Add time window constraints for each vehicle end node.\n",
|
||||
" depot_idx = data['depot']\n",
|
||||
" for vehicle_id in range(data['num_vehicles']):\n",
|
||||
" depot_idx = data[\"depot\"]\n",
|
||||
" for vehicle_id in range(data[\"num_vehicles\"]):\n",
|
||||
" index = routing.End(vehicle_id)\n",
|
||||
" time_dimension.CumulVar(index).SetRange(480, 1020) # (8am, 5pm)\n",
|
||||
"\n",
|
||||
" # Instantiate route start and end times to produce feasible times.\n",
|
||||
" for i in range(data['num_vehicles']):\n",
|
||||
" for i in range(data[\"num_vehicles\"]):\n",
|
||||
" routing.AddVariableMinimizedByFinalizer(\n",
|
||||
" time_dimension.CumulVar(routing.Start(i)))\n",
|
||||
" routing.AddVariableMinimizedByFinalizer(\n",
|
||||
" time_dimension.CumulVar(routing.End(i)))\n",
|
||||
" time_dimension.CumulVar(routing.Start(i))\n",
|
||||
" )\n",
|
||||
" routing.AddVariableMinimizedByFinalizer(time_dimension.CumulVar(routing.End(i)))\n",
|
||||
"\n",
|
||||
" # Setting first solution heuristic.\n",
|
||||
" search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n",
|
||||
" search_parameters.first_solution_strategy = (\n",
|
||||
" routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n",
|
||||
" routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC\n",
|
||||
" )\n",
|
||||
" search_parameters.local_search_metaheuristic = (\n",
|
||||
" routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)\n",
|
||||
" routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH\n",
|
||||
" )\n",
|
||||
" search_parameters.time_limit.FromSeconds(1)\n",
|
||||
"\n",
|
||||
" # Solve the problem.\n",
|
||||
@@ -295,7 +300,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -87,6 +87,7 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_data_model():\n",
|
||||
" \"\"\"Stores the data for the problem.\"\"\"\n",
|
||||
" data = {}\n",
|
||||
@@ -126,6 +127,8 @@
|
||||
" total_distance = 0\n",
|
||||
" total_token = 0\n",
|
||||
" for vehicle_id in range(manager.GetNumberOfVehicles()):\n",
|
||||
" if not routing.IsVehicleUsed(solution, vehicle_id):\n",
|
||||
" continue\n",
|
||||
" plan_output = f\"Route for vehicle {vehicle_id}:\\n\"\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" total_token += solution.Value(token_dimension.CumulVar(index))\n",
|
||||
@@ -242,7 +245,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -87,11 +87,14 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def print_solution(manager, routing, solution):\n",
|
||||
" \"\"\"Prints solution on console.\"\"\"\n",
|
||||
" print(f\"Objective: {solution.ObjectiveValue()}\")\n",
|
||||
" max_route_distance = 0\n",
|
||||
" for vehicle_id in range(manager.GetNumberOfVehicles()):\n",
|
||||
" if not routing.IsVehicleUsed(solution, vehicle_id):\n",
|
||||
" continue\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = f\"Route for vehicle {vehicle_id}:\\n\"\n",
|
||||
" route_distance = 0\n",
|
||||
@@ -170,7 +173,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -87,6 +87,7 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_data_model():\n",
|
||||
" \"\"\"Stores the data for the problem.\"\"\"\n",
|
||||
" data = {}\n",
|
||||
@@ -139,6 +140,8 @@
|
||||
" total_time = 0\n",
|
||||
" route_str = \"\"\n",
|
||||
" for i, route in enumerate(routes):\n",
|
||||
" if len(route) <= 2:\n",
|
||||
" continue\n",
|
||||
" route_str += \"Route \" + str(i) + \":\\n\"\n",
|
||||
" start_time = cumul_data[i][0][0]\n",
|
||||
" end_time = cumul_data[i][0][1]\n",
|
||||
@@ -286,7 +289,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -234,7 +234,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -333,7 +333,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -236,7 +236,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -185,7 +185,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -195,7 +195,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -232,7 +232,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -193,7 +193,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -226,7 +226,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -167,7 +167,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -216,7 +216,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -209,7 +209,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -180,7 +180,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -209,7 +209,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -191,7 +191,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -201,7 +201,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -173,7 +173,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -195,7 +195,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -168,7 +168,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -211,7 +211,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -177,7 +177,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -245,7 +245,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -238,7 +238,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -211,7 +211,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -280,7 +280,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -265,7 +265,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -184,7 +184,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -206,7 +206,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -196,7 +196,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -264,7 +264,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -170,7 +170,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -180,7 +180,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -173,7 +173,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -234,7 +234,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -247,7 +247,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -120,7 +120,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -268,7 +268,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -262,7 +262,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -174,7 +174,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -185,7 +185,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -246,7 +246,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -245,7 +245,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -230,7 +230,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -180,7 +180,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -162,7 +162,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -284,7 +284,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -183,7 +183,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -248,7 +248,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -263,7 +263,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -258,7 +258,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -160,7 +160,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -171,7 +171,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -205,7 +205,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -182,7 +182,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -184,7 +184,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -164,7 +164,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -192,7 +192,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -122,7 +122,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -184,7 +184,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -180,7 +180,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -264,7 +264,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -173,7 +173,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -203,7 +203,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -189,7 +189,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -207,7 +207,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -300,7 +300,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "google",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2024 Google LLC."
|
||||
"##### Copyright 2025 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -189,7 +189,11 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user