예제 #1
0
def main():
    np.random.seed(7890)
    # recebendo instâncias
    r = ReadingDatas("dat/p01")
    r.readFile()
    # adicionando clientes
    Customers.addCustomers(r)
    # for cst in Customers.get_customersList().values():
    # print(cst)

    # adicionando depósitos
    Depots.addDepots(r)
    # print("\n\n\n\")
    # for dpt in Depots.get_depotsList().values():
    # print(dpt)

    # cálculo das distâncias
    Distances.euclidianDistanceAll(Customers.get_customersList(),
                                   Depots.get_depotsList())

    # for cst in Customers.get_customersList():
    #     print(cst)
    #     print(Customers.get_customersList()[cst].get_depotsDistances())
    # print("\n\n\n")
    # for cst in Customers.get_customersList():
    #     print(cst)
    #     print(Customers.get_customersList()[cst].get_neighborsDistances())

    ga = GA()
    ga.GA()
예제 #2
0
    def GilletJohnson():
        SplitDepots._individual = Solution()
        SplitDepots._availableDepots = []
        customersList = copy.deepcopy(csts.get_customersList())  # dicionário

        for dpt in dpts.get_depotsList():
            SplitDepots._availableDepots.append(
                [dpt, dpts.get_depotsList()[dpt].get_loadTotal(), 0.0, 0]
            )  # depósito, carga totaL,demanda total atendida,clientes alocados

        unallocatedCustomers = SplitDepots.GilletJohnsonProcedure(
            customersList, len(SplitDepots._availableDepots))
        # print("verificando")
        # print(SplitDepots._individual)
        return SplitDepots._individual
예제 #3
0
def main(SEED, POP, DESC, PROB_MUT, PROB_LS_POP, PROB_LS, PROB_LSB, PROB_LSBP,
         GEN_ILS, GEN_ILSA, DATFILE, INSTANCE):

    # redefinindo variáveis conforme Package Irace
    # config.FRAC_MAX_DISTRIBUTION = FRAC
    config.SIZE_POP = POP
    config.SIZE_DESC = DESC
    config.PROB_MUTATION = PROB_MUT
    config.PROB_LS_POP = PROB_LS_POP
    config.PROB_LS = PROB_LS
    config.PROB_LS_BEST = PROB_LSB
    config.PROB_LS_BEST_P = PROB_LSBP
    config.GEN_ILS = GEN_ILS
    config.GEN_ILSA = GEN_ILSA

    seed = SEED

    timeIni = time.time()

    # exit(0)

    # recebendo instâncias
    r = ReadingDatas(INSTANCE)
    r.readFile()
    # adicionando clientes
    Customers.addCustomers(r)

    # adicionando depósitos
    Depots.addDepots(r)

    # cálculo das distâncias
    Distances.euclidianDistanceAll(Customers.get_customersList(),
                                   Depots.get_depotsList())

    ga = GA()
    best = ga.GA(seed)
    cost = best.get_cost()
    timeEnd = (time.time() - timeIni) / 60.0

    logging.debug("Melhor indivíduo: %s" % best)
    logging.debug("tempo total: " + str(timeEnd) + " minutos.")
    logging.debug("------------fim algoritmo genético-----------")

    with open(DATFILE, 'w') as f:
        f.write(str(cost))
예제 #4
0
    def __init__(self):
        self._giantTour = []  # lista de clientes, cada item um Customer
        self._routes = []  # lista de Route

        # self._idRoutes = []  # indicativo da rota

        self._cost = 0
        self._depots = [
        ]  # lista de depósitos, cada item o Depot de cada cliente
        self._infeasible = False
        nRoutesByDepot = []
        for dpt in Depots.get_depotsList():
            nRoutesByDepot.append((dpt, 0))
        # número de rotas por depósitos
        self._nRoutesByDepot = dict(nRoutesByDepot)
예제 #5
0
    def splitByDepot(listCustomers):
        customers = list(copy.deepcopy(listCustomers))
        depots = dpts.get_depotsList()  # dicionário
        split = []  # cada indice da lista uma subrota
        SplitDepots._individual = Solution()
        nDepots = len(depots)
        base = len(customers) / float(nDepots)
        maxCustomers = round(config.FRAC_MAX_DISTRIBUTION * base)
        # print(maxCustomers)
        # dividir em n grupos de clientes
        aux = nDepots
        for n in depots.values():
            control = [0, 0]  # carregamento, duração
            tour = []
            # se existir cliente não alocado
            while (control[0] < n.get_loadTotal()
                   and control[1] < n.get_durationTotal()) or aux == 1:
                if len(customers) == 0 or (aux > 1
                                           and len(tour) >= maxCustomers):
                    break
                control[0] = control[0] + customers[0].get_demand()
                control[1] = control[1] + customers[0].get_duration()
                if (control[0] <= n.get_loadTotal()
                        and control[1] <= n.get_durationTotal()) or aux == 1:
                    tour.append(customers[0])
                    del customers[0]  # atualizar lista
                else:
                    control[0] = control[0] - customers[0].get_demand()
                    control[1] = control[1] - customers[0].get_duration()
                    break
            split.append(tour)
            aux -= 1
        # associar o primeiro cliente da subrota ao depósito mais próximo
        depotsAvailable = list(copy.deepcopy(depots).keys())
        for s in split:
            i = 0
            depot = s[0].get_depotsDistances()[i]
            while str(depot[0]) not in depotsAvailable:
                i += 1
                depot = s[0].get_depotsDistances()[i]
            for cst in s:
                SplitDepots._individual.addGiantTour(cst,
                                                     depots[str(depot[0])])
            depotsAvailable.remove(str(depot[0]))

        return SplitDepots._individual
