Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

логистика / 0807155_B5569_tihomirova_a_n_sidorenko_e_v_matematicheskie_modeli_i_metody

.pdf
Скачиваний:
82
Добавлен:
12.03.2015
Размер:
2.02 Mб
Скачать

сравнению с жадным алгоритмом. Алгоритмы такой точности обычно называют приближенными, а не просто эвристическими.

ПРИМЕР

Задача коммивояжера. Грузовик выезжает с центральной базы для доставки товара определенному числу потребителей и возвращается впоследствии на базу. Стоимость перевозки пропорциональна пройденному расстоянию. Требуется при заданной матрице расстояний между объектами (таблица) найти путь обхода всех потребителей строго по одному разу при наименьших затратах.

Таблица 2.39. Матрица расстояний между объектами

 

1

2

3

4

5

6

1

-

6

4

8

7

14

2

6

-

7

11

7

10

3

4

7

-

4

3

10

4

8

11

4

-

5

11

5

7

7

3

5

-

7

6

14

10

10

11

7

-

РЕШЕНИЕ ПРИМЕРА Ввод:

C[i,j]-массив с весами ребер графа

Таблица 2.40. Матрица C[i,j]

 

1

2

3

4

5

6

1

-

6

4

8

7

14

2

6

-

7

11

7

10

3

4

7

-

4

3

10

4

8

11

4

-

5

11

5

7

7

3

5

-

7

6

14

10

10

11

7

-

Общий шаг:

1.Найти кратчайшее остовное дерево при помощи «жадного» алгоритма (рис. 2.53, а).

271

2

3

2

3

 

 

1

 

4

4

 

1

 

 

6

5

6

5

 

а)

б)

 

Рис.2.53. Поиск остова «жадным» алгоритмом

 

 

2

3

 

 

1

4

 

 

 

 

 

6

5

 

 

 

а)

 

 

2

3

 

 

1

4

 

 

 

 

65

б)

Рис.2.54. Сокращение выбранного пути – «сглаживание углов»

272

Вывод:

Массив p*[t].

2.Удвоить все ребра, вошедшие в кратчайший остов. Полученный граф G* – связный и его вершины имеют только четные степени (рис. 2.53, б). В графе существует эйлеров цикл.

3.Построить эйлеров цикл, начиная с вершины 1, номера вершин заносятся в массив p[t]: {1,2,1,3,4,3,5,6,5,3,1}.

4.Просматривая p[t], произвести копирование его элементов в массив p*[t], игнорируя повторно встречающиеся вершины. p*[t]: {1,2,3,4,5,6,1} – по сути мы произвели основанное на неравенстве треугольника «сглаживание», например выбирая вместо 2-1-3 прямой путь 2-3 на том основании, что в вершине 1 мы уже побывали (рис. 2.54, а,б).

Итак, алгоритм с погрешностью, равной единице, существует, и он не единственен. Однако хотелось бы иметь и точное решение. Вероятно (по крайней мере, так считается в настоящее время), точное решение может быть получено только переборными алгоритмами, вследствие чего возникают два вопроса: как наиболее эффективно осуществлять этот самый перебор и нельзя ли его как-нибудь усовершенствовать за счет отсечения заведомо неперспективных вариантов.

Алгоритм 3. Лексикографический перебор

Понятно, что практически полный перебор применим только в задачах малого размера. Выше было показано, что в задаче коммивояжера, с N объектами требует при полном переборе рассмотрения (N-1)!/2 туров в симметричной задаче и (N-1)! туров в несимметричной, а факториал, как известно, растет удручающе быстро: если при 5 объектах необходимо перебрать 24 варианта, то

при 10 эта цифра равна 362880, при 20-ти имеет порядок 1017, а при сорока – 1046.

273

Чтобы проводить полный перебор в ЗК, нужно научиться (разумеется, без повторений) генерировать все перестановки заданного числа M элементов. Это можно сделать несколькими способами, но самый распространенный и применимый вообще для переборных алгоритмов – это перебор в лексикографическом порядке.

Пусть имеются некоторый алфавит и наборы символов алфавита (букв), называемые словами. Буквы в алфавите упорядочены, а значит, можно упорядочить и слова. Скажем, дано

слово u=(u1,u2,...,uN) и слово v=(v1,v2,...,vN). Тогда если u1 < v1, то и u < v; если же u1=v1, то сравнивают вторые буквы и т.д. Символ < читается как «предшествует».

