home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / CLIPPER / MISC / NETSTUFF.ZIP / TSP.PAS < prev   
Encoding:
Pascal/Delphi Source File  |  1980-01-04  |  10.4 KB  |  348 lines

  1. {$R+}
  2. PROGRAM traveling_salesperson ;
  3.  
  4. (* Copyright 1987 - Knowledge Garden Inc.
  5.                     473A Malden Bridge Rd.
  6.                     R.D. 2
  7.                     Nassau, NY 12123       *)
  8.  
  9.  
  10. (* TSP solves a series of differential equations which simulate a neural
  11.    net solution of the traveling salesperson problem. The problem and
  12.    the equations are described in the article "Computing with Neurons" in
  13.    the July 1987 issue of AI Expert Magazine.
  14.  
  15.    This program has been tested using Turbo ver 3.01A on an IBM PC/AT. It has
  16.    been run under both DOS 3.2 and Concurrent 5.0 .
  17.  
  18.    We would be pleased to hear your comments, good or bad, or any applications
  19.    and modifications of the program. Contact us at:
  20.  
  21.      AI Expert
  22.      500 Howard St.
  23.      San Francisco, CA 94105
  24.  
  25.    Bill and Bev Thompson    *)
  26.  
  27.  CONST
  28.   max_city = 'E' ;         (* max_city and max_position are the size of the *)
  29.   max_position = 5 ;       (* neural net. They must match. Cities run from *)
  30.                            (* A to max_city *)
  31.  
  32.   a = 500.0 ;              (* these are the weighting constants described *)
  33.   b = 500.0 ;              (* in the article. By changing then you can *)
  34.   c = 200.0 ;              (* get different types of solutions *)
  35.   d = 300.0 ;              (* d seems to have the most effect, increasing *)
  36.                            (* it produces shorter distance routes, but *)
  37.                            (* they aren't necessarily real tours. *)
  38.  
  39.   u0 = 0.02 ;              (* This parameter effects the output voltage of *)
  40.                            (* the amplifiers. Increasing it gives a broader *)
  41.                            (* curve. *)
  42.  
  43.   n = 7 ;                  (* This term affects global inhibition of the *)
  44.                            (* network. By setting it slightly larger than *)
  45.                            (* the number of cities, we seem to get better *)
  46.                            (* results *)
  47.  
  48.   h = 0.01 ;               (* The time step *)
  49.  
  50.  TYPE
  51.   cities = 'A' .. max_city ;
  52.   positions = 1 .. max_position ;
  53.  
  54.  
  55.  VAR
  56.   u : ARRAY [cities,positions] OF real ;      (* Input voltages *)
  57.   dist : ARRAY [cities,cities] OF real ;      (* Distances between cities *)
  58.  
  59.  
  60.  
  61.  FUNCTION v(city : cities ; position : positions) : real ;
  62.   (* This function calculates the output voltage from an amplifier
  63.      tanh calculates the hyperbolic tangent which gives the shape
  64.      of the output curve described in the article *)
  65.  
  66.   FUNCTION tanh(r : real) : real ;
  67.    VAR
  68.     r1,r2 : real ;
  69.    BEGIN
  70.     IF r > 20.0
  71.      THEN tanh := 1.0
  72.     ELSE IF r < -20.0
  73.      THEN tanh := -1.0
  74.     ELSE
  75.      BEGIN
  76.       r1 := exp(r) ;
  77.       r2 := exp(-r) ;
  78.       tanh := (r1 - r2) / (r1 + r2) ;
  79.      END ;
  80.    END ; (* tanh *)
  81.  
  82.   BEGIN
  83.    v := (1.0 + tanh(u[city,position] / u0)) / 2.0 ;
  84.   END ; (* v *)
  85.  
  86.  
  87.  FUNCTION f(city : cities ; position : positions) : real ;
  88.   (* This function calculates the right hand side of the differential
  89.      equations described in the article. It is not optimized for anything
  90.      and is pretty slow. *)
  91.  
  92.   FUNCTION col_sum(cty : cities) : real ;
  93.    (* column inhibition. This function helps keep the number of
  94.       output items in each column small *)
  95.    VAR
  96.     col : positions ;
  97.     sum : real ;
  98.    BEGIN
  99.     sum := 0.0 ;
  100.     FOR col := 1 TO max_position DO
  101.      IF col <> position
  102.       THEN sum := sum + v(cty,col) ;
  103.     col_sum := sum ;
  104.    END ; (* col_sum *)
  105. è
  106.   FUNCTION row_sum(p : positions) : real ;
  107.    (* row inhibition. This function helps keep the number of
  108.       output items in each row small *)
  109.    VAR
  110.     row : cities ;
  111.     sum : real ;
  112.    BEGIN
  113.     sum := 0.0 ;
  114.     FOR row := 'A' TO max_city DO
  115.      IF row <> city
  116.       THEN sum := sum + v(row,p) ;
  117.     row_sum := sum ;
  118.    END ; (* row_sum *)
  119.  
  120.   FUNCTION matrix_sum : real ;
  121.    (* global inhibition. This function keeps the total number of cities
  122.       visited small *)
  123.    VAR
  124.     row : cities ;
  125.     col : positions ;
  126.     sum : real ;
  127.    BEGIN
  128.     sum := 0.0 ;
  129.     FOR row := 'A' TO max_city DO
  130.      FOR col := 1 TO max_position DO
  131.       sum := sum + v(row,col) ;
  132.     matrix_sum := sum ;
  133.    END ; (* matrix_sum *)
  134.  
  135.   FUNCTION dist_sum : real ;
  136.    (* distance inhibition. The inhibition is larger for longer tours.
  137.       Note that neuron (X,max_position) is connected to neuron (X,1),
  138.       in other words, the net is circular *)
  139.    VAR
  140.     c : cities ;
  141.     sum : real ;
  142.    BEGIN
  143.     sum := 0.0 ;
  144.     IF position = max_position
  145.      THEN
  146.       FOR c := 'A' TO max_city DO
  147.        sum := sum + dist[city,c] * (v(c,1) + v(c,position - 1))
  148.     ELSE IF position = 1
  149.      THEN
  150.       FOR c := 'A' TO max_city DO
  151.        sum := sum + dist[city,c] * (v(c,position + 1) + v(c,max_position))
  152.     ELSE
  153.      FOR c := 'A' TO max_city DO
  154.       sum := sum + dist[city,c] * (v(c,position + 1) + v(c,position - 1)) ;
  155.     dist_sum := sum ;
  156.    END ; (* dist_sum *)
  157.  
  158.   BEGIN
  159.    f := -u[city,position] - a * col_sum(city) - b * row_sum(position)
  160. è        - c * (matrix_sum - n) - d * dist_sum ;
  161.   END ; (* f *)
  162.  
  163.  
  164.  PROCEDURE iterate ;
  165.   (* The basic solution process. This is a terrible way to solve differential
  166.      equations. Don't use it for anything serious, it performs poorly
  167.      when the number of cities gets larger than 7 or 8.
  168.      We keep iterating until the norm is less than tol or until the user
  169.      gets bored and presses the space bar. *)
  170.   CONST
  171.    tol = 1.0E-05 ;
  172.   VAR
  173.    step : integer ;
  174.    c1 : cities ;
  175.    i : positions ;
  176.    nr : real ;
  177.    u_old : ARRAY [cities,positions] OF real ;
  178.    ch : char ;
  179.  
  180.   FUNCTION norm : real ;
  181.    (* The norm is a measure of how much change there has been between
  182.       solutions. This is an infinity norm, calculated as the maximum
  183.       absolute value of the difference between components of the
  184.       solution vectors. We calculate the relative norm as:
  185.         N(u_new - u) / N(u). *)
  186.    VAR
  187.     cx : cities ;
  188.     ix : positions ;
  189.     max,max_comp : real ;
  190.    BEGIN
  191.     max := 0.0 ;
  192.     FOR cx := 'A' TO max_city DO
  193.      FOR ix := 1 TO max_position DO
  194.       BEGIN
  195.        IF abs(u_old[cx,ix] - u[cx,ix]) > max
  196.         THEN max := abs(u_old[cx,ix] - u[cx,ix]) ;
  197.        IF abs(u[cx,ix]) > max_comp
  198.         THEN max_comp := abs(u[cx,ix]) ;
  199.       END ;
  200.     norm := max / max_comp ;
  201.    END ; (* norm *)
  202.  
  203.   PROCEDURE print_matrix ;
  204.    (* Every so often, we print the input and output matrices so that
  205.       you can see what is going on. If the output matrix describes a
  206.       valid tour, we print that also. *)
  207.    VAR
  208.     c1 : cities ;
  209.     i : positions ;
  210.     vv : real ;
  211.     t : ARRAY [1 .. max_position] OF char ;
  212.     t_count : integer ;
  213.  
  214.    PROCEDURE write_tour ;
  215. è    VAR
  216.      i : positions ;
  217.      t_dist : real ;
  218.     BEGIN
  219.      t_dist := 0.0 ;
  220.      FOR i := 1 TO max_position - 1 DO
  221.       t_dist := t_dist + dist[t[i],t[i+1]] ;
  222.      t_dist := t_dist + dist[t[max_position],t[1]] ;
  223.      write(output,'Tour: ') ;
  224.      FOR i := 1 TO max_position DO
  225.       write(output,t[i]) ;
  226.      writeln(output,'   dist = ',t_dist) ;
  227.     END ; (* write_tour *)
  228.  
  229.    PROCEDURE matrix_heading ;
  230.     VAR
  231.      i : positions ;
  232.     BEGIN
  233.      write(output,'  ') ;
  234.      FOR i := 1 TO max_position DO
  235.       write(output,i : 12) ;
  236.      writeln ;
  237.     END ; (* matrix_heading *)
  238.  
  239.    BEGIN
  240.     t_count := 0 ;
  241.     FOR i := 1 TO max_position DO
  242.      t[i] := chr(0) ;
  243.     writeln(output) ;
  244.     writeln(output,'Step: ',step,' norm = ',nr) ;
  245.     writeln(output) ;
  246.     writeln(output,'Input Voltages') ;
  247.     matrix_heading ;
  248.     FOR c1 := 'A' TO max_city DO
  249.      BEGIN
  250.       write(output,c1,'    ') ;
  251.       FOR i := 1 TO max_position DO
  252.        write(output,u[c1,i] : 12 : 5) ;
  253.       writeln(output) ;
  254.      END ;
  255.     writeln(output) ;
  256.     writeln(output,'Output Voltages') ;
  257.     matrix_heading ;
  258.     FOR c1 := 'A' TO max_city DO
  259.      BEGIN
  260.       write(output,c1,'    ') ;
  261.       FOR i := 1 TO max_position DO
  262.        BEGIN
  263.         vv := v(c1,i) ;
  264.         write(output,vv : 12 : 5) ;
  265.         IF (vv > 0.8) AND (t_count < max_position) AND (t[i] = chr(0))
  266.          THEN
  267.           BEGIN
  268.            t_count := t_count + 1 ;
  269.            t[i] := c1 ;
  270. è          END ;
  271.        END ;
  272.       writeln(output) ;
  273.      END ;
  274.     IF t_count = max_position
  275.      THEN write_tour ;
  276.    END ; (* print_matrix *)
  277.  
  278.   BEGIN
  279.    step := 0 ;
  280.    REPEAT
  281.     step := step + 1 ;
  282.     move(u,u_old,sizeof(u)) ;
  283.     FOR c1 := 'A' TO max_city DO
  284.      FOR i := 1 TO max_position DO
  285.       u[c1,i] := u[c1,i] + h * f(c1,i) ;
  286.     nr := norm ;
  287.     IF ((step MOD 10) = 0) OR (step < 10)
  288.      THEN print_matrix ;
  289.    UNTIL keypressed OR (nr < tol) ;
  290.    IF keypressed
  291.     THEN read(kbd,ch) ;
  292.    print_matrix ;
  293.   END ; (* iterate *)
  294.  
  295.  
  296.  PROCEDURE initialize ;
  297.   TYPE
  298.    location = RECORD
  299.                x : real ;
  300.                y : real ;
  301.               END ;
  302.    city_array = ARRAY [cities] OF location ;
  303.   CONST
  304.    u00 = -0.01386 ;
  305. (* city_loc : city_array = ( (x : 0.21192 ; y : 0.54866),
  306.                              (x : 0.98817 ; y : 0.68465),
  307.                              (x : 0.53109 ; y : 0.72173),
  308.                              (x : 0.31459 ; y : 0.79397),
  309.                              (x : 0.63290 ; y : 0.85573)) ;
  310.  
  311.    These are the values we used for the article, if you want to
  312.    check our results, remove the comments here and use this data *)
  313.   VAR
  314.    c1,c2 : cities ;
  315.    i : positions ;
  316.    city_loc : city_array ;
  317.    ch : char ;
  318.   BEGIN
  319.    randomize ;
  320.    FOR c1 := 'A' TO max_city DO
  321.     BEGIN
  322.      city_loc[c1].x := random ;
  323.      city_loc[c1].y := random ;
  324.     END ;
  325. è   FOR c1 := 'A' TO pred(max_city) DO
  326.     BEGIN
  327.      dist[c1,c1] := 0.0 ;
  328.      FOR c2 := succ(c1) TO max_city DO
  329.       BEGIN
  330.        dist[c1,c2] := sqrt(sqr(city_loc[c1].x - city_loc[c2].x) +
  331.                            sqr(city_loc[c1].y - city_loc[c2].y)) ;
  332.        dist[c2,c1] := dist[c1,c2] ;
  333.       END ;
  334.     END ;
  335.    dist[max_city,max_city] := 0.0 ;
  336.    FOR c1 := 'A' TO max_city DO
  337.     FOR i := 1 TO max_position DO
  338.      u[c1,i] := u00 + (((2 * random - 1.0) / 10.0) * u0) ;
  339.    clrscr ;
  340.    writeln('TSP         [c] 1987 Knowledge Garden Inc.') ;
  341.    writeln('                     473A Malden Bridge Rd') ;
  342.    writeln('                     Nassau, NY 12123') ;
  343.    writeln ;
  344.    writeln('Press <Space Bar> to begin - Press again to stop iterating.') ;
  345.    read(kbd,ch) ;
  346.   END ; (* initialize *)
  347.  
  348.  
  349.  BEGIN
  350.   initialize ;
  351.   iterate ;
  352.  END.
  353.