| (!******************************************************
   Mosel graph examples
   ==================== 
   file routes.mos
   ```````````````
   Iterative display of routes with subtours,
   demonstrating interaction between model and
   display via 'pause' to inspect a graph and 
   stop algorithm by 'closing' event.
   - Using SVG animation -
     (only visible with browsers supporting SVG animation)
   
   Uses functions from the mmsvg library to draw
   a "User graph" in SVG format.
   
   (c) 2017 Fair Isaac Corporation
       author: S. Heipcke, Jul. 2017, rev. Sep. 2017
*******************************************************!)
model routes
  uses "mmsvg"
 
  declarations
    RT: range
    solroute = record
      sol: real
      tours: dynamic array(RT) of list of integer
    end-record
    Routes: array(Sols:range) of solroute
    XPOS,YPOS: array(RP:range) of integer
    tpath: text
  end-declarations
  initializations from "routes.dat"
    Routes  [XPOS,YPOS] as "POS"
  end-initializations
  svgrefresh
  forall(s in Sols) do
   ! Interrupt loop if window is closed
    if svgclosing then break; end-if
   ! Delete previous graph contents 
    svgerase
   
    ct:=0
    forall(ct as counter, t in RT | exists(Routes(s).tours(t)) ) do
      svgaddgroup("t"+t, "Tour "+t)
      svgaddline(sum(i in Routes(s).tours(t)) [XPOS(i),YPOS(i)])
    end-do
    svgaddgroup("N", "Nodes", SVG_GRAY)
    svgsetstyle("SVG_STROKEWIDTH", 2)
    forall(p in RP) svgaddpoint(XPOS(p),YPOS(p))
    svgaddgroup("msg", "", SVG_BLACK)
    svgaddtext(15, 5, "Total tour length: " + Routes(s).sol + 
      if(ct>1, " ("+ct+" subtours)", " (solution)"))
   ! Add SVG animation for final tour 
   ! (only visible in browsers with SVG support)
    if ct=1 then
      tf:= min(t in RT | exists(Routes(s).tours(t)) ) t
      tlist:= gethead(Routes(s).tours(tf),-1)
      prevx:=XPOS(Routes(s).tours(tf).first)
      prevy:=YPOS(Routes(s).tours(tf).first)
      svgaddfile("./truck.gif", "truck.gif")     ! Upload graphic file
      svgaddimage("t"+tf, "truck.gif", prevx-10, prevy-10, 30, 30)
      tpath:="m"               ! Define a motion path with relative positions
      forall(i in tlist) do
        tpath+=text(" ")+(XPOS(i)-prevx)+" "+(-(YPOS(i)-prevy))
        prevx:=XPOS(i); prevy:=YPOS(i)
      end-do
      tpath+=" Z"              ! Return to the initial point
      svgsetstyle(svggetlastobj, SVG_ANIMATE,
       '')
      svgsave("tour.svg")
    end-if
   ! Display tours
    svgrefresh
   ! Pause if there is more than 1 tour
    if ct>1 then svgpause; end-if
  end-do
 ! Wait for display window to close 
  svgwaitclose("Close browser window to terminate model execution.")
end-model
(! Generate input data for TSP solving
  procedure gendata(num:integer)
    declarations
      XPOS,YPOS: array(RP:range) of integer
      DIST: dynamic array(RP,RP) of integer
    end-declarations
  
    setrandseed(7)
    forall(p in 1..num) do
      XPOS(p):=25+round(450*random)
      YPOS(p):=25+round(450*random)
    end-do
    forall(n,m in RP | n |