Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Алгоритмы > Задача коммивояжера


Автор: Graf Zeppelin 19.4.2004, 14:49
На практике столкнулся с такой проблемой: есть сверлильный станок для него существуе задание просверлить N дырок и вернутся в исходную позицию. Координаты дырок известны, нужно минимизировать пройденный путь.
ЗЫ Мне посоветовали читать книжки по теории графов sad.gif

Автор: Alex101 19.4.2004, 16:27
Если на плоскости, то это типичная задача коммивояжера.
Оптимизировать можно, отсекая лишние ветви, если уже на i-том шаге путь станка больше какого-то полученного. А вообще посмотри метод Литтла. Вроде как он позволяет решать задачу для N (кол-ва городов) в районе 30-50...

Автор: Graf Zeppelin 25.4.2004, 11:01
Плиз дайте ссылку.

Автор: Maverick 6.5.2004, 08:52
http://alglib.manual.ru/

Там только блок-схема была в прошлый раз.... но на безрыбье....

Автор: Lem03 6.5.2004, 13:45
Можно использовать генетический алгоритм. Поищи "Konstantin Boukreev" , он написал программу на эту тему и выложил исходник. Правда генетические алгоритмы довольно медленные.

Автор: Graf Zeppelin 7.5.2004, 23:32
http://www.codeproject.com/cpp/tspapp.asp
Буду разбириться

Автор: Golod 8.5.2004, 08:54
Алгоритм решения задачи комивояжера: (алгоритм жадный, так что он может давать оптимальное решение, а может и не давать, но не жадного алгоритма нет т.к. задача NP-полна)
1)Начинаем строить цикл, включив в него ребро наименьшего веса;
2)Среди рёбер, инцедентных концам нашего ребра, находится ребро наименьшего веса(весом будет расстояние между дырками) и тоже включается в цикл;
3)Если построили цепь, то просматриваем рёбра, инцедентные концам цепи, и не образующие цикл с уже включёнными рёбрами, выбираем наименьшее и включаем;
4)Пункт 3 повторяем, пока не закончатся вершины, а потом соединяем последнюю и первую вершины.
Вот и весь алгоритм. Его удобнее всего реализовать методом расстановки меток.

Автор: Crot 13.5.2004, 05:59
А скажите, задача коммивояжёра определена для полного графа, или для любого?

Автор: Guest 13.5.2004, 10:20
Hello, ALL !

Если путь замкнутый, то видимо для любого.

В случае с печ-ми платми, прирост производит-ти станка при замене пути,
может достичь ~30 % (где вычитал не помню, давно это было)
Реальный экономический эффект, без "большого" напряга :-)
Когда-то я пробовал решать эту задачу по алгоритму, схожему с предложенным
Golod-ом, но с некоторым отличием. Внедрить, увы не удалось, т к на тот момент
все производства "дохли" ... :-( Попробуйте, может у вас что-то получится.

Итак, алгоритм:

1) в составленной матрице из _расстояний_ между точками выбираем самую
"дальнюю" точку (можно по макс расст или по сумме всех расст. Я брал 1-й вар )
2) вкл в маршрут _две_ ближайшие точки
3) добавить в маршрут точку с наименьшей ценой, т е включение которой даёт
_наименьшее_ приращение длинны маршрута. Включение этой точки
производится перебором включением во все рёбра уже имеющегося маршрута.
Есс-но выбирается вставка в то ребро, где приращение маршрута наименьше.
4) ... и так далее, пока не будут вставлены в маршрут все точки.

