graph: Adjust calculation to match exercise
This commit is contained in:
29
classes.py
29
classes.py
@@ -15,22 +15,33 @@ class LocationType(Enum):
|
||||
|
||||
|
||||
class TransportData():
|
||||
def __init__(self, co2: float, speed: float, distance_penalty: float):
|
||||
def __init__(self, co2: float, speed: float):
|
||||
self.co2 = co2
|
||||
self.speed = speed
|
||||
self.distance_penalty = distance_penalty
|
||||
|
||||
def __str__(self):
|
||||
return f"{{co2: {self.co2}, speed: {self.speed}}}"
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
|
||||
class TransportMethod(Enum):
|
||||
WALK = TransportData(0, 4)
|
||||
CITY = TransportData(0.189, 30)
|
||||
AUTOBAHN = TransportData(0.189, 100)
|
||||
OEPNV = TransportData(0.055, 30)
|
||||
ICE = TransportData(0.055, 100)
|
||||
AIRPLANE = TransportData(0.2113, 900)
|
||||
|
||||
|
||||
class TransportKind(Enum):
|
||||
"""
|
||||
(co2 emission, speed, distance_penalty)
|
||||
distance_penalty
|
||||
"""
|
||||
WALK = TransportData(0, 4, 0.2)
|
||||
CITY = TransportData(0.189, 30, 0.2)
|
||||
AUTOBAHN = TransportData(0.189, 100, 0.2)
|
||||
OEPNV = TransportData(0.055, 30, 0.1)
|
||||
ICE = TransportData(0.055, 100, 0.1)
|
||||
AIRPLANE = TransportData(0.2113, 900, 0.02)
|
||||
INDIVIDUAL = 0.2
|
||||
TRAIN = 0.1
|
||||
FLYING = 0.02
|
||||
|
||||
|
||||
class Coordinate:
|
||||
|
||||
77
dijkstra.py
77
dijkstra.py
@@ -1,77 +0,0 @@
|
||||
"""
|
||||
Module, which holds the logic for the solving algorithms
|
||||
"""
|
||||
|
||||
from classes import DataSet, LocationType, Location, TransportMethod
|
||||
|
||||
|
||||
def calc_co2(distance: float, method: TransportMethod) -> float:
|
||||
"""
|
||||
Return co2 emission in kg
|
||||
"""
|
||||
return (distance * method.value.distance_penalty) * method.value.co2
|
||||
|
||||
|
||||
def calc_time(distance: float, method: TransportMethod) -> float:
|
||||
"""
|
||||
Return time taking in h
|
||||
"""
|
||||
return (distance * method.value.distance_penalty) / method.value.speed
|
||||
|
||||
|
||||
def add_node(graph: dict, frm: str, to: str, locs: dict, method: TransportMethod):
|
||||
"""
|
||||
Add a node into the graph
|
||||
"""
|
||||
distance = locs[frm].distance(locs[to])
|
||||
co2 = calc_co2(distance, method)
|
||||
time = calc_time(distance, method)
|
||||
new_connection: dict = {to: {"type": method, "co2": co2, "time": time}}
|
||||
graph[frm].append(new_connection)
|
||||
print(f"Added node from {frm} to {to} with type {method}.")
|
||||
|
||||
|
||||
def create_graph(dataset: DataSet) -> dict:
|
||||
"""
|
||||
Creates the initial graph, with all edges
|
||||
"""
|
||||
locations = dataset.locations
|
||||
graph: dict = {}
|
||||
|
||||
# add nodes with no edges
|
||||
for start in locations:
|
||||
graph.update({start: []})
|
||||
|
||||
# add edges
|
||||
for start in locations:
|
||||
for dest in locations:
|
||||
# skip, if we wouldnt go anywhere
|
||||
if start == dest:
|
||||
continue
|
||||
print(f"Searching for nodes from {start} to {dest}...")
|
||||
distance = locations[start].distance(locations[dest])
|
||||
|
||||
# Individualtransport
|
||||
if distance <= 1:
|
||||
add_node(graph, start, dest, locations, TransportMethod.WALK)
|
||||
if distance <= 10 + 1:
|
||||
add_node(graph, start, dest, locations, TransportMethod.CITY)
|
||||
if distance <= 2000 + 10 + 1:
|
||||
add_node(graph, start, dest, locations, TransportMethod.AUTOBAHN)
|
||||
|
||||
# Train
|
||||
if locations[start].type == LocationType.HALTESTELLE:
|
||||
dest_type = locations[dest].type
|
||||
# there are only trains between haltestellen or airports
|
||||
if dest_type == LocationType.HALTESTELLE or dest_type == LocationType.FLUGHAFEN:
|
||||
if distance <= 25:
|
||||
add_node(graph, start, dest, locations, TransportMethod.OEPNV)
|
||||
else:
|
||||
add_node(graph, start, dest, locations, TransportMethod.ICE)
|
||||
|
||||
# Flying
|
||||
flights = dataset.flights
|
||||
for flight in flights:
|
||||
add_node(graph, start, dest, locations, TransportMethod.AIRPLANE)
|
||||
|
||||
return graph
|
||||
19
dijsktra.py
Normal file
19
dijsktra.py
Normal file
@@ -0,0 +1,19 @@
|
||||
"""
|
||||
This module holds the logic for the solving
|
||||
"""
|
||||
|
||||
|
||||
class Dijkstra():
|
||||
def __init__(self, graph: dict):
|
||||
"""
|
||||
table: matrix with vertex as key, price and prev vertex as value
|
||||
OL: open list, to keep track of finished vertecis
|
||||
"""
|
||||
self.graph = graph
|
||||
self.table = {}
|
||||
self.OL = []
|
||||
|
||||
def algorithm(self):
|
||||
print("Performing Dijkstra on the following graph...")
|
||||
for vertex in self.graph:
|
||||
print(f"{vertex}: {self.graph[vertex]}")
|
||||
133
graph.py
Normal file
133
graph.py
Normal file
@@ -0,0 +1,133 @@
|
||||
"""
|
||||
Module, which creates a graph
|
||||
"""
|
||||
|
||||
from classes import DataSet, LocationType, TransportMethod, TransportKind
|
||||
|
||||
|
||||
def calc_co2(distance: float, kind: TransportKind) -> float:
|
||||
"""
|
||||
Return co2 emission in kg
|
||||
"""
|
||||
match kind:
|
||||
case TransportKind.INDIVIDUAL:
|
||||
if distance <= 1:
|
||||
return 0
|
||||
else:
|
||||
# TODO: CITY == AUTOBAHN
|
||||
return distance * TransportMethod.CITY.value.co2
|
||||
case TransportKind.TRAIN:
|
||||
# TODO: OPENV == ICE
|
||||
return distance * TransportMethod.ICE.value.co2
|
||||
case TransportKind.FLYING:
|
||||
return distance * TransportMethod.AIRPLANE.value.co2
|
||||
|
||||
|
||||
def calc_time(
|
||||
distance: float,
|
||||
kind: TransportKind,
|
||||
flights: dict = None,
|
||||
frm: dict = None,
|
||||
) -> float:
|
||||
"""
|
||||
distance: distance without penalty
|
||||
kind: kind of transport
|
||||
flights: all flights (optional)
|
||||
frm: start location (need for flights, optional)
|
||||
"""
|
||||
match kind:
|
||||
case TransportKind.INDIVIDUAL:
|
||||
distance += distance * TransportKind.INDIVIDUAL.value
|
||||
if distance <= 1:
|
||||
return distance / TransportMethod.WALK.value.speed
|
||||
elif distance <= 10 + 1:
|
||||
speed = 1 / TransportMethod.WALK.value.speed
|
||||
return speed + ((distance - 1) / TransportMethod.CITY.value.speed)
|
||||
elif distance < 2000 + 10 + 1:
|
||||
speed = 1 / TransportMethod.WALK.value.speed
|
||||
speed += 10 / TransportMethod.WALK.value.speed
|
||||
return speed + ((distance - 1 - 10) / TransportMethod.AUTOBAHN.value.speed)
|
||||
case TransportKind.TRAIN:
|
||||
distance += distance * TransportKind.TRAIN.value
|
||||
if distance <= 25:
|
||||
return distance / TransportMethod.OEPNV.value.speed
|
||||
else:
|
||||
speed = 25 / TransportMethod.OEPNV.value.speed
|
||||
# NOTE: should we subtract here?
|
||||
return speed + ((distance - 25) / TransportMethod.ICE.value.speed)
|
||||
case TransportKind.FLYING:
|
||||
assert(flights != None)
|
||||
assert(frm != None)
|
||||
distance += distance * TransportKind.FLYING.value
|
||||
stops = flights[frm]["stops"]
|
||||
domestic = flights[frm]["domestic"]
|
||||
if domestic:
|
||||
time = 2
|
||||
else:
|
||||
time = 3
|
||||
waittime = (stops + 1) * time
|
||||
return waittime + (distance / TransportMethod.AIRPLANE.value.speed)
|
||||
|
||||
|
||||
def create_graph(dataset: DataSet) -> dict:
|
||||
"""
|
||||
Creates the initial graph, with all edges
|
||||
"""
|
||||
locations = dataset.locations
|
||||
graph: dict = {}
|
||||
|
||||
# add nodes with no edges
|
||||
for start in locations:
|
||||
graph.update({start: []})
|
||||
|
||||
# add edges
|
||||
for start in locations:
|
||||
for dest in locations:
|
||||
# skip, if we wouldnt go anywhere
|
||||
if start == dest:
|
||||
continue
|
||||
print(f"Searching for nodes from {start} to {dest}...")
|
||||
distance = locations[start].distance(locations[dest])
|
||||
|
||||
# Individualtransport
|
||||
if distance <= 2000 + 10 + 1:
|
||||
time = calc_time(distance, TransportKind.INDIVIDUAL)
|
||||
co2 = calc_co2(distance, TransportKind.INDIVIDUAL)
|
||||
new_connection: dict = {dest:
|
||||
{"kind": TransportKind.INDIVIDUAL,
|
||||
"co2": co2,
|
||||
"time": time}}
|
||||
graph[start].append(new_connection)
|
||||
print(f"Added new INDIVIDUAL connection from {start} to {dest}")
|
||||
|
||||
# Train
|
||||
if locations[start].type == LocationType.HALTESTELLE:
|
||||
dest_type = locations[dest].type
|
||||
# there are only trains between haltestellen or airports
|
||||
if dest_type == LocationType.HALTESTELLE or dest_type == LocationType.FLUGHAFEN:
|
||||
time = calc_time(distance, TransportKind.TRAIN)
|
||||
co2 = calc_co2(distance, TransportKind.TRAIN)
|
||||
new_connection: dict = {dest:
|
||||
{"kind": TransportKind.TRAIN,
|
||||
"co2": co2,
|
||||
"time": time}}
|
||||
graph[start].append(new_connection)
|
||||
print(f"Added new TRAIN connection from {start} to {dest}")
|
||||
|
||||
# Flying
|
||||
print("Adding flights...")
|
||||
flights = dataset.flights
|
||||
for flight in flights:
|
||||
start = flight
|
||||
dest = flights[flight]["to"]
|
||||
distance = locations[start].distance(locations[dest])
|
||||
time = calc_time(distance, TransportKind.FLYING, flights, start)
|
||||
co2 = calc_co2(distance, TransportKind.FLYING)
|
||||
new_connection: dict = {dest:
|
||||
{"kind": TransportKind.TRAIN,
|
||||
"co2": co2,
|
||||
"time": time}}
|
||||
graph[start].append(new_connection)
|
||||
print(f"Added new FLYING connection from {start} to {dest}")
|
||||
|
||||
return graph
|
||||
9
main.py
9
main.py
@@ -4,7 +4,8 @@ Requires: python > 3.10.x
|
||||
"""
|
||||
|
||||
from parser import parse
|
||||
from dijkstra import create_graph
|
||||
from graph import create_graph
|
||||
from dijsktra import Dijkstra
|
||||
|
||||
|
||||
INPUTFILE = "file.txt"
|
||||
@@ -12,9 +13,11 @@ INPUTFILE = "file.txt"
|
||||
|
||||
def main():
|
||||
dataset: dict = parse(INPUTFILE)
|
||||
print(dataset)
|
||||
# print(dataset)
|
||||
graph: dict = create_graph(dataset)
|
||||
print(graph)
|
||||
# print(graph)
|
||||
dijkstra = Dijkstra(graph)
|
||||
dijkstra.algorithm()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -68,7 +68,11 @@ def parse(filename: str) -> DataSet:
|
||||
stops = splitted[2]
|
||||
else:
|
||||
stops = 0
|
||||
flights.update({id1: {"to": id2, "stops": stops}})
|
||||
if len(splitted) == 4:
|
||||
domestic = True
|
||||
else:
|
||||
domestic = False
|
||||
flights.update({id1: {"to": id2, "stops": stops, "domestic": domestic}})
|
||||
continue
|
||||
case ParsingMode.FINDCONNECTION:
|
||||
print("Parsing connection...")
|
||||
|
||||
Reference in New Issue
Block a user