summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMitsuo Tokumori <[email protected]>2022-05-06 03:11:18 -0500
committerMitsuo Tokumori <[email protected]>2022-05-06 03:11:18 -0500
commit9ac1b21b42571c0e8e3dee9619931a670f1a3c10 (patch)
tree1d8dcc5c828927f0bc291a0c146182a20382b25b
parenta7c5bec4705708eb87fb8d9a60b2868471ce702a (diff)
downloadVRPTW-ACO-python-master.tar.gz
VRPTW-ACO-python-master.tar.bz2
VRPTW-ACO-python-master.zip
Refactor some functions out of example1.pyHEADmaster
-rw-r--r--configOPP.py52
-rw-r--r--example1.py151
-rw-r--r--nodeOPP.py68
-rw-r--r--readerOPP.py75
4 files changed, 206 insertions, 140 deletions
diff --git a/configOPP.py b/configOPP.py
new file mode 100644
index 0000000..3caad8d
--- /dev/null
+++ b/configOPP.py
@@ -0,0 +1,52 @@
+"""
+Global Variables go here
+
+OPP = OdiParPack
+"""
+
+config = {
+ 'depot_num': 3, # number of depots
+ 'veh_types': { # Vehicle type properties (capacity)
+ 'typeA': 90,
+ 'typeB': 45,
+ 'typeC': 30
+ },
+ 'veh_fleet': { # Initial vehicle fleet locations
+ 'Lima': {
+ 'typeA': 4,
+ 'typeB': 7,
+ 'typeC': 10
+ },
+ 'Areq': {
+ 'typeA': 1,
+ 'typeB': 3,
+ 'typeC': 6
+ },
+ 'Truj': {
+ 'typeA': 1,
+ 'typeB': 5,
+ 'typeC': 8
+ }
+ },
+ 'veh_speed': { # Vehicle speed (depends on natural region) (km/h)
+ 'costa': {
+ 'costa': 70,
+ 'sierra': 50,
+ 'selva': 60 # temporal, no deberian haber tramos costa-selva
+ },
+ 'sierra': {
+ 'sierra': 60,
+ 'selva': 55
+ },
+ 'selva': {
+ 'selva': 65
+ }
+ },
+ 'veh_maint': {}, # Vehicle maintenance plans
+ 'veh_breakdown_downtime': { # Segun tipo de averia de vehiculos (minutes)
+ # TODO: double check if values are correct
+ 'moderada': 12 * 60,
+ 'fuerte': 72 * 60,
+ 'siniestro': 0
+ }
+}
diff --git a/example1.py b/example1.py
index fdacd9d..da01dd4 100644
--- a/example1.py
+++ b/example1.py
@@ -1,76 +1,17 @@
+"""
+Run project like this: $ python example1
+
+TODO: Read "raw" or preprocessed ventas data
+
+"""
+
from vrptw_base import VrptwGraph
from multiple_ant_colony_system import MultipleAntColonySystem
-import numpy as np
-import csv
import math
-import random
+import numpy as np
import networkx as nx
-import matplotlib.pyplot as plt
-
-
-class Node:
- """
- Attributes
- ----------
- index : int
- index
- ubigeo : str
- 6 digits
- lat : float
- Latitud (angulo de los Paralelos) en grados sexagesimales
- lon : float
- Longitud (angulo de los Meridianos) en grados sexagesimales
- is_depot : bool
- demand : int
- ready_time : float
- due_time : float
- service_time : float
- x : float
- Aproximacion local, en Km respecto
- y : float
- Aproximacion local, en Km respecto ("Lima")
-
- Notes
- -----
- Web Mercator projection (BAD):
-
- x = floor(256 / (2 * math.pi) * 2**(zoom_level) * (lon + math.pi))
- y = floor(265 / (2 * math.pi) * 2**(zoom_level) * (math.pi - math.ln(math.tan( math.pi / 4 + lat / 2 ))))
-
- x = R * lon
- y = R * ln(tan(pi/4 + lat/2)
-
- Both `lon` and `lat` in radians.
-
- "Lima": -12.04591952,-77.03049615 (lat, long)
- """
-
- def __init__(self, index: int, ubigeo, lat, lon, is_depot,
- demand, ready_time, due_time, service_time):
- super()
- self.index = index
- self.ubigeo = ubigeo
-
- if is_depot:
- self.is_depot = True
- else:
- self.is_depot = False
-
- earth_radius_km = 6371 # Avg. radius
- lima_lat = -12.04591952
- lima_lon = -77.03049615
-
- self.lat = lat
- self.lon = lon
- self.x = (lon - lima_lon) * (math.pi / 180) * earth_radius_km
- self.y = (lat - lima_lat) * (math.pi / 180) * earth_radius_km
- self.x = round(self.x, 3)
- self.y = round(self.y, 3)
- self.demand = demand
- self.ready_time = 0 # ready_time
- self.due_time = due_time
- self.service_time = service_time
+from readerOPP import read_nodes, read_tramos
def _deg2rad(degrees):
@@ -93,76 +34,6 @@ def distance_between_coordinates(lat1, lon1, lat2, lon2):
return earth_radius_km * c
-def _read_nodes(depot_num):
- """
- Read nodes from input file.
-
- Attributes
- ----------
- depot_num : int
- Number of depots
-
- Returns
- -------
- list
- List of Nodes. The first `depot_num` nodes are the depots.
- """
- depots = []
- no_depots = []
- with open('odiparpack/inf226.oficinas_mod.csv', newline='') as csvfile:
- orders = csv.reader(csvfile)
- count = 1
- index_customer = depot_num
- index_depot = 0
- for row in orders:
- if count == 1:
- count += 1
- continue
-
- ubigeo, dept, prov, lat, lon, region_natural, is_depot = row[:7]
- demand, ready_time, due_time, service_time = row[7:]
-
- n = Node(
- -1, ubigeo, float(lat), float(lon),
- int(is_depot),
- demand=float(demand), ready_time=0,
- due_time=float(due_time), service_time=60
- )
-
- if n.is_depot:
- n.index = index_depot
- depots.append(n)
- index_depot += 1
- else:
- n.index = index_customer
- no_depots.append(n)
- index_customer += 1
-
- count += 1
-
- return depots + no_depots
-
-
-def _read_tramos():
- """
- Lee archivo de tramos
-
- Returns
- -------
- list
- Lista de tuplas con los tramos (ubigeo1, ubigeo2)
- """
- tramos = []
- with open('odiparpack/inf226.tramos.v.2.0.csv', newline='') as f:
- rows = csv.reader(f)
- count = 1
- for row in rows:
- if count >= 2:
- tramos.append([row[0], row[1]])
- count += 1
- return tramos
-
-
def make_complete_customer_node_graph(nodes, tramos):
"""
Nodes + Tramos make a network. An undirected graph. But we only care
@@ -227,8 +98,8 @@ def make_complete_customer_node_graph(nodes, tramos):
def lab():
depot_num = 3
- nodes = _read_nodes(depot_num)
- tramos = _read_tramos()
+ nodes = read_nodes(depot_num)
+ tramos = read_tramos()
nodes, node_dist_mat, len_path = \
make_complete_customer_node_graph(nodes, tramos)
diff --git a/nodeOPP.py b/nodeOPP.py
new file mode 100644
index 0000000..0f792f4
--- /dev/null
+++ b/nodeOPP.py
@@ -0,0 +1,68 @@
+"""
+Custom Node class for OdiParPack
+"""
+
+import math
+
+class Node:
+ """
+ Attributes
+ ----------
+ index : int
+ Index in some arrays
+ ubigeo : str
+ 6 digit ID
+ lat : float
+ Latitud (angulo de los Paralelos) en grados sexagesimales
+ lon : float
+ Longitud (angulo de los Meridianos) en grados sexagesimales
+ is_depot : bool
+ demand : int
+ ready_time : float
+ due_time : float
+ service_time : float
+ x : float
+ Aproximacion local, en Km respecto
+ y : float
+ Aproximacion local, en Km respecto ("Lima")
+
+ Notes
+ -----
+ Web Mercator projection (BAD):
+
+ x = floor(256 / (2 * math.pi) * 2**(zoom_level) * (lon + math.pi))
+ y = floor(265 / (2 * math.pi) * 2**(zoom_level) * (math.pi - math.ln(math.tan( math.pi / 4 + lat / 2 ))))
+
+ x = R * lon
+ y = R * ln(tan(pi/4 + lat/2)
+
+ Both `lon` and `lat` in radians.
+
+ "Lima": -12.04591952,-77.03049615 (lat, long)
+ """
+
+ def __init__(self, index: int, ubigeo, lat, lon, is_depot,
+ demand, ready_time, due_time, service_time):
+ super()
+ self.index = index
+ self.ubigeo = ubigeo
+
+ if is_depot:
+ self.is_depot = True
+ else:
+ self.is_depot = False
+
+ earth_radius_km = 6371 # Avg. radius
+ lima_lat = -12.04591952
+ lima_lon = -77.03049615
+
+ self.lat = lat
+ self.lon = lon
+ self.x = (lon - lima_lon) * (math.pi / 180) * earth_radius_km
+ self.y = (lat - lima_lat) * (math.pi / 180) * earth_radius_km
+ self.x = round(self.x, 3)
+ self.y = round(self.y, 3)
+ self.demand = demand
+ self.ready_time = 0 # ready_time
+ self.due_time = due_time
+ self.service_time = service_time
diff --git a/readerOPP.py b/readerOPP.py
new file mode 100644
index 0000000..ccd213e
--- /dev/null
+++ b/readerOPP.py
@@ -0,0 +1,75 @@
+"""
+Functions to read input data from files
+"""
+import csv
+from nodeOPP import Node
+
+
+def read_nodes(depot_num):
+ """
+ Read nodes from input file.
+
+ Attributes
+ ----------
+ depot_num : int
+ Number of depots
+
+ Returns
+ -------
+ list
+ List of Nodes. The first `depot_num` nodes are the depots.
+ """
+ depots = []
+ no_depots = []
+ with open('odiparpack/inf226.oficinas_mod.csv', newline='') as csvfile:
+ orders = csv.reader(csvfile)
+ count = 1
+ index_customer = depot_num
+ index_depot = 0
+ for row in orders:
+ if count == 1:
+ count += 1
+ continue
+
+ ubigeo, dept, prov, lat, lon, region_natural, is_depot = row[:7]
+ demand, ready_time, due_time, service_time = row[7:]
+
+ n = Node(
+ -1, ubigeo, float(lat), float(lon),
+ int(is_depot),
+ demand=float(demand), ready_time=0,
+ due_time=float(due_time), service_time=60
+ )
+
+ if n.is_depot:
+ n.index = index_depot
+ depots.append(n)
+ index_depot += 1
+ else:
+ n.index = index_customer
+ no_depots.append(n)
+ index_customer += 1
+
+ count += 1
+
+ return depots + no_depots
+
+
+def read_tramos():
+ """
+ Lee archivo de tramos
+
+ Returns
+ -------
+ list
+ Lista de tuplas con los tramos (ubigeo1, ubigeo2)
+ """
+ tramos = []
+ with open('odiparpack/inf226.tramos.v.2.0.csv', newline='') as f:
+ rows = csv.reader(f)
+ count = 1
+ for row in rows:
+ if count >= 2:
+ tramos.append([row[0], row[1]])
+ count += 1
+ return tramos