Была и вторая часть, оптимизатор, но сейчас точно я его не помню :-(
Если найду, кину. Эх, давно это было ... :-(

Удачи !

Автор: maxim1000 13.5.2004, 11:37
кстати, а сколько отверстий? (приблизительно)

Автор: Graf Zeppelin 14.5.2004, 11:22
Цитата(maxim1000 @ 13.5.2004, 11:37)
кстати, а сколько отверстий? (приблизительно)

~100 в худшем случае
p.s. уже потихоньку врубаюсь в книжку Кристофидеса "Графы.
Алгоритмический подход"

Автор: Гость_Eugene 14.5.2004, 11:29
В догонку wink.gif

Как вариант:
п 2 можно изменить на включение 2-х или 3-х самых дальних точек,
что-бы охватить сразу _весь_ периметр печатной платы.
Этот вариант у меня тоже был. Экспериментируйте...

Удачи !

Автор: LSD 14.5.2004, 20:07
Цитата(Crot @ 13.5.2004, 05:59)
А скажите, задача коммивояжёра определена для полного графа, или для любого?

Решение есть если граф Гамильтонов, задача определения являеся ли граф Гамильтоновым NP полная, но полный граф всегда Гамильтонов.

Автор: achmed 14.5.2004, 20:18
в догонку могу посоветовать книгу Мину, тоже по графам.

Автор: HalkaR 17.5.2004, 20:57
http://algolist.manual.ru

Вобщем там есть достаточно простые методы. Хотя там нет методов ветвей и границ.

Автор: Ruff18 11.6.2004, 17:15
[color=darkblue][/color]
А где можно качнуть решение задачи о комивояжёре на С++ или Paskale ? thumbs-up.gif

Автор: Graf Zeppelin 25.6.2004, 23:06
/*
Решение Задачи Коммивояжера методом Монте-Карло
Лебедев Сергей 21.06.2004
*/
#include <string.h>
#include <stdlib.h>
#include <conio.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <alloc.h>
#include <graphics.h>

int x[255],y[255];

int minimum(long dis[1000],int n)
{
unsigned long i,tmp,f;
tmp=800;
for (i=0;i<n;i++)
{
if (dis[i]<=tmp)
{
f=i;
tmp=dis[f];
}
}
return(f);
}

long viability(char *string,char n)
{
char i;
long viability=0;
viability=max(abs(x[string[0]]-x[string[n-1]]),abs(y[string[0]]-y[string[n-1]]));
for (i=0;i<n-1;i++)
{
viability+=max(abs(x[string[i]]-x[string[i+1]]),abs(y[string[i]]-y[string[i+1]]));
}
return(viability);
}


void inversion(char *string, char n)
{
char i,j,k,*tmp;
i=random(n);
j=random(n);
tmp=malloc((abs(i-j)+1)*sizeof(char));
for (k=min(i,j);k<=max(i,j);k++)
{
*(tmp+k-min(i,j))=*(string+k);
}

for (k=min(i,j);k<=max(i,j);k++)
{
*(string+k)=*(tmp+max(i,j)-k);
}
free(tmp);
}

void main(void)
{
long dis[255];
char string[255],elite[255],chk[255];
char i,j,k,l,n=100;
unsigned int s=0;
int graphdriver,graphmode;
detectgraph(&graphdriver,&graphmode);
initgraph(&graphdriver,&graphmode,"C:\\TC\\BGI");

randomize();
clrscr();
cleardevice();
for (i=0;i<n;i++)
{
x[i]=random(getmaxx());
y[i]=random(getmaxy());
}

for (l=0;l<n;l++)
{
chk[l]=0;
}
l=0;
//LazyFrog-algorithm
for (j=1;j<n;j++)
{
for (i=0;i<n;i++)
{
if ((chk[i]!=1)&&(i!=l))
{
dis[i]=max(abs(x[i]-x[l]),abs(y[i]-y[l]));
}
else
{
dis[i]=2000;
}
}
chk[l]=1;
k=minimum(dis,n);
setcolor(RED);
string[j]=k;
l=k;
}
string[0]=0;
for (i=0;i<n;i++)
{
putpixel(x[i],y[i],GREEN);
}
for (i=0;i<n;i++)
{
// string[i]=i;
elite[i]=string[i];
}
do
{
for (i=0;i<n;i++)
{
string[i]=elite[i];
}
inversion(&string,n);
if (viability(&string,n)<viability(&elite,n))
{
for (i=0;i<n;i++)
{
elite[i]=string[i];
// printf("%3d",elite[i]);
}
// printf(": Elite\n");
s=0;
}
s++;
}while (s<pow(2,15));
printf("%d \nPress Any Key",viability(&elite,n));
getch();
cleardevice();
for (i=0;i<n-1;i++)
{
setcolor(BLUE);
line(x[elite[i]],y[elite[i]],x[elite[i+1]],y[elite[i+1]]);
}
line(x[elite[0]],y[elite[0]],x[elite[n-1]],y[elite[n-1]]);

for (i=0;i<n;i++)
{
putpixel(x[i],y[i],GREEN);
}

getch();
closegraph();
}

Автор: neutrino 31.7.2004, 20:46
Я писал прогу для генетиков, как раз решение той же задачи, только на генах в ДНК.

Автор: IgorMAN 14.8.2006, 09:09
Добрый день уважаемые програмисты!!! А есть у кого-нибудь решение задачи коммивояжера методом ГА в ручную(на бумаге), с 4 или 5 городами??? Если есть то скиньте на [email protected]
Пожалуйсто не игнорируйте мое сообщение, от него может зависеть будущее моего обучения. smile 

Автор: Magister Y0da 12.1.2007, 22:46
Graf Zeppelin, а можешь выложить скаченное http://www.codeproject.com/cpp/tspapp.asp?

Автор: DAGON 17.5.2007, 14:12
Народ плиз есть у когонить листинг жадного алгоритма на паскеле или ВБ если есть плиз скиньте на мыло [email protected]
Буду очень благодарен

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)