예제 #6
0
 def calculateCost(self, extraPenalty=0):
     self._cost = 0.0
     depots = Depots.get_depotsList()
     for r in self._routes:
         self._cost += r.get_totalCost()
     # penalidade por excesso de rotas
     if extraPenalty > 0:
         self._cost += extraPenalty
         self._infeasible = True
     else:
         # verificar número de rotas por depósito
         for i in self.get_nRoutesByDepot():
             nRoutes = self.get_nRoutesByDepot()[i]
             nVehicles = depots[i].get_numberVehicles()
             if nVehicles < nRoutes:  # excedente
                 exceed = nRoutes - nVehicles
                 self._cost += exceed * 1000
예제 #7
0
    def removeRoutesEmpty(self):
        auxRoutes = []
        # verificar depósitos com excesso de rotas
        exceed = []
        depots = Depots.get_depotsList()
        for c in self._nRoutesByDepot:
            if depots[c].get_numberVehicles() < self._nRoutesByDepot[c]:
                exceed.append(c)
        # eliminar rotas vazias
        for r in self._routes:
            if r.get_tour():
                auxRoutes.append(r)
            else:  # está vazia
                keyDpt = str(r.get_depot().get_id())
                self.decreaseRoute(keyDpt)
                if keyDpt in exceed and depots[keyDpt].get_numberVehicles(
                ) >= self._nRoutesByDepot[keyDpt]:
                    self._cost -= 1000

        self._routes = auxRoutes
예제 #8
0
    def M10(self, solution):
        solution1 = copy.deepcopy(solution)
        depots = dpts.get_depotsList()
        #escolha da rota
        routes = solution1.get_routes()
        idRoute = np.random.randint(len(routes))
        route = copy.deepcopy(routes[idRoute])
        length = len(route.get_tour())  # comprimento da rota
        oldDepot = route.get_depot()
        costWithoutRoute = solution1.get_cost() - route.get_totalCost()
        penalty = route.get_totalCost() - route.get_costWithoutPenalty()
        extraPenalty = 0
        # print(penalty)
        cont = 0

        bestRoute = copy.deepcopy(route)
        # print("tamanho de rotas")
        # print(len(routes))
        # print("route")
        # print(route)
        if length > 0:
            route1 = copy.deepcopy(route)
            #rotação da rota
            for i in range(length):
                #rotacionar
                # print(route1)
                aux = route1.get_tour()[0]
                # print(aux)
                cost = route1.costWithoutNode(0)
                route1.removeCustomer(aux)
                route1.set_cost(cost[1], cost[2], cost[3])
                cost = route1.costWithNode(aux, length - 1)
                route1.addCustomer(aux)
                route1.set_cost(cost[1], cost[2], cost[3])
                # print(route1)
                # print("-----")
                # verificar se rota gerada é melhor (considerando mesmo depósito)
                if bestRoute.get_totalCost() > route1.get_totalCost():
                    extraPenalty = 0
                    bestRoute = copy.deepcopy(route1)
                    cont = 1
                # verificar transferência da rota em outro depósito
                for dpt in depots.values():
                    if str(dpt) != str(oldDepot):
                        # verificar rota para o novo depósito
                        tour = route1.get_tour()
                        # tirar o custo associado ao depósito
                        cost1 = route1.get_totalCost() - dist.euclidianDistance(tour[0].get_x_coord(),
                                tour[0].get_y_coord(), oldDepot.get_x_coord(), oldDepot.get_y_coord()) - \
                                dist.euclidianDistance(tour[length-1].get_x_coord(),
                                tour[length-1].get_y_coord(), oldDepot.get_x_coord(), oldDepot.get_y_coord())

                        # computar custo com o novo depósito
                        newCost = cost1 + dist.euclidianDistance(tour[0].get_x_coord(),
                            tour[0].get_y_coord(), dpt.get_x_coord(), dpt.get_y_coord()) + \
                            dist.euclidianDistance(tour[length-1].get_x_coord(),
                            tour[length-1].get_y_coord(), dpt.get_x_coord(), dpt.get_y_coord())

                        if bestRoute.get_totalCost() > newCost:
                            # verifica número de veículos utilizados pelo depósito
                            nVehicles = 0
                            for r in solution1.get_routes():
                                if r.get_depot() == dpt:
                                    nVehicles += 1
                            if nVehicles < dpt.get_numberVehicles():
                                if (costWithoutRoute + newCost
                                    ) < solution1.get_cost():  # é melhor
                                    extraPenalty = 0
                                    bestRoute = copy.deepcopy(route1)
                                    bestRoute.set_depot(dpt)
                                    newCost1 = newCost - penalty
                                    bestRoute.set_cost(
                                        newCost1, bestRoute.get_totalDemand(),
                                        bestRoute.get_totalService())

                                    cont = 1
                            # else:
                            #     if (costWithoutRoute + newCost + 1000) < solution1.get_cost(): # ainda é melhor
                            #         extraPenalty = 1000 #penalização por rota a mais
                            #         bestRoute.set_depot(dpt)
                            #         newCost1 = newCost - penalty
                            #         bestRoute.set_cost(newCost1, bestRoute.get_totalDemand(),
                            #             bestRoute.get_totalService())
                            #         cont = 1

            if cont == 1:
                # print(penalty)
                # # print(bestRoute.get_totalCost())
                # print(route)
                # # print("best")
                # print(bestRoute)
                solution1.setRoute(bestRoute, idRoute)
                solution1.formGiantTour()
                solution1.calculateCost(extraPenalty)
                return solution1

        return solution