Основная идея Нужно двигаться по перестановке справа налево, пока не

появится число меньшее, чем рассмотренное перед ним. Это число надо увеличить, поставив вместо него какое-то число из расположенных правее. Число большее, чем текущее, обязательно найдется в силу начальной упорядоченности по возрастанию. Если есть несколько больших чисел, то, очевидно, надо ставить меньшее из них. Затем все числа далее до конца (кроме выбранного большего) нужно упорядочить по возрастанию. В результате получится непосредственно следующая перестановка.

Возможные сложности

В ЗК с N городами не нужны все перестановки из N элементов, потому что перестановки, скажем, 1 3 5 4 2 и 3 5 4 2 1 (последний элемент соединен с первым) задают один и тот же тур, начинающийся сначала с города 1, а потом с города 3.

Способы преодоления Нужно зафиксировать начальный город 1 и присоединять к

нему все перестановки из четырех элементов. Этот перебор даст нам (N-1)! разных туров, т.е. полный перебор в несимметричной ЗК (мы по-прежнему будем различать туры 1 3 5 4 2 и 1 2 4 5 3).

274

Формальное описание алгоритма

Ввод:

C[i,j]-массив с весами ребер графа

Инициализация:

search – логическая переменная, принимает значение «истина», если существуют еще не рассмотренные подстановки, и «ложь» если таковых больше нет, изначально равна «истина»;

P[i] – очередная подстановка, изначально заполнить номерами вершин в порядке возрастания {1,2,..,N}; Best_p[i]- массив для хранения последней самой удачной подстановки, изначально совпадает с массивом P[i];

new_res – длина гамильтонова цикла для очередной подстановки, изначально приравнять нулю;

best_res - длина гамильтонова цикла для подстановки, записанной в best_p[i], изначально

приравнять

c[1,2]+c[2,3]+…+c[N-1,N]+c[N,1].

Общий шаг:

пока

 

До

тех пор

search=true

В

цикле по i от

N до 2 (первый элемент

фиксируем)

Если p[i-1] < p[i] то search:=true; find_Min:= p[i-1];

find_Max:= Б (символ, у которого нет среди рассматриваемых последователя);

в цикле по j от i до N если (p[j]>find_Min) and (p[j]< find_Max) то

275

Схема работы алгоритма дана на рис.2.55.

 

Ввод матрицы C(i,j) – массив с

весами ребер графа

Начальная подстановка –

 

 

 

 

упорядоченная по

Сформировать подстановку p(i)

возрастанию

 

 

последовательность

 

 

вершин

Взять вершину i, начиная с

 

конца

 

 

да

p(i-1) < p(i)

нет

 

search=true

 

search=false

find_min=p(i-1)

 

 

find_max=Б

 

 

Взять вершину j,

 

 

начиная с номера

 

 

вершины i

 

 

 

нет

 

p(j)>find_min

 

 

and

 

 

p(j)<find_max

 

 

да

 

 

find_max=p(j)

 

 

Рис.2.55. Схема работы алгоритма "Лексикографический

 

перебор"(начало)

 

276

 

index=j

p(index)=find_min

p(i-1)=find_max

Отсортировать по возрастанию

new_res=new_res+c(p(i),p(i+1))

new_res<best_re

да

best_res=new_res

best_res

Рис.2.55. Схема работы алгоритма "Лексикографический перебор" (окончание)

find_Max:= p[j]; index:=j; p[index]:=find_Min;

p[i-1]:= find_Max;

в цикле по j от i до N отсортировать по возрастанию p[j];

277

В цикле по i от 1 до N-1

new_res:= new_res + c[p[i], p[i+1]]; new_res:= new_res + c[p[N], p[1]];

if new_res < best_res то best_res: = New_res

В цикле по i от 1 до N best_p[i]:=p[i]; new_res:=0 (обнуляем для последующего

использования);

Иначе search:=false.

Вывод:

best_res – длина кратчайшего гамильтонова цикла; Best_p[i] – массив, содержащий подстановку, для которой длина гамильтонова цикла равна best_res.

РЕШЕНИЕ ПРИМЕРА

Ввод: C[i,j] – массив с весами ребер графа

Таблица 2.41. Матрица C[i,j]

 

1

2

3

4

5

6

1

-

6

4

8

7

14

2

