Esempio n. 1
0
    def splitLinearBounded(solution):
        solution1 = copy.deepcopy(solution)
        solution2 = copy.deepcopy(solution)
        depotsList = dpts.get_depotsList()
        customers = solution1.get_giantTour()
        depots = solution1.get_depots()
        for dpt in depotsList:
            listCst = []
            depot = depotsList[dpt]
            for j in range(len(customers)):
                if dpt == str(depots[j].get_id()):
                    listCst.append(customers[j])

            sumDistance = [0.0 for x in range(len(listCst) + 1)]
            sumLoad = [0.0 for x in range(len(listCst) + 1)]
            sumDistance[0] = 0  # distancia do depósito
            # distância do depósito ao primeiro nó
            sumDistance[1] = dist.euclidianDistance(listCst[0].get_x_coord(),
                                                    listCst[0].get_y_coord(),
                                                    depot.get_x_coord(),
                                                    depot.get_y_coord())

            sumLoad[0] = 0
            sumLoad[1] = customers[0].get_demand()
            # inicializar com o somatório distancia de i-1 a i e a demanda de i-1 a i
            for i in range(2, len(listCst) + 1):
                sumDistance[i] = sumDistance[i - 1] + dist.euclidianDistance(
                    listCst[i - 2].get_x_coord(), listCst[i - 2].get_y_coord(),
                    listCst[i - 1].get_x_coord(), listCst[i - 1].get_y_coord())
                sumLoad[i] = sumLoad[i - 1] + listCst[i - 1].get_demand()

            potential = []
            pred = []

            for k in range(depot.get_numberVehicles() + 1):
                potential.append([1.e30 for x in range(len(listCst) + 1)])
                pred.append([-1 for x in range(len(listCst) + 1)])

            potential[0][0] = 0

            for k in range(depot.get_numberVehicles()):
                queue = [k]
                i = k + 1
                while (i <= len(listCst)) and (len(queue) > 0):
                    # o primeiro da fila será o melhor predecessor de i
                    potential[k + 1][i] = SplitAlgorithms.propagatek(
                        queue[0], i, k, listCst, sumDistance, potential,
                        depot)  # calcula custo de i a j
                    pred[k + 1][i] = queue[0]

                    # se i não é dominado pelo último da pilha
                    if i < len(listCst):
                        if not (SplitAlgorithms.dominatesk(
                                queue[len(queue) - 1], i, k, listCst,
                                sumDistance, potential, sumLoad, depot)):
                            # então i será inserido, precisando remover quem ele domina
                            while len(
                                    queue
                            ) > 0 and SplitAlgorithms.dominatesRightk(
                                    queue[len(queue) - 1], i, k, listCst,
                                    sumDistance, potential, depot):
                                del queue[len(queue) - 1]
                            queue.append(i)

                        # Verifica se a frente consegue chegar ao próximo nó, caso contrário ele desaparecerá.
                        while len(queue) > 0 and (
                                sumLoad[i + 1] - sumLoad[queue[0]]) > (
                                    depot.get_loadVehicle() + 0.0001):
                            del queue[0]

                    i += 1

            if potential[depot.get_numberVehicles()][len(listCst)] > 1.e29:
                # print("ERRO: nenhuma solução de divisão foi propagada até o último nó")
                del solution1
                return SplitAlgorithms.mountRoutes(solution2)

            else:
                # achando o número ótimo de rotas
                minCost = 1.e30
                nRoutes = 0
                for k in range(1, depot.get_numberVehicles() + 1):
                    if potential[k][len(listCst)] < minCost:
                        minCost = potential[k][len(listCst)]
                        # print("minCost "+str(minCost))
                        nRoutes = k

                cour = len(listCst)
                for i in range(nRoutes - 1, -1, -1):
                    route = Route(depot)
                    j = pred[i + 1][cour]
                    for k in range(j + 1, cour + 1):
                        route.addCustomer(listCst[k - 1])
                    cour = j
                    # calcular custo da rota formada
                    route.startValues()
                    route.calculeCost()
                    solution1.addRoutes(route)

        solution1.formGiantTour()
        solution1.calculateCost()
        # print(solution)
        return solution1
Esempio n. 2
0
    def mountRoutes(solution):
        solution1 = copy.deepcopy(solution)
        allDepots = dpts.get_depotsList()
        numberDepots = dpts.get_numberDepots()
        customers = solution1.get_giantTour()
        depots = solution1.get_depots()
        numberVehicles = depots[0].get_numberVehicles()
        # print("customers: "+str(customers))
        # print("deposts: "+str(depots))

        # depósitos já vem separados, utilizar heurística de Prins2004 para separar as rotas

        # separar conjuntos
        for i in allDepots:
            depot = allDepots[i]
            path = []
            for j in range(len(customers)):
                if str(depot.get_id()) == str(depots[j].get_id()):
                    path.append(customers[j])
            # print("path: "+str(path))
            # gerar rotas para cada caminho
            # método retorna lista de predecessores
            pred = SplitAlgorithms.splitRoute(path, depot)
            # método retorna lista de lista com rotas para um depósito (número máximo de veículos não delimitado)
            allroutes = SplitAlgorithms.extractVRP(pred, path)
            # verificar número de rotas formadas

            routes = []
            for l in allroutes:
                if len(l) > 0:  # há rota
                    routes.append(l)
            # print("routes: "+ str(routes))
            # caso tenha mais rotas que veículos
            if len(routes) > numberVehicles:
                # ordenada em ordem crescente de demanda
                routes = sorted(routes, key=lambda x: x[1])
                # juntar rotas com menor demanda
                aux = len(routes) - numberVehicles
                while aux > 0:
                    r0 = routes[0][0]
                    r1 = routes[1][0]
                    r0 = r0 + r1
                    demand = routes[0][1] + routes[1][1]
                    routes[0] = [r0, demand]
                    del routes[1]
                    # ordenada em ordem crescente de demanda
                    routes = sorted(routes, key=lambda x: x[1])
                    aux -= 1

            k = -1
            for l in routes:
                route = Route(depot)
                if len(l) > 0:
                    for m in l[0]:
                        route.addCustomer(m)
                        k += 1

                    # calcular custo da rota formada
                    route.startValues()
                    route.calculeCost()
                    solution1.addRoutes(route)
        solution1.formGiantTour()
        solution1.calculateCost()
        # print(solution1)
        return solution1
