139 lines
4.4 KiB
Python
139 lines
4.4 KiB
Python
from math import log, ceil
|
|
from operator import itemgetter
|
|
from classes import *
|
|
|
|
class SolvingAlgorithm:
|
|
def __init__(self,space,gMngr:GarageManager):
|
|
self.space:MetricSpace = space
|
|
self.garageManager:GarageManager = gMngr
|
|
self.amountTraveled = 0
|
|
|
|
def getGarageForCar(self,car:Point):
|
|
garages:List[Garage] = list(self.garageManager.garages)
|
|
garages = sorted(garages,key=lambda g: self.space.distancefunction.apply(car,g))
|
|
|
|
for g in garages:
|
|
if self.garageManager.is_full(g):
|
|
continue
|
|
else:
|
|
g.cars_parked.append(g)
|
|
self.amountTraveled += self.space.distancefunction.apply(car,g)
|
|
return g
|
|
|
|
return None
|
|
|
|
|
|
class MST():
|
|
@classmethod
|
|
def _helper_getListInPointset(self, pointesets:List[List[Point]] , point:tuple):
|
|
for li in pointesets:
|
|
if point in li:
|
|
return li
|
|
return None
|
|
|
|
|
|
def __init__(self, points:set, distancefunction: DistanceFunction,space:MetricSpace, powerTWO = False,mst_visualize=True):
|
|
self.points = points
|
|
self.distancefunction = distancefunction
|
|
|
|
all_edges = []
|
|
for i in self.points:
|
|
for j in self.points:
|
|
if not i == j:
|
|
if not (j,i, distancefunction.apply(i,j)) in all_edges:
|
|
all_edges.append((i,j, distancefunction.apply(i,j)))
|
|
|
|
all_edges = sorted(all_edges,key=itemgetter(2))
|
|
|
|
minimal_edges = [] # edge is represented by (i,j, distance/Weight)
|
|
pointSets:List[List[Point]] = []
|
|
for p in self.points:
|
|
pointSets.append([p])
|
|
|
|
visualisations =[]
|
|
for edge in all_edges:
|
|
if len(pointSets) <= 1: break
|
|
li0 = MST._helper_getListInPointset(pointSets,edge[0])
|
|
li1 = MST._helper_getListInPointset(pointSets,edge[1])
|
|
|
|
if not( li0 == li1):
|
|
minimal_edges.append(edge)
|
|
|
|
li_new = li0 + li1
|
|
pointSets.remove(li0)
|
|
pointSets.remove(li1)
|
|
pointSets.append( li_new)
|
|
|
|
if (mst_visualize):
|
|
a= frameGenerator.point_to_pixel_center(space,edge[0])
|
|
b= frameGenerator.point_to_pixel_center(space,edge[1])
|
|
data = [ a[0], a[1], b[0], b [1], (23,64,96,100)]
|
|
visualisations.append(RenderTask(RenderTaskType.LINE,"mst",data))
|
|
RenderTaskStack.add_single_frame_render(RenderTaskFrame(visualisations.copy()))
|
|
|
|
if(powerTWO):
|
|
for x in range(len(minimal_edges)):
|
|
c_edge = minimal_edges[x]
|
|
c_edge = ( c_edge[0], c_edge[1], 2**ceil(log(c_edge[2],2)) )
|
|
minimal_edges[x] = c_edge
|
|
|
|
if (mst_visualize):
|
|
RenderTaskStack.add_single_frame_render(RenderTaskFrame(visualisations.copy(),True))
|
|
|
|
self.minimalEdges: List[tuple[Point,Point,float]] = minimal_edges
|
|
|
|
def _dfs_recursive(self, tree, start, visited =[]):
|
|
# due tue MST property,
|
|
tour = []
|
|
|
|
for edge in tree:# go throug all edges and recursively walk down all that lead to new places, on return add back edge
|
|
if edge[0] == start and edge[1] not in visited:
|
|
tour.append(edge)
|
|
visited.append(start) # visited only needs to be carried in for a node downwards but not upwards, since this is a MST
|
|
data = self._dfs_recursive(tree,edge[1],visited)
|
|
tour+= data # add subtree
|
|
tour.append((edge[1],edge[0],edge[2])) #append reversed edge
|
|
|
|
return tour
|
|
|
|
|
|
|
|
def get_dfs_eulerwalk(self,start:Point, level= 0):
|
|
directionalEdges = []
|
|
for min_edge in self.minimalEdges:
|
|
i,j,dist = min_edge
|
|
if dist > 2**level: continue
|
|
directionalEdges.append((i,j,dist))
|
|
directionalEdges.append((j,i,dist))
|
|
|
|
# create walk with dfs
|
|
walk:List[tuple[Point,Point,float]] = self._dfs_recursive(directionalEdges,start)
|
|
|
|
return walk
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class AlgorithmA(SolvingAlgorithm):
|
|
def __init__(self, space:MetricSpace, gMngr: GarageManager):
|
|
super().__init__(space, gMngr)
|
|
gar_set = set(gMngr.garages)
|
|
self.mst = MST(gar_set,space.distancefunction,space,True)
|
|
|
|
def getGarageForCar(self, car: Point):
|
|
|
|
return super().getGarageForCar(car)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|