Untitled

 avatar
unknown
python
2 years ago
8.5 kB
4
Indexable
# 8) Для размещения магазинов в торговом центре выделено 200 млн руб. и площадь 2 км2. На территории торгового
# центра необходимо разместить магазины. Сгенерировать множество из 400 магазинов со следующими параметрами:
# стоимость размещения магазина в интервале [10;20] млн руб.; посещаемость магазина [1;10] тыс. человек;
# занимаемая магазином площадь в интервале [50;150] м2. Требуется найти комбинацию магазинов, обеспечивающих
# максимальную посещаемость торгового центра.
import random as rnd
import matplotlib.pyplot as plt
from random import randint, random

# Ограниченное количество ресурсов
BUDGET = 200
MALL_SQUARE = 2000000

# Параметры работы генетического алгоритма
CHROMOSOME_SIZE = 400
POPULATION_SIZE = 400
P_CROSSOVER = 0.9
P_MUTATION = 0.01
MAX_GENERATIONS = 3000

# Параметры генератора случайных чисел
RANDOM_SEED = 5
rnd.seed(RANDOM_SEED)


class Furniture:
    def __init__(self):
        self.cost_placement = randint(10, 20)
        self.attendance = randint(1, 10)
        self.square = randint(50, 150)


class FitnessMax():
    def __init__(self):
        self.value = 0


class Individual(list):
    def __init__(self, *args):
        super().__init__(*args)
        self.fitness = FitnessMax()


def one_max_fitness(individual):
    budget_expenses, square_expenses = get_budget_square_expenses(individual)
    attendance = get_attendance(individual)

    kb = 0 if budget_expenses < BUDGET else attendance
    ks = 0 if square_expenses < MALL_SQUARE else attendance

    fitness = attendance - kb * (budget_expenses - BUDGET) - ks * (square_expenses - MALL_SQUARE)
    return fitness


def get_attendance(individual):
    attendance = 0
    for gene in individual:
        if gene:
            attendance = attendance + gene.attendance
    return attendance


def get_budget_square_expenses(individual):
    budget_expenses = 0
    square_expenses = 0
    for gene in individual:
        if gene:
            budget_expenses = budget_expenses + gene.cost_placement
            square_expenses = square_expenses + gene.square
    return budget_expenses, square_expenses


def create_basic_set():
    genes = []
    for i in range(CHROMOSOME_SIZE):
        genes.append(Furniture())
    return Individual(genes)


def individual_creator(basic_set):
    genes = []
    for i in range(CHROMOSOME_SIZE):
        if random() >= 0.5:
            genes.append(basic_set[i])
        else:
            genes.append(None)
    return Individual(genes)


def population_creator(basic_set, n=POPULATION_SIZE):
    return list([individual_creator(basic_set) for i in range(n)])


def clone(value):
    ind = Individual(value[:])
    ind.fitness.value = value.fitness.value
    return ind


def selection(population, basic_set):
    population.sort(key=lambda x: x.fitness.value, reverse=True)
    elite = population[:50]
    population = population_creator(basic_set)
    population[:50] = elite[:50]
    return population


def crossover_two_point(child1, child2):
    point_1 = 0
    point_2 = 0
    while point_1 >= point_2:
        point_1 = randint(2, len(child1) - 3)
        point_2 = randint(2, len(child1) - 3)
    child1[point_1:point_2], child2[point_1:point_2] = child2[point_1:point_2], child1[point_1:point_2]


def genetic_mutation(mutant, basic_set):
    for index in range(len(mutant)):
        if random() < P_MUTATION:
            mutant[index] = None if mutant[index] else basic_set[index]



if __name__ == '__main__':
    best_individuals = []
    basic_set = create_basic_set()
    population = population_creator(basic_set)
    generation_counter = 0

    fitness_values = list(map(one_max_fitness, population))
    for individual, fitness_value in zip(population, fitness_values):
        individual.fitness.value = fitness_value

    max_fitness_values = []
    mean_fitness_values = []
    min_budget_square_expenses_values = []

    while generation_counter < MAX_GENERATIONS:
        generation_counter += 1
        offspring = selection(population, basic_set)
        offspring = list(map(clone, offspring))

        for child1, child2 in zip(offspring[::2], offspring[1::2]):
            if random() < P_CROSSOVER:
                crossover_two_point(child1, child2)

        fresh_fitness_values = list(map(one_max_fitness, offspring))
        for individual, fitness_value in zip(offspring, fresh_fitness_values):
            individual.fitness.value = fitness_value

        population[:] = offspring

        fitness_values = [ind.fitness.value for ind in population]

        max_fitness = max(fitness_values)
        max_fitness_index = fitness_values.index(max_fitness)
        min_budget_square_expenses = get_budget_square_expenses(population[max_fitness_index])

        mean_fitness = sum(fitness_values) / len(population)
        max_fitness_values.append(max_fitness)
        mean_fitness_values.append(mean_fitness)
        min_budget_square_expenses_values.append(min_budget_square_expenses)
        print(
            f"Поколение {generation_counter}: Макс приспособленность = {max_fitness}, Средняя приспособленность = {mean_fitness}")

        best_index = fitness_values.index(max(fitness_values))
        best_individual = population[best_index]
        best_individuals.append(best_individual)

        print("Лучший индивидуум = ", *best_individual)
        budget_square_expenses = get_budget_square_expenses(best_individual)
        print(f"Потрачено: {budget_square_expenses[0]} млн руб, {budget_square_expenses[1]} м2")
        print(f"Посещения: {get_attendance(best_individual)} тыс человек")
        print()

    budget_expenses_values = [i[0] for i in min_budget_square_expenses_values]
    square_expenses_values = [i[1] for i in min_budget_square_expenses_values]

    plt.plot(max_fitness_values, color='red')
    plt.plot(mean_fitness_values, color='green')
    plt.legend(["Максимальная приспособленность, кол-во тыс", "Средняя приспособленность, кол-во тыс"])
    plt.xlabel('Поколение, число')
    plt.ylabel('Макс/средняя приспособленность, кол-во тыс')
    plt.title('Зависимость максимальной и средней приспособленности от поколения')
    plt.grid()
    plt.show()

    plt.plot(budget_expenses_values, color='red')
    plt.plot(square_expenses_values, color='green')
    plt.legend(["Расход бюджета, млн руб", "Расход площади, м2"])
    plt.xlabel('Поколение, число')
    plt.ylabel('Расход бюджета/площади, млн руб/м2')
    plt.title('Расход бюджета и площади от поколения')
    plt.grid()
    plt.show()

    best_individuals_chromosome_sum = [ sum(x is not None for x in chromosomes) for chromosomes in best_individuals]
    plt.plot(best_individuals_chromosome_sum)
    plt.xlabel('Поколение, число')
    plt.ylabel('Число единиц в хромосоме лучшего индивидуума, число')
    plt.title('Число ед-ц в хромосоме лучшего индивидуума в зав-ти от поколения')
    plt.grid()
    plt.show()

    best_individuals.sort(key=lambda x: x.fitness.value, reverse=True)
    best_individual = best_individuals[0]
    print("Лучший индивидуум за всё время = ", best_individual)
    budget_square_expenses = get_budget_square_expenses(best_individual)
    print(f"Потрачено: {budget_square_expenses[0]} млн руб, {budget_square_expenses[1]} м2")
    print(f"Посещения: {get_attendance(best_individual)} тыс человек")
    print()
Editor is loading...