예제 #9
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
예제 #10
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
예제 #11
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
예제 #12
0
    def randomDistribution():
        #print('Entrou aqui')
        #np.random.seed(idum)
        SplitDepots._individual = Solution()
        customersList = copy.deepcopy(csts.get_customersList())  # dicionário
        # lista com as chaves dos clientes
        keysCst = list(customersList.keys())
        depots = dpts.get_depotsList()  # dicionário
        nDepots = len(depots)
        base = len(customersList) / float(nDepots)
        maxCustomers = round(config.FRAC_MAX_DISTRIBUTION * base)

        nCustomers = len(keysCst)
        solution = {}

        # (depósito, [total de demanda, número de clientes alocados]
        control = {}

        for depot in depots:
            control[depot] = [0, 0]
        while nCustomers > 0:  # enquanto tiver cliente não alocado
            # cliente aleatório
            idCst = np.random.randint(0, len(keysCst))
            customer = customersList[keysCst[idCst]]
            # depósito mais próximo
            i = 0
            dpt = customer.get_depotsDistances()[i]
            cont = len(customer.get_depotsDistances())
            aux = 0
            while (control[str(dpt[0])][0] >=
                   depots[str(dpt[0])].get_loadTotal() + 0.0001 or
                   (cont > 1
                    and control[str(dpt[0])][1] > maxCustomers)) and cont > 0:
                if cont == 1:
                    aux = 1  # indica que todos os depósitos anteriores estão lotados
                i += 1
                dpt = customer.get_depotsDistances()[i]
                cont -= 1

            depot = depots[str(dpt[0])]
            control[str(
                dpt[0])][0] = control[str(dpt[0])][0] + customer.get_demand()
            control[str(dpt[0])][1] = control[str(dpt[0])][1] + 1

            # adicionar cliente ao depósito
            SplitDepots._individual.addGiantTour(customer, depot)
            del keysCst[idCst]  # atualizar lista
            nCustomers -= 1
            # escolher três clientes aleatórios
            if len(keysCst) > 0:
                idcst1 = np.random.randint(0, len(keysCst))
                neighbor1 = customersList[keysCst[idcst1]]
                dist1 = dist.euclidianDistance(customer.get_x_coord(),
                                               customer.get_y_coord(),
                                               neighbor1.get_x_coord(),
                                               neighbor1.get_y_coord())
                idcst2 = np.random.randint(0, len(keysCst))
                neighbor2 = customersList[keysCst[idcst2]]
                dist2 = dist.euclidianDistance(customer.get_x_coord(),
                                               customer.get_y_coord(),
                                               neighbor2.get_x_coord(),
                                               neighbor2.get_y_coord())
                idcst3 = np.random.randint(0, len(keysCst))
                neighbor3 = customersList[keysCst[idcst3]]
                dist3 = dist1 = dist.euclidianDistance(customer.get_x_coord(),
                                                       customer.get_y_coord(),
                                                       neighbor3.get_x_coord(),
                                                       neighbor3.get_y_coord())
                # ver o mais próximo ao cliente
                if dist1 <= dist2 and dist1 <= dist3:
                    close = neighbor1
                    id = idcst1
                elif dist2 <= dist1 and dist2 <= dist3:
                    close = neighbor2
                    id = idcst2
                else:
                    close = neighbor3
                    id = idcst3

                control[str(
                    dpt[0])][0] = control[str(dpt[0])][0] + close.get_demand()
                control[str(dpt[0])][1] = control[str(dpt[0])][1] + 1

                if (control[str(dpt[0])][0] <= depot.get_loadTotal() + 0.0001
                        and
                        control[str(dpt[0])][1] <= maxCustomers) or aux == 1:
                    # adicionar vizinho mais próximo a solução
                    SplitDepots._individual.addGiantTour(close, depot)
                    del keysCst[id]  # atualizar lista
                    nCustomers -= 1
                else:
                    control[str(dpt[0])][0] = control[str(
                        dpt[0])][0] - close.get_demand()
                    control[str(dpt[0])][1] = control[str(dpt[0])][1] - 1

        # print(self._individual.get_giantTour())
        # print(SplitDepots._individual.get_depots())
        return SplitDepots._individual