Esempio n. 3
0
    def splitLinear(solution, limitRoutes=True):
        solution1 = copy.deepcopy(solution)
        depotsList = dpts.get_depotsList()
        customers = solution1.get_giantTour()
        depots = solution1.get_depots()
        penalty = 0.0
        for dpt in depotsList:
            listCst = []
            depot = depotsList[dpt]
            for j in range(len(customers)):
                if dpt == str(depots[j].get_id()):
                    listCst.append(customers[j])

            lenListCst = len(listCst)
            sumDistance = []
            sumLoad = []
            potential = []
            pred = []

            for x in range(lenListCst + 1):
                sumDistance.append(0.0)
                sumLoad.append(0.0)
                potential.append(1.e30)
                pred.append(-1)

            sumDistance[0] = 0  # distancia do depósito
            # distância do depósito ao primeiro nó
            sumDistance[1] = dist.euclidianDistance(listCst[0].get_x_coord(),
                                                    listCst[0].get_y_coord(),
                                                    depot.get_x_coord(),
                                                    depot.get_y_coord())

            sumLoad[0] = 0
            sumLoad[1] = customers[0].get_demand()
            potential[0] = 0

            # inicializar com o somatório distancia de i-1 a i e a demanda de i-1 a i
            for i in range(2, lenListCst + 1):
                sumDistance[i] = sumDistance[i - 1] + dist.euclidianDistance(
                    listCst[i - 2].get_x_coord(), listCst[i - 2].get_y_coord(),
                    listCst[i - 1].get_x_coord(), listCst[i - 1].get_y_coord())
                sumLoad[i] = sumLoad[i - 1] + listCst[i - 1].get_demand()

            queue = [0]

            for i in range(1, lenListCst + 1):
                # da frente é o melhor predecessor de 1
                potential[i] = SplitAlgorithms.propagate(
                    queue[0], i, listCst, sumDistance, potential, depot)
                pred[i] = queue[0]

                if i < lenListCst:
                    # se i não é dominado pelo último da pilha
                    if not SplitAlgorithms.dominates(
                            queue[len(queue) - 1], i, listCst, sumDistance,
                            potential, sumLoad, depot):
                        # então i será inserido, precisando remover quem ele domina
                        while len(
                                queue) > 0 and SplitAlgorithms.dominatesRight(
                                    queue[len(queue) - 1], i, listCst,
                                    sumDistance, potential, depot):
                            del queue[len(queue) - 1]
                        queue.append(i)
                    # Verifica se a frente consegue chegar ao próximo nó, caso contrário ele desaparecerá.
                    while len(queue) > 0 and (sumLoad[i + 1] - sumLoad[
                            queue[0]]) > (depot.get_loadVehicle() + 0.0001):
                        del queue[0]

            if potential[len(listCst)] > 1.e29:
                print(
                    "ERRO: nenhuma solução de divisão foi propagada até o último nó"
                )
                exit(1)
            else:
                # achando o número ótimo de rotas
                minCost = 1.e30
                nRoutes = 0
                cour = lenListCst
                while cour > 0:
                    cour = pred[cour]
                    nRoutes += 1

                cour = len(listCst)
                # print(listCst)
                # print(pred)
                # print(cour)
                trip = []
                for i in range(nRoutes - 1, -1, -1):
                    t = []

                    j = pred[cour]
                    load = 0
                    for k in range(j + 1, cour + 1):
                        t.append(listCst[k - 1])
                        load += listCst[k - 1].get_demand()
                    cour = j
                    trip.append([t, load])

                # se o número de rotas formadas for maior que o número de veículos, juntar as de menor demanda
                numberVehicles = depot.get_numberVehicles()
                if nRoutes > numberVehicles:
                    # ordenada em ordem crescente de demanda
                    trip = sorted(trip, key=lambda x: x[1])
                    # juntar rotas com menor demanda
                    aux = len(trip) - numberVehicles
                    aux1 = aux

                    if limitRoutes:
                        while aux > 0:
                            r0 = trip[0][0]
                            r1 = trip[1][0]
                            r0 = r0 + r1
                            demand = trip[0][1] + trip[1][1]
                            trip[0] = [r0, demand]
                            del trip[1]
                            # ordenada em ordem crescente de demanda
                            trip = sorted(trip, key=lambda x: x[1])
                            aux -= 1
                    else:
                        penalty += 1000 * aux1

                # adicionar rotas a solucao
                for r in trip:
                    route = Route(depot)
                    # print("r")
                    # print(r)
                    for c in r[0]:
                        # print("c")
                        # print(c)
                        route.addCustomer(c)
                    # calcular custo da rota formada
                    route.startValues()
                    route.calculeCost()
                    solution1.addRoutes(route)

        solution1.formGiantTour()
        solution1.calculateCost(penalty)
        # print(solution1.get_routes())
        # exit(1)
        return solution1