FICO
FICO Xpress Optimization Examples Repository
FICO Optimization Community FICO Xpress Optimization Home
Back to examples browserPrevious example

Iterative display of tours

Description
This model iteratively displays sets of subtours connecting a set of locations represented as points. Each display iteration checks for interruption through closing of the display window and pauses for inspection until the user hits the 'Continue' button in the display. Animation (motion) of final display.

Further explanation of this example: 'Mosel Language Reference', Chapter 'mmsvg'


Source Files

Data Files





routes.mos

(!******************************************************
   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,
       '<animateMotion repeatCount="indefinite" path="'+tpath+'" dur="10s"/>')
      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<m)
      DIST(n,m):=round(1.5*sqrt((XPOS(n)-XPOS(m))^2 + (YPOS(n)-YPOS(m))^2)) 

    initializations to "routes"+num+".dat"
      [XPOS,YPOS] as "POS"  DIST
    end-initializations  
  end-procedure
!)
 

Back to examples browserPrevious example