예제 #13
0
    def GilletJohnsonProcedure(customersList, nDepotsAvailable):
        unallocatedCustomers = customersList
        numberDepotsAvailable = nDepotsAvailable
        depots = dpts.get_depotsList()
        auxiliar = []
        base = len(csts.get_customersList()) / float(len(depots))
        maxCustomers = round(config.FRAC_MAX_DISTRIBUTION * base)
        # print("maxCustomers:")
        # print(maxCustomers)
        # print(unallocatedCustomers)
        for cst in unallocatedCustomers:
            depotsDistances = unallocatedCustomers[cst].get_depotsDistances()
            depotsAvailable = []
            # recuperar apenas depósitos com vagas

            for dptDist in depotsDistances:
                for adpts in SplitDepots._availableDepots:
                    if str(dptDist[0]) == adpts[0]:
                        depotsAvailable.append(dptDist)
                        break

            # print("saiu do for")
            # print(depotsAvailable)

            if len(depotsAvailable) > 1:
                fstDepot = depotsAvailable[0]  # primeiro depósito mais próximo
                sndDepot = depotsAvailable[1]  # segundo depósito mais próximo
                fstDistance = fstDepot[1]  # distância do primeiro depósito
                sndDistance = sndDepot[1]  # distância do segundo depósito
                ratio = fstDistance / float(sndDistance)
                auxiliar.append(
                    [unallocatedCustomers[cst], ratio,
                     str(fstDepot[0])])
            elif len(depotsAvailable) == 1:
                fstDepot = depotsAvailable[0]  # primeiro depósito mais próximo
                ratio = 1.0
                auxiliar.append(
                    [unallocatedCustomers[cst], ratio,
                     str(fstDepot[0])])
        # print("check")
        # print(unallocatedCustomers[cst])
        # ordenar lista auxiliar em ordem decrescente
        pts = sorted(auxiliar, key=lambda x: x[1], reverse=True)
        # print("pts:")
        # print(pts)
        # print(SplitDepots._individual)
        for dpt in SplitDepots._availableDepots:
            control = 0
            for pt in pts:
                # print(pt)
                if dpt[0] == pt[2]:
                    dpt[2] = dpt[2] + pt[0].get_demand()
                    dpt[3] = dpt[3] + 1
                    # demanda total > carga total (considera cheio)
                    if (dpt[2] > dpt[1] or dpt[3] > maxCustomers):
                        if numberDepotsAvailable > 1:
                            dpt[2] = dpt[2] - pt[0].get_demand()
                            dpt[3] = dpt[3] - 1

                            dpt[0] = "-1"
                            numberDepotsAvailable -= 1
                            #print("é menor")
                        else:  # se ainda faltarem clientes para serem alocados e restar apenas 1 depósito, a carga total será desrespeitada
                            #print("último depósito disponível")
                            # print(SplitDepots._availableDepots)
                            # adiciona o cliente no depósito mais próximo
                            SplitDepots._individual.addGiantTour(
                                pt[0], depots[dpt[0]])
                            # remove da lista de unallocatedCustomers
                            unallocatedCustomers.pop(str(pt[0].get_id()), -1)
                            control += 1
                    else:
                        # adiciona o cliente no depósito mais próximo
                        SplitDepots._individual.addGiantTour(
                            pt[0], depots[dpt[0]])
                        # remove da lista de unallocatedCustomers
                        unallocatedCustomers.pop(str(pt[0].get_id()), -1)
                        control += 1

        # print(":")
        # print(SplitDepots._availableDepots)
        # print(unallocatedCustomers)
        # print(SplitDepots._availableDepots)
        if len(unallocatedCustomers) > 0:
            return SplitDepots.GilletJohnsonProcedure(unallocatedCustomers,
                                                      numberDepotsAvailable)
        else:
            return unallocatedCustomers