VRP-System / DE_GUI.py
DE_GUI.py
Raw
import math
from random import sample, random
from tkinter import *
import matplotlib.pyplot as plt
from DP import preparation as DP
import pandas as pd


def get_cities():
    df = pd.read_excel(r'data.xlsx')
    cities = {}
    for i in range(len(df)):
        cities[df.iloc[i][0]] = [df.iloc[i][1], df.iloc[i][2]]
    return cities


cities = get_cities()
listOfCities = list(cities.keys())
best = []
generation = []


def initializePopulation(populationSize=100, numberOfTrucks=4):
    population = []
    for i in range(populationSize):
        shuffuledCities = sample(listOfCities, len(listOfCities))

        individual = []

        for z in range(numberOfTrucks):
            individual.append(" ")

        c = 0
        for x in range(len(shuffuledCities)):
            if (c == numberOfTrucks):
                c = 0
            individual[c] += shuffuledCities[x]
            c += 1

        individual = ''.join(individual)

        population.append(individual.strip())
    population = convertPopulation(population, number=True)
    return population


def convertPopulation(population, number=False):
    convertedPopulation = []
    for individual in population:
        individualList = []
        for gene in individual:
            if number:
                individualList.append(ord(gene))
            else:
                individualList.append(chr(gene))
        if not number:
            individualList = ''.join(individualList)
        convertedPopulation.append(individualList)
    return convertedPopulation


def ensure(donor, bound):
    min = bound[0]
    max = bound[1]
    v = []

    for d in donor:
        if d == 32:
            v.append(32)
        else:
            if d < min:
                v.append(min)
            elif d > max:
                v.append(max)
            elif min <= d <= max:
                v.append(d)
    return v


def crossOver(target, donor, r):
    v = []
    for i in range(len(target)):
        rand = random()

        if r <= rand:
            v.append(donor[i])
        else:
            v.append(target[i])

    return v


def calc_distance(x1, y1, x2, y2):
    return (((x2 - x1) ** 2) + ((y2 - y1) ** 2)) ** 0.5


def calc_cost(population):
    dict = cities
    individual = {}
    cost = 2

    c = 0
    for x in population:
        individual[c] = x.split()
        c += 1

    sum = 0
    totalCost = []
    for v in individual.values():

        for x in v:

            for j in range(len(x)):

                if j == 0 or j == len(x) - 1:
                    x1 = dict['Start'][0]
                    y1 = dict['Start'][1]
                    x2 = dict[x[j]][0]
                    y2 = dict[x[j]][1]
                    dist = calc_distance(x1, y1, x2, y2)
                    sum += dist
                    continue

                x1 = dict[x[j]][0]
                y1 = dict[x[j]][1]
                x2 = dict[x[j - 1]][0]
                y2 = dict[x[j - 1]][1]
                dist = calc_distance(x1, y1, x2, y2)
                sum += dist

        totalCost.append(int(sum) * cost)
        sum = 0
    return totalCost


def calc_fitness(population, target=9000):
    fit = []
    total = calc_cost(population)
    for x in total:
        fit.append(target - x)
    return fit


def replaceDuplicates(individual):
    individualList = []
    for gene in individual:
        individualList.append(chr(gene))
    individual = ''.join(individualList)

    cities1 = listOfCities.copy()

    str1 = ""
    for i in individual:
        if i in cities1:
            cities1.remove(i)
            str1 += i
        else:
            if i == " ":
                str1 += " "
            else:
                str1 += "*"

    child1 = ""
    for i in str1:
        if i == "*":
            child1 += cities1[0]
            del cities1[0]
        else:
            child1 += i

    return child1


def select(population, j, target, trial):
    if calc_fitness([replaceDuplicates(target)])[0] > calc_fitness([replaceDuplicates(trial)])[0]:
        population[j] = target
    else:
        population[j] = trial


def mutate(randIndex, population, factor, bound):
    x_1 = population[randIndex[0]]
    x_2 = population[randIndex[1]]
    x_3 = population[randIndex[2]]

    diff = [x2 - x3 for x2, x3 in zip(x_2, x_3)]

    donor = [math.ceil(x1 + factor * diff_i) for x1, diff_i in zip(x_1, diff)]
    donor = ensure(donor, bound)
    return donor

