⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tsp.pas

📁 delphi pascal、 人工神经网络源代码
💻 PAS
字号:
{$R+}
PROGRAM traveling_salesperson ;

(* Copyright 1987 - Knowledge Garden Inc.
                    473A Malden Bridge Rd.
                    R.D. 2
                    Nassau, NY 12123       *)


(* TSP solves a series of differential equations which simulate a neural
   net solution of the traveling salesperson problem. The problem and
   the equations are described in the article "Computing with Neurons" in
   the July 1987 issue of AI Expert Magazine.

   This program has been tested using Turbo ver 3.01A on an IBM PC/AT. It has
   been run under both DOS 3.2 and Concurrent 5.0 .

   We would be pleased to hear your comments, good or bad, or any applications
   and modifications of the program. Contact us at:

     AI Expert
     CL Publications Inc.
     650 Fifth St.
     Suite 311
     San Francisco, CA 94107

   or on the AI Expert BBS. Our id is BillandBev Thompson ,[76703,4324].
   You can also contact us on BIX, our id is bbt.

   Bill and Bev Thompson    *)

 CONST
  max_city = 'E' ;         (* max_city and max_position are the size of the *)
  max_position = 5 ;       (* neural net. They must match. Cities run from *)
                           (* A to max_city *)

  a = 500.0 ;              (* these are the weighting constants described *)
  b = 500.0 ;              (* in the article. By changing then you can *)
  c = 200.0 ;              (* get different types of solutions *)
  d = 300.0 ;              (* d seems to have the most effect, increasing *)
                           (* it produces shorter distance routes, but *)
                           (* they aren't necessarily real tours. *)

  u0 = 0.02 ;              (* This parameter effects the output voltage of *)
                           (* the amplifiers. Increasing it gives a broader *)
                           (* curve. *)

  n = 7 ;                  (* This term affects global inhibition of the *)
                           (* network. By setting it slightly larger than *)
                           (* the number of cities, we seem to get better *)
                           (* results *)

  h = 0.01 ;               (* The time step *)


 TYPE
  cities = 'A' .. max_city ;
  positions = 1 .. max_position ;


 VAR
  u : ARRAY [cities,positions] OF real ;      (* Input voltages *)
  dist : ARRAY [cities,cities] OF real ;      (* Distances between cities *)



 FUNCTION v(city : cities ; position : positions) : real ;
  (* This function calculates the output voltage from an amplifier
     tanh calculates the hyperbolic tangent which gives the shape
     of the output curve described in the article *)

  FUNCTION tanh(r : real) : real ;
   VAR
    r1,r2 : real ;
   BEGIN
    IF r > 20.0
     THEN tanh := 1.0
    ELSE IF r < -20.0
     THEN tanh := -1.0
    ELSE
     BEGIN
      r1 := exp(r) ;
      r2 := exp(-r) ;
      tanh := (r1 - r2) / (r1 + r2) ;
     END ;
   END ; (* tanh *)

  BEGIN
   v := (1.0 + tanh(u[city,position] / u0)) / 2.0 ;
  END ; (* v *)


 FUNCTION f(city : cities ; position : positions) : real ;
  (* This function calculates the right hand side of the differential
     equations described in the article. It is not optimized for anything
     and is pretty slow. *)

  FUNCTION col_sum(cty : cities) : real ;
   (* column inhibition. This function helps keep the number of
      output items in each column small *)
   VAR
    col : positions ;
    sum : real ;
   BEGIN
    sum := 0.0 ;
    FOR col := 1 TO max_position DO
     IF col <> position
      THEN sum := sum + v(cty,col) ;
    col_sum := sum ;
   END ; (* col_sum *)

  FUNCTION row_sum(p : positions) : real ;
   (* row inhibition. This function helps keep the number of
      output items in each row small *)
   VAR
    row : cities ;
    sum : real ;
   BEGIN
    sum := 0.0 ;
    FOR row := 'A' TO max_city DO
     IF row <> city
      THEN sum := sum + v(row,p) ;
    row_sum := sum ;
   END ; (* row_sum *)

  FUNCTION matrix_sum : real ;
   (* global inhibition. This function keeps the total number of cities
      visited small *)
   VAR
    row : cities ;
    col : positions ;
    sum : real ;
   BEGIN
    sum := 0.0 ;
    FOR row := 'A' TO max_city DO
     FOR col := 1 TO max_position DO
      sum := sum + v(row,col) ;
    matrix_sum := sum ;
   END ; (* matrix_sum *)

  FUNCTION dist_sum : real ;
   (* distance inhibition. The inhibition is larger for longer tours.
      Note that neuron (X,max_position) is connected to neuron (X,1),
      in other words, the net is circular *)
   VAR
    c : cities ;
    sum : real ;
   BEGIN
    sum := 0.0 ;
    IF position = max_position
     THEN
      FOR c := 'A' TO max_city DO
       sum := sum + dist[city,c] * (v(c,1) + v(c,position - 1))
    ELSE IF position = 1
     THEN
      FOR c := 'A' TO max_city DO
       sum := sum + dist[city,c] * (v(c,position + 1) + v(c,max_position))
    ELSE
     FOR c := 'A' TO max_city DO
      sum := sum + dist[city,c] * (v(c,position + 1) + v(c,position - 1)) ;
    dist_sum := sum ;
   END ; (* dist_sum *)

  BEGIN
   f := -u[city,position] - a * col_sum(city) - b * row_sum(position)
        - c * (matrix_sum - n) - d * dist_sum ;
  END ; (* f *)


 PROCEDURE iterate ;
  (* The basic solution process. This is a terrible way to solve differential
     equations. Don't use it for anything serious, it performs poorly
     when the number of cities gets larger than 7 or 8.
     We keep iterating until the norm is less than tol or until the user
     gets bored and presses the space bar. *)
  CONST
   tol = 1.0E-05 ;
  VAR
   step : integer ;
   c1 : cities ;
   i : positions ;
   nr : real ;
   u_old : ARRAY [cities,positions] OF real ;
   ch : char ;

  FUNCTION norm : real ;
   (* The norm is a measure of how much change there has been between
      solutions. This is an infinity norm, calculated as the maximum
      absolute value of the difference between components of the
      solution vectors. We calculate the relative norm as:
        N(u_new - u) / N(u). *)
   VAR
    cx : cities ;
    ix : positions ;
    max,max_comp : real ;
   BEGIN
    max := 0.0 ;
    FOR cx := 'A' TO max_city DO
     FOR ix := 1 TO max_position DO
      BEGIN
       IF abs(u_old[cx,ix] - u[cx,ix]) > max
        THEN max := abs(u_old[cx,ix] - u[cx,ix]) ;
       IF abs(u[cx,ix]) > max_comp
        THEN max_comp := abs(u[cx,ix]) ;
      END ;
    norm := max / max_comp ;
   END ; (* norm *)

  PROCEDURE print_matrix ;
   (* Every so often, we print the input and output matrices so that
      you can see what is going on. If the output matrix describes a
      valid tour, we print that also. *)
   VAR
    c1 : cities ;
    i : positions ;
    vv : real ;
    t : ARRAY [1 .. max_position] OF char ;
    t_count : integer ;

   PROCEDURE write_tour ;
    VAR
     i : positions ;
     t_dist : real ;
    BEGIN
     t_dist := 0.0 ;
     FOR i := 1 TO max_position - 1 DO
      t_dist := t_dist + dist[t[i],t[i+1]] ;
     t_dist := t_dist + dist[t[max_position],t[1]] ;
     write(output,'Tour: ') ;
     FOR i := 1 TO max_position DO
      write(output,t[i]) ;
     writeln(output,'   dist = ',t_dist) ;
    END ; (* write_tour *)

   PROCEDURE matrix_heading ;
    VAR
     i : positions ;
    BEGIN
     write(output,'  ') ;
     FOR i := 1 TO max_position DO
      write(output,i : 12) ;
     writeln ;
    END ; (* matrix_heading *)

   BEGIN
    t_count := 0 ;
    FOR i := 1 TO max_position DO
     t[i] := chr(0) ;
    writeln(output) ;
    writeln(output,'Step: ',step,' norm = ',nr) ;
    writeln(output) ;
    writeln(output,'Input Voltages') ;
    matrix_heading ;
    FOR c1 := 'A' TO max_city DO
     BEGIN
      write(output,c1,'    ') ;
      FOR i := 1 TO max_position DO
       write(output,u[c1,i] : 12 : 5) ;
      writeln(output) ;
     END ;
    writeln(output) ;
    writeln(output,'Output Voltages') ;
    matrix_heading ;
    FOR c1 := 'A' TO max_city DO
     BEGIN
      write(output,c1,'    ') ;
      FOR i := 1 TO max_position DO
       BEGIN
        vv := v(c1,i) ;
        write(output,vv : 12 : 5) ;
        IF (vv > 0.8) AND (t_count < max_position) AND (t[i] = chr(0))
         THEN
          BEGIN
           t_count := t_count + 1 ;
           t[i] := c1 ;
          END ;
       END ;
      writeln(output) ;
     END ;
    IF t_count = max_position
     THEN write_tour ;
   END ; (* print_matrix *)

  BEGIN
   step := 0 ;
   REPEAT
    step := step + 1 ;
    move(u,u_old,sizeof(u)) ;
    FOR c1 := 'A' TO max_city DO
     FOR i := 1 TO max_position DO
      u[c1,i] := u[c1,i] + h * f(c1,i) ;
    nr := norm ;
    IF ((step MOD 10) = 0) OR (step < 10)
     THEN print_matrix ;
   UNTIL keypressed OR (nr < tol) ;
   IF keypressed
    THEN read(kbd,ch) ;
   print_matrix ;
  END ; (* iterate *)


 PROCEDURE initialize ;
  TYPE
   location = RECORD
               x : real ;
               y : real ;
              END ;
   city_array = ARRAY [cities] OF location ;
  CONST
   u00 = -0.01386 ;
(* city_loc : city_array = ( (x : 0.21192 ; y : 0.54866),
                             (x : 0.98817 ; y : 0.68465),
                             (x : 0.53109 ; y : 0.72173),
                             (x : 0.31459 ; y : 0.79397),
                             (x : 0.63290 ; y : 0.85573)) ;

   These are the values we used for the article, if you want to
   check our results, remove the comments here and use this data *)
  VAR
   c1,c2 : cities ;
   i : positions ;
   city_loc : city_array ;
   ch : char ;
  BEGIN
   randomize ;
   FOR c1 := 'A' TO max_city DO
    BEGIN
     city_loc[c1].x := random ;
     city_loc[c1].y := random ;
    END ;
   FOR c1 := 'A' TO pred(max_city) DO
    BEGIN
     dist[c1,c1] := 0.0 ;
     FOR c2 := succ(c1) TO max_city DO
      BEGIN
       dist[c1,c2] := sqrt(sqr(city_loc[c1].x - city_loc[c2].x) +
                           sqr(city_loc[c1].y - city_loc[c2].y)) ;
       dist[c2,c1] := dist[c1,c2] ;
      END ;
    END ;
   dist[max_city,max_city] := 0.0 ;
   FOR c1 := 'A' TO max_city DO
    FOR i := 1 TO max_position DO
     u[c1,i] := u00 + (((2 * random - 1.0) / 10.0) * u0) ;
   clrscr ;
   writeln('TSP         [c] 1987 Knowledge Garden Inc.') ;
   writeln('                     473A Malden Bridge Rd') ;
   writeln('                     Nassau, NY 12123') ;
   writeln ;
   writeln('Press <Space Bar> to begin - Press again to stop iterating.') ;
   read(kbd,ch) ;
  END ; (* initialize *)


 BEGIN
  initialize ;
  iterate ;
 END.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -