Recent

Author Topic: Traveling Salesman  (Read 6635 times)

dryzone

  • New Member
  • *
  • Posts: 13
Traveling Salesman
« on: March 12, 2019, 03:56:30 am »
Anyone know of a pascal or lazarus routine for the traveling salesman problem, obviously for a limited set of data as the TSP has not been solved in exact form for arbitrary number of points.

Thanks

avk

  • Hero Member
  • *****
  • Posts: 752
Re: Traveling Salesman
« Reply #1 on: March 12, 2019, 05:22:47 am »
Take a look at https://github.com/avk959/LGenerics (unit LGSparseGraph, class TGTspHelper)

Thausand

  • Sr. Member
  • ****
  • Posts: 292
Re: Traveling Salesman
« Reply #2 on: March 12, 2019, 06:31:06 am »
Maybe example better found also here on forum can show http://delphiforfun.org/programs/traveling_salesman.htm

Also good programmer on forum like benibela has made code competition on lazy salesman i think from 2014

tr_escape

  • Sr. Member
  • ****
  • Posts: 432
  • sector name toys | respect to spectre
    • Github:
Re: Traveling Salesman
« Reply #3 on: March 12, 2019, 07:12:04 am »
Maybe example better found also here on forum can show http://delphiforfun.org/programs/traveling_salesman.htm

Also good programmer on forum like benibela has made code competition on lazy salesman i think from 2014

For now days maybe it wont work because of Gary Derby's DFF library.

I tried some changes about project to convert to lazarus and you can find this repo but of course it has got some bugs  :o

https://github.com/mehmetulukaya/laz-projects/tree/master/LazTSP

https://github.com/mehmetulukaya/laz-projects/tree/master/LazDFFLib

Note: Unfortunatelly you have to pull whole project but I will/hope change to each project independent.
« Last Edit: March 12, 2019, 07:15:09 am by tr_escape »

Thausand

  • Sr. Member
  • ****
  • Posts: 292
Re: Traveling Salesman
« Reply #4 on: March 12, 2019, 07:39:27 am »
You make delphi to lazarus for Traveling Salesman ?

Thank you much tr_escape. That very good !

Not so good has some bugs  ;). Maybe we can fix but i now busy. I look later your version, first i install Lazarus on device ARM and linux but have problem i need fix. Thank you your version.


I search competition 2014 (i was good thinking) here https://www.go-hero.net/jam/14/solutions/2/3/Pascal

tr_escape

  • Sr. Member
  • ****
  • Posts: 432
  • sector name toys | respect to spectre
    • Github:
Re: Traveling Salesman
« Reply #5 on: March 12, 2019, 08:37:43 am »
You make delphi to lazarus for Traveling Salesman ?

Thank you much tr_escape. That very good !

Not so good has some bugs  ;). Maybe we can fix but i now busy. I look later your version, first i install Lazarus on device ARM and linux but have problem i need fix. Thank you your version.


I search competition 2014 (i was good thinking) here https://www.go-hero.net/jam/14/solutions/2/3/Pascal

But original project designed for windows means you have to use only method instead of whole project.
I just convert to lazarus and compile/run for windows.

I'll try to compile for linux as soon as possible ---> OK but more or less some functions
« Last Edit: March 15, 2019, 02:25:31 pm by tr_escape »

avk

  • Hero Member
  • *****
  • Posts: 752
Re: Traveling Salesman
« Reply #6 on: March 12, 2019, 09:31:14 am »
Maybe example better found also here on forum can show http://delphiforfun.org/programs/traveling_salesman.htm
Did I understand correctly that your proposal as an exact solution involves an exhaustive search?

Thausand

  • Sr. Member
  • ****
  • Posts: 292
Re: Traveling Salesman
« Reply #7 on: March 12, 2019, 09:47:09 am »
Quote
I'll try to compile for linux as soon as possible
i read in source is windows only and using windows units. That good for delphi (and windows) and not so good for linux and other.

That is many work to correct.

Your code see many with statement that is not good for lazarus. Many warnings on forum say not using with statement because using wrong components/class for property to change and give error. That true, but i have not look your code many long. I try when have ready my installation but is lenghty because fixing errors so not soon. I need for test linux.

Thausand

  • Sr. Member
  • ****
  • Posts: 292
Re: Traveling Salesman
« Reply #8 on: March 12, 2019, 09:53:28 am »
Quote
Did I understand correctly that your proposal as an exact solution involves an exhaustive search?
Sorry i tell to have not look at your code so not know solution you have make. You talk on how solve problem of TSP ? I try look soon your code to see how your solve. Short look i see used generics so that modern coding and not same as delphiforfun solution.

Sorry my english

avk

  • Hero Member
  • *****
  • Posts: 752
Re: Traveling Salesman
« Reply #9 on: March 17, 2019, 06:38:18 am »
Sorry for the late reply.
You talk on how solve problem of TSP ?
Yes, I just could not believe my eyes, you offer an exhaustive search (the slowest method)
and say that this is a "better example". The limit for TSP exhaustive search is 15-16 cities.
For comparison, I added more cities to Gary's list (now it’s 70),
the optimal route branch-and-bound search against all cities took about
110 minutes on my machine(the results is in the attachment).

Thausand

  • Sr. Member
  • ****
  • Posts: 292
Re: Traveling Salesman
« Reply #10 on: March 17, 2019, 08:45:42 pm »
Quote
Sorry for the late reply.
No problem. I busy  :)

Thank for reply.

Quote
Yes, I just could not believe my eyes, you offer an exhaustive search (the slowest method)
and say that this is a "better example".
Oh No. I not mean better example. I mean better search forum  :-[


TSP math problem. You now good math then solve faster. Not good math then solve slower.

Question was lazarus or freepascal. You freepascal so I search lazarus.

I not now if questioner not now how work TSP math, not now how write pascal or not now how write lazarus GUI for see.

That 3 different problems

DelphiForFun is example that can see how work lazarus (real delphi) graphics and same time see solution calculate.

You math method many faster  8)

I quick make work tr_escape for linux. not fast but slow (in picture).

DehlpiForFun example write:
Quote
5. Click either the "Exhaustive Search" or "Heuristic path search" button to see the computer solutions.  Exhaustive search is slow but sure, it will probably not complete for more than 13 or 14 cities.  You can set a long time limit and interrupt it a any time, successively better routes will be displayed as they are found..  Heuristic search is a "good, but not necessarily the best" approach,  It is fast and  good enough to usually find a shorter path than yours for 15 or more cities.  Current heuristic search techniques only consider closed routes (i.e. when the "Round trip" box is checked) and are disabled for open routes.
« Last Edit: March 17, 2019, 08:50:02 pm by Thausand »

avk

  • Hero Member
  • *****
  • Posts: 752
Re: Traveling Salesman
« Reply #11 on: March 18, 2019, 04:07:46 am »
Looks funny indeed, compared to it, my graphic example is very ascetic.

BobDog

  • Sr. Member
  • ****
  • Posts: 394
Re: Traveling Salesman
« Reply #12 on: March 19, 2019, 10:29:50 pm »
Non Lazarus brute force (twoish seconds)
Code: Pascal  [Select][+][-]
  1.  
  2.  
  3.  
  4.  
  5. program traveller;
  6.  
  7. uses
  8.   graph,wincrt;
  9.     {wincrt only for readkey}
  10. type
  11.  pt =object
  12. x,y:int64;
  13. end;
  14.  
  15. type
  16. pts=object
  17. p:array of pt;
  18. index:int64;
  19. end;
  20.  
  21. var copy:array of pts;  {global variable}
  22.  
  23. function range(first:integer;last:integer):integer;
  24. begin
  25. result:= trunc( Random()*(last-first+1)) + first
  26. end; {range}
  27.  
  28. procedure setup(var points:pts;n:integer;xres:word;yres:word);
  29. var i:integer;
  30. begin
  31. if high(points.p)=-1 then setlength(points.p,n);
  32.  for i:=0 to high(points.p) do
  33. begin
  34. points.p[i].x :=range(20,(xres)-20);
  35. points.p[i].y :=range(80,(yres)-20);
  36. end;
  37. end; {setup}
  38.  
  39. procedure drawpoints(points:pts);
  40. var c:string;
  41. var i:integer;
  42. begin
  43.  for i:=0 to high(points.p) do
  44.   begin
  45.   if i=0 then  setfillstyle(solidfill,white) else setfillstyle(solidfill,red);
  46.   if i= high(points.p) then setfillstyle(solidfill,green);
  47.   fillellipse(points.p[i].x,points.p[i].y,10,10) ;
  48.      str((i+1),c);
  49.      OutTextXY(points.p[i].x,points.p[i].y+15,c);
  50.   end;
  51. end;  {drawpoints}
  52.  
  53. procedure join(points:pts);
  54. var i:integer;
  55. begin
  56. drawpoints(points);
  57. for i:=0 to high(points.p)-1 do line(points.p[i].x,points.p[i].y,points.p[i+1].x,points.p[i+1].y);
  58. end; {join}
  59.  
  60. procedure fasttrack(var points:pts);
  61. var min:int64= 20000000;
  62. var ctr,total,runs,x,y:int64;
  63. var sz:longword=0;
  64. var i:longword; {for loops}
  65. var L,vmin:int64;
  66.  
  67. function length(a:pt;b:pt):int64;
  68. begin
  69. result:= (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)
  70. end;{length -- nested}
  71.  
  72. procedure swaps(var p1:pt;var p2:pt);
  73. var tmp:pt;
  74. begin
  75. tmp:=p1;p1:=p2;p2:=tmp;
  76. end;{swaps -- nested}
  77.  
  78. begin
  79. vmin:=0;
  80. total:=0;
  81. ctr:=0;
  82. sz:= high(points.p);
  83. runs:=2000000; {iterations}
  84.  
  85. if high(copy)=-1 then
  86. begin
  87. setlength(copy,runs); {allocate}
  88. for i:=0 to runs do setlength(copy[i].p,sz); {allocate}
  89. end;
  90.  
  91.  
  92. repeat
  93.  
  94. repeat
  95. x:=Range(1,sz-1);
  96. y:=Range(1,sz-1);
  97. until x <> y;
  98. swaps(points.p[x],points.p[y]);
  99. total:=0;
  100. ctr+=1;
  101. for i:=0 to sz-1 do
  102. begin
  103.  L:=length(points.p[i],points.p[i+1]);
  104.  total+=L;
  105. end; {for}
  106.  
  107. for i:=0 to high(points.p) do
  108. begin
  109. copy[ctr].p[i].x:=points.p[i].x;
  110. copy[ctr].p[i].y:=points.p[i].y;
  111. end;{for}
  112.   copy[ctr].index:=total;
  113.   If min>total Then min:=total ;
  114. until ctr>=runs;
  115.  
  116. For i  :=0 To high(copy) do   If copy[i].index = min Then Vmin:=i;
  117.  
  118.  for i:=0 to high(points.p) do
  119.  begin
  120.  points.p[i].x:=copy[vmin].p[i].x;
  121.  points.p[i].y:=copy[vmin].p[i].y;
  122.  end;
  123. end; {fasttrack}
  124.  
  125.  Function distance(points:pts):Int64;
  126.  var total,L:int64;
  127.  var n:longint;
  128.    function length(a:pt;b:pt):int64;
  129.    begin
  130.    result:= trunc(sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)))
  131.    end;{length -- nested}
  132.    begin
  133.    total:=0;
  134.     For n :=0 To high(points.p)-1 do
  135.     begin
  136.         L:= length(points.p[n],points.p[n+1]);
  137.         total+=(L);
  138.         end ;
  139.     Result:= total ;
  140. End; {distance}
  141.  
  142.  var c : char;
  143.  var  gd, gm: SmallInt;
  144.  var points:pts;
  145.  var distance1:int64;
  146.  var d1:string;
  147.  
  148. begin
  149.  
  150.    {==========  set up graph =========}
  151.   gd := D8bit;
  152.   gm :=  m800x600;
  153.   InitGraph(gd, gm, '');
  154.   if GraphResult <> grok then  halt;
  155.   SetTextStyle(SansSerifFont ,HorizDir,2);
  156.   setbkcolor(3);
  157.    {===================================}
  158.    // randomize;
  159.    repeat
  160.    setup(points,12,800,600);
  161.    Cleardevice;
  162.    setcolor(blue);
  163.    join(points);
  164.    distance1:=distance(points);
  165.    str (distance1,d1);
  166.    OutTextXY(10,10,'Through distance, white to green '+d1);
  167.    OutTextXY(10,30,'Press a key ');
  168.    c:=readkey;
  169.    cleardevice;
  170.    OutTextXY(10,10,'Press a key to redo, esc to end');
  171.    fasttrack(points); {do the business here }
  172.    setcolor(white);
  173.    join(points);
  174.    OutTextXY(10,30,'Old distsnce '+d1);
  175.    distance1:=distance(points);
  176.    str (distance1,d1);
  177.    OutTextXY(10,50,'New distsnce '+d1);
  178.    c:=readkey;
  179.   until  c=#27 ;
  180.  
  181.   Closegraph;
  182. end.
fpc 3.04
dev-pas ide.
Tested 64 and 32 bits.
Uses graph and wincrt.
« Last Edit: March 19, 2019, 11:53:37 pm by BobDog »

Thausand

  • Sr. Member
  • ****
  • Posts: 292
Re: Traveling Salesman
« Reply #13 on: March 22, 2019, 08:08:57 am »
Quote
fpc 3.04
dev-pas ide.
Tested 64 and 32 bits.
Uses graph and wincrt.
sorry, i not can test linux pi then missing unit graph.  :'(

I know not use wincrt and replace crt.

strange not unit graph. i use fpc-deluxe. maybe bug ?

tr_escape

  • Sr. Member
  • ****
  • Posts: 432
  • sector name toys | respect to spectre
    • Github:
Re: Traveling Salesman
« Reply #14 on: March 22, 2019, 09:05:00 am »
I compiled but not linked because of static link (I think)

Log:

"
mintx@mintx-VirtualBox:~/Belgeler/gitprojects/laztravel$ fpc traveller.pas
Free Pascal Compiler version 3.0.4 [2018/10/29] for x86_64
Copyright (c) 1993-2017 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling traveller.pas
Linking traveller
/usr/bin/ld: uyarı: link.res çıktı bölümleri içeriyor; -T yi unuttunuz mu?
/usr/bin/ld: -lggi bulunamadı
Error: Error while linking
Fatal: There were 1 errors compiling module, stopping
Fatal: Compilation aborted
Error: /usr/bin/ppcx64 returned an error exitcode

"


In linux mint changed to uses block GGI an GGIGraph it is compiling but not linking maybe library missing or cancelled by linux maintainer.


See:
http://manpages.ubuntu.com/cgi-bin/search.py?q=libggi&cx=003883529982892832976%3A5zl6o8w6f0s&cof=FORID%3A9&ie=UTF-8&siteurl=manpages.ubuntu.com%2Fmanpages%2Fprecise%2Fman7%2Flibggi.7.html&ref=www.google.com%2F&ss=1295j427255j6


I think we need to change suitable uses list or modify to nowdays libraries
Code: Pascal  [Select][+][-]
  1. {$Mode objfpc}
  2. program traveller;
  3.  
  4. uses
  5.   GGI,
  6.   GGIGraph,
  7.   Crt;
  8.  
  9. {wincrt only for readkey}
  10. type
  11.   pt = object
  12.     x, y: int64;
  13.   end;
  14.  
  15. type
  16.   pts = object
  17.     p: array of pt;
  18.     index: int64;
  19.   end;
  20.  
  21. var
  22.   copy: array of pts;  {global variable}
  23.  
  24.   function range(First: integer; last: integer): integer;
  25.   begin
  26.     Result := trunc(Random() * (last - First + 1)) + First;
  27.   end; {range}
  28.  
  29.   procedure setup(var points: pts; n: integer; xres: word; yres: word);
  30.   var
  31.     i: integer;
  32.   begin
  33.     if high(points.p) = -1 then
  34.       setlength(points.p, n);
  35.     for i := 0 to high(points.p) do
  36.     begin
  37.       points.p[i].x := range(20, (xres) - 20);
  38.       points.p[i].y := range(80, (yres) - 20);
  39.     end;
  40.   end; {setup}
  41.  
  42.   procedure drawpoints(points: pts);
  43.   var
  44.     c: string;
  45.   var
  46.     i: integer;
  47.   begin
  48.     for i := 0 to high(points.p) do
  49.     begin
  50.       if i = 0 then
  51.         setfillstyle(solidfill, white)
  52.       else
  53.         setfillstyle(solidfill, red);
  54.       if i = high(points.p) then
  55.         setfillstyle(solidfill, green);
  56.       fillellipse(points.p[i].x, points.p[i].y, 10, 10);
  57.       str((i + 1), c);
  58.       OutTextXY(points.p[i].x, points.p[i].y + 15, c);
  59.     end;
  60.   end;  {drawpoints}
  61.  
  62.   procedure join(points: pts);
  63.   var
  64.     i: integer;
  65.   begin
  66.     drawpoints(points);
  67.     for i := 0 to high(points.p) - 1 do
  68.       line(points.p[i].x, points.p[i].y, points.p[i + 1].x, points.p[i + 1].y);
  69.   end; {join}
  70.  
  71.   procedure fasttrack(var points: pts);
  72.   var
  73.     min: int64 = 20000000;
  74.   var
  75.     ctr, total, runs, x, y: int64;
  76.   var
  77.     sz: longword = 0;
  78.   var
  79.     i: longword; {for loops}
  80.   var
  81.     L, vmin: int64;
  82.  
  83.     function length(a: pt; b: pt): int64;
  84.     begin
  85.       Result := (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
  86.     end;{length -- nested}
  87.  
  88.     procedure swaps(var p1: pt; var p2: pt);
  89.     var
  90.       tmp: pt;
  91.     begin
  92.       tmp := p1;
  93.       p1 := p2;
  94.       p2 := tmp;
  95.     end;{swaps -- nested}
  96.  
  97.   begin
  98.     vmin := 0;
  99.     total := 0;
  100.     ctr := 0;
  101.     sz := high(points.p);
  102.     runs := 2000000; {iterations}
  103.  
  104.     if high(copy) = -1 then
  105.     begin
  106.       setlength(copy, runs); {allocate}
  107.       for i := 0 to runs do
  108.         setlength(copy[i].p, sz); {allocate}
  109.     end;
  110.  
  111.  
  112.     repeat
  113.  
  114.       repeat
  115.         x := Range(1, sz - 1);
  116.         y := Range(1, sz - 1);
  117.       until x <> y;
  118.       swaps(points.p[x], points.p[y]);
  119.       total := 0;
  120.       inc(ctr);
  121.       for i := 0 to sz - 1 do
  122.       begin
  123.         L := length(points.p[i], points.p[i + 1]);
  124.         inc(total,L);
  125.       end; {for}
  126.  
  127.       for i := 0 to high(points.p) do
  128.       begin
  129.         copy[ctr].p[i].x := points.p[i].x;
  130.         copy[ctr].p[i].y := points.p[i].y;
  131.       end;{for}
  132.       copy[ctr].index := total;
  133.       if min > total then
  134.         min := total;
  135.     until ctr >= runs;
  136.  
  137.     for i := 0 to high(copy) do
  138.       if copy[i].index = min then
  139.         Vmin := i;
  140.  
  141.     for i := 0 to high(points.p) do
  142.     begin
  143.       points.p[i].x := copy[vmin].p[i].x;
  144.       points.p[i].y := copy[vmin].p[i].y;
  145.     end;
  146.   end; {fasttrack}
  147.  
  148.   function distance(points: pts): int64;
  149.   var
  150.     total, L: int64;
  151.   var
  152.     n: longint;
  153.  
  154.     function length(a: pt; b: pt): int64;
  155.     begin
  156.       Result := trunc(sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)));
  157.     end;
  158.     {length -- nested}
  159.   begin
  160.     total := 0;
  161.     for n := 0 to high(points.p) - 1 do
  162.     begin
  163.       L := length(points.p[n], points.p[n + 1]);
  164.       inc(total,L);;
  165.     end;
  166.     Result := total;
  167.   end; {distance}
  168.  
  169. var
  170.   c: char;
  171. var
  172.   gd, gm: smallint;
  173. var
  174.   points: pts;
  175. var
  176.   distance1: int64;
  177. var
  178.   d1: string;
  179.  
  180. begin
  181.  
  182.   {==========  set up graph =========}
  183.   gd := D8bit;
  184.   gm := m800x600;
  185.   InitGraph(gd, gm, '');
  186.   if GraphResult <> grok then
  187.     halt;
  188.   SetTextStyle(SansSerifFont, HorizDir, 2);
  189.   setbkcolor(3);
  190.   {===================================}
  191.   // randomize;
  192.   repeat
  193.     setup(points, 12, 800, 600);
  194.     Cleardevice;
  195.     setcolor(blue);
  196.     join(points);
  197.     distance1 := distance(points);
  198.     str(distance1, d1);
  199.     OutTextXY(10, 10, 'Through distance, white to green ' + d1);
  200.     OutTextXY(10, 30, 'Press a key ');
  201.     c := readkey;
  202.     cleardevice;
  203.     OutTextXY(10, 10, 'Press a key to redo, esc to end');
  204.     fasttrack(points); {do the business here }
  205.     setcolor(white);
  206.     join(points);
  207.     OutTextXY(10, 30, 'Old distsnce ' + d1);
  208.     distance1 := distance(points);
  209.     str(distance1, d1);
  210.     OutTextXY(10, 50, 'New distsnce ' + d1);
  211.     c := readkey;
  212.   until c = #27;
  213.  
  214.   Closegraph;
  215. end.
  216.  

Also it is working in windows 10 see attach. (with old units)
« Last Edit: March 22, 2019, 09:39:23 am by tr_escape »

 

TinyPortal © 2005-2018