gtarget = 9000
numberOfTrucks = 4
populationSize = 100
xx=0 
yy=0
def evolve(factor=0.5, Generationlimit=10, recombinationFactor=0.7, bound=[65, 90]):
    global truck, entry1, entry2, targetValue, gtarget, numberOfTrucks, populationSize, cities, xx, yy
    cities["Start"] = [float(entry1.get()), float(entry2.get())]
    gtarget = int(targetValue.get())
    numberOfTrucks = int(truck.get())
    populationSize = populationSize

    population = initializePopulation(populationSize, numberOfTrucks)
    bestIndividual = convertPopulation([population[0]])[0]

    for i in range(1, Generationlimit + 1):

        print('Generation #', i, ': ')

        for j in range(len(population)):

            indices = list(range(0, len(population)))
            indices.remove(j)
            xtarget = population[j]
            randIndex = sample(indices, 3)

            donor = mutate(randIndex, population, factor, bound)

            trial = crossOver(xtarget, donor, recombinationFactor)

            select(population, j, xtarget, trial)

            pop = convertPopulation(population)

            for p in pop:
                generation.append(p)
                if calc_fitness(bestIndividual) < calc_fitness(p):
                    bestIndividual = p
                    best.append(bestIndividual)

        print(calc_fitness([bestIndividual])[0], bestIndividual)

    create_map(generation,best)


def GUI():
    global entry1, entry2, truck, targetValue
    window = Tk()
    window.title('VRP')
    window.geometry('400x350')
    window.resizable(False, False)

    Label(window, text="Start Point", fg='blue', font=("Arial", 17)).place(x=160, y=20)

    Label(window, text="X :", font=("bold", 10)).place(x=120, y=70)

    Label(window, text="Y :", font=("bold", 10)).place(x=120, y=120)

    Label(window, text="Number of Trucks:", font=("bold", 10)).place(x=12, y=170)

    Label(window, text="Expected Value :", font=("bold", 10)).place(x=15, y=220)

    entry1 = Entry(window)
    entry1.place(x=150, y=70)

    entry2 = Entry(window)
    entry2.place(x=150, y=120)

    truck = Entry(window)
    truck.place(x=150, y=170)

    targetValue = Entry(window)
    targetValue.place(x=150, y=220)

    Button(window, text='Next', relief="flat", bg='blue', fg='white', font=("bold"), command=evolve).place(x=180, y=260)

    window.mainloop()


def create_line(coordinates, n):
    lineColor = ["red", "blue", "yellow", "green", "black", "brown", "cyan", "magenta"]
    for i in range(len(coordinates) - 1):
        plt.plot([coordinates[i][0], coordinates[i + 1][0]], [coordinates[i][1], coordinates[i + 1][1]],
                 color=lineColor[n])
        plt.pause(0.00001)


def create_map(generations, bestPath):
    m = DP.create_dictionary()
    lineColor = ["red", "blue", "yellow", "green", "black", "brown", "cyan", "magenta"]
    coordinates = []
    coordinates.append(m["Start"])
    c = 1
    n = 0
    for str in generations:

        str += " "
        plt.cla()
        plt.title("Locations", fontsize=20)
        plt.scatter(coordinates[0][0], coordinates[0][1], s=100, color=lineColor[0])
        plt.annotate("Start", (coordinates[0][0], coordinates[0][1] + 10))
        plt.xlabel("X", fontweight='bold')
        plt.ylabel("Y", fontweight='bold')
        for x in str:

            if (x == " "):
                coordinates.append(m["Start"])
                create_line(coordinates, n)
                coordinates = []
                coordinates.append(m["Start"])
                n += 1
                if n == len(lineColor):
                    n = 0
                c = 1
            else:
                coordinates.append(m[x])
                plt.scatter(coordinates[c][0], coordinates[c][1], s=40, color=lineColor[n])
                plt.annotate(x, (coordinates[c][0], coordinates[c][1] + 10))
                c += 1
        plt.pause(1)

    bestPath += " "
    plt.show()
    plt.title("Optimal Solution", fontsize=20)
    plt.scatter(coordinates[0][0], coordinates[0][1], s=100, color=lineColor[0])
    plt.annotate("Start", (coordinates[0][0], coordinates[0][1] + 10))
    plt.xlabel("X", fontweight='bold')
    plt.ylabel("Y", fontweight='bold')

    for z in bestPath:

        if (z == " "):
            coordinates.append(m["Start"])
            create_line(coordinates, n)
            coordinates = []
            coordinates.append(m["Start"])
            n += 1
            if n == len(lineColor):
                n = 0
            c = 1
        else:
            coordinates.append(m[z])
            plt.scatter(coordinates[c][0], coordinates[c][1], s=40, color=lineColor[n])
            plt.annotate(z, (coordinates[c][0], coordinates[c][1] + 10))
            c += 1