6

-

7

11

7

10

3

4

7

-

4

3

10

4

8

11

4

-

5

11

5

7

7

3

5

-

7

6

14

10

10

11

7

-

Инициализация: search:=true; P[i]:= {1,2,3,4,5,6};

best_p[i]:= {1,2,3,4,5,6}; new_res:=0; best_res:=6+7+4+5+7+14=43.

Общий шаг:

До тех пор пока search=true:

278

Перестановка №1: В цикле по i от 6 до 2 i=6:

Если p[5] < p[6] (5<6, выполняется) то search:=true;

find_min:= p[5]=5; find_max:= 9;

вцикле по j от 6 до 6 если (p[j]>find_min) and (p[j]< find_max) то

при j=6 find_max:= p[6]=6, index:=6; p[6]:=5;

p[5]:=6;

вцикле по j от 6 до 6 отсортировать по возрастанию p[j] (пока не требуется);

В цикле по i от 1 до 5:

при i=1: new_res:= 0+ c[p[1], p[2]]=c[1,2]=6;

при i=2: new_res:= 6+ c[p[2], p[3]]=6+c[2,3]=6+7=13; при i=3: new_res:= 13+ c[p[3], p[4]]=13+c[3,4]=13+4=17; при i=4: new_res:= 17+ c[p[4], p[5]]=17+c[4,6]=17+11=28; при i=5: new_res:= 28+ c[p[5], p[6]]=28+c[6,5]=28+7=35; new_res:= 35 + c[p[6], p[1]]=35+ c[5,1]=35+7=42;

if new_res < best_res (42<43, выполняется) то best_res: = 42;

В цикле по i от 1 до N best_p[i]:=p[i]={1,2,3,4,6,5} new_res:=0;

Иначе …

(итак, получилась перестановка 1 2 3 4 6 5 с весом 42, что лучше чем предыдущий результат, поэтому вес запомним в переменной best_res, а саму подстановку в массиве best_p[i])

Перестановка №2 (на данный момент p[i]={1 2 3 4 6 5}) В цикле по i от 6 до 2

При i=6:

Если p[5] < p[6] (6<5, не выполняется) то … Иначе search:=false;

При i=5:

279

Если p[4] < p[5] (4<6, выполняется) то search:=true;

find_min:= p[4]=4; find_max:= 9;

вцикле по j от 5 до 6 если (p[j]>find_min) and (p[j]< find_max) то

при j=5 (p[5]>4) and (p[5]< 9) find_max:= p[5]=6, index:=5; при j=6 (p[6]>4) and (p[6]< 6) find_max:= p[6]=5, index:=6; p[4]:=5;

p[6]:=4;

вцикле по j от 5 до 6 отсортировать по возрастанию p[j];

(из массива {1,2,3,5,6,4} получим {1,2,3,5,4,6});

В цикле по i от 1 до 5:

при i=1: new_res:= 0+ c[p[1], p[2]]=c[1,2]=6;

при i=2: new_res:= 6+ c[p[2], p[3]]=6+c[2,3]=6+7=13; при i=3: new_res:= 13+ c[p[3], p[4]]=13+c[3,5]=13+3=16; при i=4: new_res:= 16+ c[p[4], p[5]]=16+c[5,4]=16+5=21; при i=5: new_res:= 21+ c[p[5], p[6]]=21+c[4,6]=21+11=32; new_res:= 32 + c[p[6], p[1]]=32+c[6,1]=32+14=46;

if new_res < best_res (46<42, не выполняется) то .. new_res:=0;

Иначе … (итак, получилась перестановка 1 2 3 5 4 6 с весом 46, что хуже,

чем предыдущий результат 42).

Аналогично будут получены прочие подстановки: приведем их сначала для иллюстрации собственно лексикографического перебора без расчета веса соответствующего гамильтонова цикла. Подчеркнут элемент, меньший предыдущего при просмотре массива с конца. Жирным шрифтом выделен элемент, на который будет осуществляться замена. Курсивом отмечена часть массива, нуждающаяся в сортировке по возрастанию.

№0: 1 2 3 4 5 6

№1: 1 2 3 4 6 5 делаем замену 1 2 3 5 6 4 и после сортировки получим:

№2: 1 2 3 5 4 6

№3: 1 2 3 5 6 4 делаем замену 1 2 3 6 5 4 и после сортировки получим:

280