Академический Документы
Профессиональный Документы
Культура Документы
КОНТРОЛЬНАЯ РАБОТА
Выполнил обучающийся:
Широхов Игорь Владимирович
(Ф.И.О.)
Направление подготовки:
09.03.02 Информационные системы и технологии
(код и наименование)
Курс: 5
Группа: 353818
Руководитель:
Р.А. Воронцов, ассистент
(Ф.И.О. руководителя, должность / уч. степень / звание)
Отметка о зачете
(отметка прописью) (дата)
Архангельск 2022
МИНИСТЕРСТВО НАУКИ И ВЫСШЕГО ОБРАЗОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ
федеральное государственное автономное образовательное учреждение
высшего образования
«Северный (Арктический) федеральный университет имени М.В. Ломоносова»
п
по Интеллектуальные системы и технологии
(наименование дисциплины)
студенту ВШИТиАС высшей школы 5 курса 353818 группы
Широхов Игорь Владимирович
(фамилия, имя, отчество студента)
09.03.02 «Информационные системы и технологии»
(код и наименование направления подготовки/специальности)
ТЕМА: Решение задачи коммивояжера при помощи генетического
алгоритма Вариант № 30
ИСХОДНЫЕ ДАННЫЕ:
Необходимо разработать программную реализацию генетического алгоритма,
решающего задачу коммивояжера на основе матриц расстояний. В качестве оператора
скрещивания должно быть использовано циклическое скрещивание
Архангельск 2022
ЛИСТ ДЛЯ ЗАМЕЧАНИЙ
ОГЛАВЛЕНИЕ
Введение...........................................................................................................................5
1 Описание задачи и метода ее решения.......................................................................6
2 Решение задачи коммивоежера.................................................................................10
Заключение.....................................................................................................................17
Список использованных источников...........................................................................18
Приложение А (обязательное) Код генетического алгоритма..................................19
ВВЕДЕНИЕ
5
1 ОПИСАНИЕ ЗАДАЧИ И МЕТОДА ЕЁ РЕШЕНИЯ
6
Рисунок 1 – Последовательность работы алгоритма
7
Поэтому они могут работать с функциями, которые трудно или невозможно
продифференцировать.
В задаче коммивояжера имеется десять городов, расстояния между
которыми представлены матрицей расстояний, состоящей из 10 столбов и 10
строк, где на пересечении строки и столбца находится расстояние между
соответствующими городами.
Решение представим в виде перестановки чисел от 1 до 10, отображающей
последовательность посещения городов. А значение целевой функции будет
равно стоимости всей поездки, вычисленной в соответствии с матрицей.
Все элементы будем записывать в виде списка, состоящего из 11 элементов,
так как необходимо посетить 10 городов и вернуться в начальный пункт. Пример
показан на рисунке 2.
8
В нашей задаче необходимо найти минимальный путь, это говорит о том,
что значение функции оценки должно быть минимальным. Поэтому для решения
поставленной задачи необходимо будет инвертировать ее значение.
Цель генетических алгоритмов – найти оптимальное решение некоторой
задачи. Если дарвиновская эволюция развивает популяцию отдельных особей, то
генетические алгоритмы развивают популяцию потенциальных решений данной
задачи.
В результате решения задачи коммивояжера должен быть представлен путь,
имеющий наименьшую длину, которая была получена в ходе работы
генетического алгоритма.
9
2 РЕШЕНИЕ ЗАДАЧИ КОММИВОЕЖЕРА
11
После формирования родительского пула – из него формируются пары.
Пары образуются случайным образом так, чтобы в них не было одинаковых
элементов.
Функция «createPara» представляет собой описание формирования пар из
родительского пула. В данной функции в цикле формируются уникальные пары
без повторов, пока их число не станет кратным 5.
Исходный код данной функции представлен на листинге 4.
Листинг 4 – Функция формирования пар
# Формирование пар
def createPara(elements):
paras = []
while len(paras)<5:
para = []
choice1 = random.randint(0,9)
choice2 = random.randint(0,9)
paraex1 = elements[choice1]
paraex2 = elements[choice2]
if paraex1 != paraex2:
count = 0
for el in paras:
if (el[0] == paraex1 and el[1] == paraex2) or
(el[0]==paraex2 and el[1]==paraex1):
count += 1
if count==0:
para.append(paraex1)
para.append(paraex2)
paras.append(para)
return paras
for i in range(1,5):
count_p1c1=0
for it in ch1:
if it == par1[i]:
count_p1c1 += 1
count_p1c2=0
for it in ch2:
if it == par2[i]:
count_p1c2 += 1
if count_p1c1==0:
ch1[i]=par1[i]
else:
for s in range(i+1,i+5):
if par1[s] not in ch1:
ch1[i]=par1[s]
break
if count_p1c2==0:
ch2[i]=par2[i]
else:
for s in range(i+1,i+5):
if par2[s] not in ch2:
ch2[i]=par2[s]
break
count_p2c1=0
for it in ch1:
if it == par2[10-i]:
13
count_p2c1 += 1
count_p2c2=0
for it in ch2:
if it == par1[10-i]:
count_p2c2 += 1
if count_p2c1 ==0:
ch1[10-i]=par2[10-i]
else:
for d in range(10-i,1,-1):
if par2[d] not in ch1:
ch1[10-i]=par2[d]
break
if count_p2c2 ==0:
ch2[10-i]=par1[10-i]
else:
for d in range(10-i,1,-1):
if par1[d] not in ch2:
ch2[10-i]=par1[d]
break
ch1it5 = 0
for ile in par1:
if ile not in ch1:
ch1it5=ile
ch1[5]=ch1it5
ch2it5 = 0
for ile in par1:
if ile not in ch2:
ch2it5=ile
ch2[5]=ch2it5
childrens.extend([ch1,ch2])
return childrens
print("Кратчайший путь
-",m_f_values[massive.index(min(massive))],"Длина -",min(massive))
break
else:
new_population = salesman(w)
w[:]=new_population
fin_f_values=elements_f_values(w)
freshFitn=(min(fin_f_values))
massive.append(freshFitn)
m_f_values.append(w[fin_f_values.index(min(fin_f_values))])
15
Для расчетов нам необхома матрица расстояний. Её будем хранить в виде
массива, представленного на рисунке 3.
16
ЗАКЛЮЧЕНИЕ
17
СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ
18
ПРИЛОЖЕНИЕ А
(обязательное)
Код генетического алгоритма
import random
matrix = [
[0,3,2,1,7,8,9,1,2,9],
[3,0,1,5,7,3,2,1,5,7],
[2,1,0,1,5,7,4,1,2,5],
[1,5,1,0,2,8,4,4,3,9],
[7,7,5,2,0,9,2,2,1,8],
[8,3,7,8,9,0,1,3,9,3],
[9,2,4,4,2,1,0,5,2,1],
[1,1,1,4,2,3,5,0,5,3],
[2,5,2,3,1,9,2,5,0,9],
[9,7,5,9,8,3,1,3,9,0],
]
def f(el):
dist = 0
for i in range(0,10):
dist +=matrix[el[i]-1][el[i+1]-1]
return dist
def elements_f_values(elements):
mass=[]
for element in elements:
value=f(element)
mass.append(value)
return mass
def v(el,sumf):
return el/sumf*100
def v_elements(f_elements):
mass=[]
for element in f_elements:
val=v(1/element,sum([(1/x) for x in f_elements]))
mass.append(val)
return mass
19
def roulette(v_elements):
mas = []
sum_el = 0
for i in v_elements:
sum_el += i
mas.append(sum_el)
new_parents = []
for i in range(0, 10):
num = random.randint(0,100)
for pos in mas:
if pos >=num:
el_index = mas.index(pos)
new_parents.append(el_index)
break
return new_parents
def createPara(elements):
paras = []
while len(paras)<5:
para = []
choice1 = random.randint(0,9)
choice2 = random.randint(0,9)
paraex1 = elements[choice1]
paraex2 = elements[choice2]
if paraex1 != paraex2:
count = 0
for el in paras:
if (el[0] == paraex1 and el[1] == paraex2) or
(el[0]==paraex2 and el[1]==paraex1):
count += 1
if count==0:
para.append(paraex1)
para.append(paraex2)
paras.append(para)
return paras
for i in range(1,5):
count_p1c1=0
for it in ch1:
if it == par1[i]:
count_p1c1 += 1
count_p1c2=0
20
for it in ch2:
if it == par2[i]:
count_p1c2 += 1
if count_p1c1==0:
ch1[i]=par1[i]
else:
for s in range(i+1,i+5):
if par1[s] not in ch1:
ch1[i]=par1[s]
break
if count_p1c2==0:
ch2[i]=par2[i]
else:
for s in range(i+1,i+5):
if par2[s] not in ch2:
ch2[i]=par2[s]
break
count_p2c1=0
for it in ch1:
if it == par2[10-i]:
count_p2c1 += 1
count_p2c2=0
for it in ch2:
if it == par1[10-i]:
count_p2c2 += 1
if count_p2c1 ==0:
ch1[10-i]=par2[10-i]
else:
for d in range(10-i,1,-1):
if par2[d] not in ch1:
ch1[10-i]=par2[d]
break
if count_p2c2 ==0:
ch2[10-i]=par1[10-i]
else:
for d in range(10-i,1,-1):
if par1[d] not in ch2:
ch2[10-i]=par1[d]
break
ch1it5 = 0
for ile in par1:
if ile not in ch1:
ch1it5=ile
ch1[5]=ch1it5
21
ch2it5 = 0
for ile in par1:
if ile not in ch2:
ch2it5=ile
ch2[5]=ch2it5
childrens.extend([ch1,ch2])
return childrens
def salesman(old_population):
el_f = elements_f_values(old_population)
el_v = v_elements(el_f)
ro = roulette(el_v)
pa = createPara(ro)
new_population = crossCycle(pa,old_population)
return new_population
w=first_population()
fin_f_values=elements_f_values(w)
m_f_values=[]
massive=[]
massive.append(min(fin_f_values))
m_f_values.append(w[fin_f_values.index(min(fin_f_values))])
for generationCounter in range(1,50):
if len(massive)>=5:
last_index=len(massive)-1
print(len(massive))
last1_mean = massive[last_index]
last2_mean = massive[last_index - 1]
last3_mean = massive[last_index - 2]
last4_mean = massive[last_index - 3]
print(last1_mean, last2_mean, last3_mean, last4_mean)
if (1/last4_mean - 1/last3_mean) + (1/last3_mean -
1/last2_mean) + (1/last2_mean - 1/last1_mean) < 0.01:
new_population = salesman(w)
w[:]=new_population
fin_f_values=elements_f_values(w)
freshFitn=(min(fin_f_values))
massive.append(freshFitn)
m_f_values.append(w[fin_f_values.index(min(fin_f_values)
)])
else:
print("Кратчайший путь
-",m_f_values[massive.index(min(massive))],"Длина -",min(massive))
break
else:
new_population = salesman(w)
w[:]=new_population
fin_f_values=elements_f_values(w)
22
freshFitn=(min(fin_f_values))
massive.append(freshFitn)
m_f_values.append(w[fin_f_values.index(min(fin_f_values))])
23