Initializing help system before first use

Transport - Insight GUI, user graph


Type: Transportation problem
Rating: 3 (intermediate)
Description:
  • transport_insight.zip: Xpress Insight application (includes transport_insight.mos, transportdata.vdl, transportcustsel.vdl, transportres.vdl, transportressum.vdl, transprt.dat, transport_insight.xml)
  • transport_graph.mos: Graphical solution output with mmsvg (requires transprt.dat)
File(s): transport_insight.mos, transportdata.vdl, transportcustsel.vdl, transportres.vdl, transportressum.vdl, transport_insight.xml, transport_graph.mos
Data file(s): transport_insight.zip, transprt.dat

transport_insight.mos
(!******************************************************
   Mosel User Guide Example Problems
   =================================

   file transport_insight.mos
   ``````````````````````````
   Solution display in Insight application.

   (c) 2012 Fair Isaac Corporation
       author: S.Heipcke, Sep. 2012, rev. Dec. 2020
*******************************************************!)

model "Transport"
 uses "mmxprs", "mmsystem", "mmsvg"
 uses "mminsight"

 version 1.0.2

 forward procedure readdata
 forward function solveproblem: boolean
 forward procedure drawsolution(ifdisplay: boolean)

 !@insight.manage=input
 public declarations
  !@insight.alias Customer regions
  REGION: set of string                 ! Set of customer regions
  !@insight.alias Plants
  PLANT: set of string                  ! Set of plants
  !@insight.alias Demand
  DEMAND: array(REGION) of real         ! Demand at regions
  !@insight.alias Production capacity
  PLANTCAP: array(PLANT) of real        ! Production capacity at plants
  !@insight.alias Unit production cost
  PLANTCOST: array(PLANT) of real       ! Unit production cost at plants
  !@insight.alias Capacity on each route
  TRANSCAP: dynamic array(PLANT,REGION) of real
                                        ! Capacity on each route plant->region
  !@insight.alias Distance per route
  DISTANCE: dynamic array(PLANT,REGION) of real
                                        ! Distance of each route plant->region
  !@insight.alias Fuel cost per unit distance
  FUELCOST: real                        ! Fuel cost per unit distance
  !@insight.update.afterexecution=true
  ! @insight.hidden=true
  SELCUST: array(REGION) of boolean     ! Customer selection for display
  ! @insight.hidden=true
  !@insight.update.afterexecution=true
  CURRENTPLANT: string                  ! Plant selection for display
 end-declarations

 !@insight.manage=result
 public declarations
  !@insight.alias Production capacity limits
  MaxCap: array(PLANT) of linctr        ! Capacity constraints
  !@insight.alias Amount shipped
  flow: dynamic array(PLANT,REGION) of mpvar    ! Flow on each route
  RunDate: string                       ! Date for display
  !@insight.hidden=true
  MincostSol: real
  !@insight.hidden=true
  pltotal: array(PLANT) of real         !@insight.alias Total
  !@insight.hidden=true
  rgtotal: array(REGION) of real
 end-declarations

 !@insight.resultdata.delete=on-execute

! Handling of Insight execution modes
! (whether to read data from file or use scenario data)
 case insightgetmode of
  INSIGHT_MODE_LOAD: do
     readdata             ! Initialize data from file
     exit(0)              ! Stop model run after data input
    end-do
  INSIGHT_MODE_RUN: do
     insightpopulate      ! Inject scenario data
     if solveproblem then   ! State and solve the optimization problem
      drawsolution(false)
     end-if
    end-do
  INSIGHT_MODE_NONE: do
     readdata             ! Non-Insight runs: initialize data from file
     if solveproblem then   ! State and solve the optimization problem
      drawsolution(true)
     end-if
    end-do
  else
    writeln_("Unknown run mode")
    exit(1)
 end-case

!***********************************************************************
 ! **** State and solve the optimization problem
 function solveproblem: boolean
 ! Create the flow variables that exist
  forall(p in PLANT, r in REGION | exists(TRANSCAP(p,r)) ) create(flow(p,r))

 ! Objective: minimize total cost
  MinCost:= sum(p in PLANT, r in REGION | exists(flow(p,r)))
             (FUELCOST * DISTANCE(p,r) + PLANTCOST(p)) * flow(p,r)

 ! Limits on plant capacity
  forall(p in PLANT) MaxCap(p):= sum(r in REGION) flow(p,r) <= PLANTCAP(p)

 ! Satisfy all demands
  forall(r in REGION) sum(p in PLANT) flow(p,r) = DEMAND(r)

 ! Bounds on flows
  forall(p in PLANT, r in REGION | exists(flow(p,r)))
   flow(p,r) <= TRANSCAP(p,r)

  insightminimize(MinCost)      ! Solve problem through Xpress Insight

  setparam("datetimefmt", "%0d-%N-%y, %0H:%0M:%0S")
  RunDate:= string(datetime(SYS_NOW))

  if getprobstat=XPRS_OPT then
   writeln("Solution: ", getobjval)

 ! Result objects accessed by Xpress Insight
   MincostSol:= getobjval
   pltotal:= array(p in PLANT) sum(r in REGION) flow(p,r).sol
   rgtotal:= array(r in REGION) sum(p in PLANT) flow(p,r).sol

   returned:=true
  else
   writeln("No solution found")
   returned:=false
  end-if
 end-function

 ! **** Data input from file
 procedure readdata
  initializations from 'transprt.dat'
       DEMAND
       [PLANTCAP,PLANTCOST] as 'PLANTDATA'
       [DISTANCE,TRANSCAP] as 'ROUTES'
       FUELCOST
  end-initializations
 end-procedure

 ! **** Create an SVG graphic representing the solution
 procedure drawsolution(ifdisplay: boolean)
  declarations
   YP: array(PLANT) of real           ! y-coordinates of plants
   YR: array(REGION) of real          ! y-coordinates of sales regions
  end-declarations

  ! Scale the size of the displayed graph
  svgsetgraphviewbox(0.2,0.4,4,getsize(REGION)-0.55)
  svgsetgraphsize(490,490)
  svgsetgraphscale(100)
 
  ! Determine y-coordinates for plants and regions
  ct:= floor((getsize(REGION)-getsize(PLANT))/2)
  forall(p in PLANT, ct as counter) YP(p):= ct
writeln(YP)
  ct:=0
  forall(r in REGION, ct as counter) YR(r):= ct-0.5

  ! Draw the plants
  svgaddgroup("PGr", "Plants", svgcolor(0,63,95))
  svgsetstyle(SVG_FONTSIZE, 20)
  forall(p in PLANT) svgaddtext(0.2, YP(p)-0.05, p)

  ! Draw the sales regions
  svgaddgroup("RGr", "Regions", svgcolor(0,157,169))
  svgsetstyle(SVG_FONTSIZE, 20)
  forall(r in REGION) svgaddtext(3.1, YR(r)-0.05, r)

  ! Draw all transport routes
  svgaddgroup("TGr", "Routes", SVG_GREY)
  forall(p in PLANT, r in REGION | exists(TRANSCAP(p,r)) )
   svgaddline(1, YP(p), 3, YR(r))

  ! Draw the routes used by the solution
  svgaddgroup("SGr", "Solution", SVG_ORANGE)
  forall(p in PLANT, r in REGION | exists(flow(p,r)) and getsol(flow(p,r)) > 0)
   svgaddarrow(1, YP(p), 3, YR(r))

  ! Generate the SVG graphic file
  svgsave("transport.svg")

  ! Don't try to display the graphic if this model is run within Insight
  if ifdisplay then
   svgrefresh
   svgwaitclose("Close browser window to terminate model execution.", 1)
  else
   ! Upload the graphic as attachment
   insightputscenattach("transport.svg",true)
   insightsetscenattachtags("transport.svg", ["resultgraph"])
  end-if
 end-procedure
end-model

transportdata.vdl
<vdl version="4.7">
  <vdl-page>    <!-- 'vdl' and 'vdl-page' tags must always be present -->

    <!-- 'header' element: container for any vdl elements that are not part 
         of the page layout -->
    <vdl-header>
      <vdl-action-group name="runModel">
        <vdl-action-execute mode="RUN"></vdl-action-execute>
      </vdl-action-group>
    </vdl-header>

    <!-- Structural element 'section': print header text for a section -->
    <vdl-section heading="Transportation data input">

      <!-- Structural element 'row': arrange contents in rows -->
      <vdl-row>
        <!-- A form contains one or several input elements -->
        <vdl-column size="4">
          <vdl-form>
            <!-- 'Run' button to launch optimization -->
            <vdl-button vdl-event="click:actions.runModel" 
                        label="Run optimization"></vdl-button>
          </vdl-form>
        </vdl-column> 
        <vdl-column size="4">
          <vdl-form>
            <!-- Input field for the fuel cost -->
            <vdl-field entity="FUELCOST" label-size="8" size="4"/>
          </vdl-form>
        </vdl-column> 
      </vdl-row>

      <vdl-row>
        <!-- Several columns within a 'row' for display side-by-side,
	     dividing up the total row width of 12 via 'size' setting
             on each column. -->
        <vdl-column size="4" heading="Plant data">
	  <!-- Display the plant data input values, default table format -->
          <vdl-table>
             <vdl-table-column entity="PLANTCAP" editable="true"/>
             <vdl-table-column entity="PLANTCOST" editable="true"/>
          </vdl-table>
        </vdl-column> 
        <vdl-column size="4" heading="Customer demands">
          <!-- Display the demand input values, default table format -->
          <vdl-table>
            <vdl-table-column entity="DEMAND" editable="true"/>  
          </vdl-table>
        </vdl-column> 
        <vdl-column size="4" heading="Transportation routes">
          <!-- Display the route input values, default table format,
               enabling pagewise display with 8 entries per page -->
          <vdl-table page-mode="paged" page-size="8"> 
            <vdl-table-column entity="DISTANCE" editable="true"/>
            <vdl-table-column entity="TRANSCAP" editable="true"/>
          </vdl-table>
        </vdl-column>
      </vdl-row>
    </vdl-section>
  </vdl-page>
</vdl>

transportcustsel.vdl
<vdl version="4.7">
    <!-- Implementation of a table row filter  -->
    <script>
        function filterRow(rowData, idx, current, Select) {
            // Plant === CURRENTPLANT && SELCUST for selecting the customers
            return (rowData[0] === current.value) && Select(rowData[1]).value;
        }
    </script>
    <vdl-page>
        <!-- 'vdl' and 'vdl-page' tags must always be present -->

        <!-- Structural element 'section': print header text for a section -->
        <vdl-section heading="Customer selection">
            <vdl-row>
                <vdl-column size="12">
                    <vdl-row>
                        <vdl-column><span vdl-text="Example of interaction between VDL elements: selecting customers and plant locations for display of input and result data in a filtered table."></span></vdl-column>
                    </vdl-row>
                    <vdl-row>
                        <!-- Display the input values as a table for indices 
                             selected upfront. -->
                        <!-- Several columns within a 'row' for display 
                             side-by-side, dividing up the total row width 
                             of 12 via 'size' setting on each column. -->
                        <vdl-column size="4" heading="Customer selection">
                            <vdl-table>
                                <vdl-table-column entity="SELCUST" editable="true"></vdl-table-column>
                            </vdl-table>
                        </vdl-column>
                        <vdl-column size="8" heading="Data and results for selected customers">
                            <vdl-form>
                                <vdl-field label="Plants" entity="CURRENTPLANT" options-set="PLANT"></vdl-field>
                            </vdl-form>
                            <vdl-table row-filter="=function(rowData, idx) {return filterRow(rowData, idx, scenario.entities.CURRENTPLANT, scenario.entities.SELCUST)}">
                                <vdl-table-column entity="TRANSCAP"></vdl-table-column>
                                <vdl-table-column entity="DISTANCE"></vdl-table-column>
                                <vdl-table-column entity="flow"></vdl-table-column>
                            </vdl-table>
                        </vdl-column>
                    </vdl-row>
                </vdl-column>
            </vdl-row>
        </vdl-section>
    </vdl-page>
</vdl>

transportres.vdl
<vdl version="4.7">
    <!-- 'vdl' and 'vdl-page' must always be present -->
    <vdl-page>
        <!-- 'header' element: container for any vdl elements that are not part 
             of the page layout -->
        <vdl-header>
         <!-- Optional style definition -->
             <style>
                 .Strong {
                     font-weight: bold;
                     font-style: italic;
                 }
             </style>
        </vdl-header>
 
        <!-- Placeholder message -->
	<vdl-container vdl-if="=!scenario.summaryData.hasResultData">
            <span vdl-text="No results available. Run the scenario to see the results." 
            style="font-style:italic"></span></vdl-container>

        <!-- Structural element 'section': 
             if hasResultData: display data once result values become available 
                              (after scenario execution) -->
        <vdl-section heading="Transportation Plan" vdl-if="=scenario.summaryData.hasResultData">

            <!-- Structural element 'row': arrange contents in rows -->
            <vdl-row>
                <!-- Several columns within a 'row' for display side-by-side,
                     dividing up the total row width of 12 via 'size' setting
                     on each column. -->
                <!-- Display inline text element with objective value -->
                <vdl-column size="4">
                    <vdl-container><span vdl-text="Total cost: &#163;"></span><span vdl-text="=insight.Formatter.formatNumber(scenario.entities.MincostSol.value, 
  '#,###.00')"></span></vdl-container>
                </vdl-column>
                <vdl-column size="8">
                    <vdl-container><span vdl-text="Date: "></span><span inline="true" vdl-text="=scenario.entities.RunDate.value" vd-selection="510.3619866979374"></span></vdl-container>
                </vdl-column>
            </vdl-row>
            <vdl-row>
                <vdl-column size="6">
                    <vdl-row>
                        <!-- Display the 'flow' solution values, showing the 
                             table in rectangular format (last index across the 
                             columns) with an additional colum for the 
                             single-index array 'pltotal' printed in bold font. -->
                        <vdl-column size="12" heading="Customized Autotable">
                            <vdl-table>
                                <vdl-table-column entity="flow" heading="=r.label" vdl-repeat="=r in scenario.entities.REGION">
                                    <vdl-index-filter set="REGION" value="=r.value"></vdl-index-filter>
                                </vdl-table-column>
                                <vdl-table-column entity="pltotal" label="Total" class="Strong"></vdl-table-column>
                            </vdl-table>
                        </vdl-column>
                    </vdl-row>
                    <vdl-row>
                        <!-- Display 'flow' solution values using the default 
                             table format, enabling pagewise display with 
                             10 entries per per -->
                        <vdl-column size="12" heading="Default Autotable format">
                            <vdl-table page-mode="paged" page-size="10">
                                <vdl-table-column entity="flow"></vdl-table-column>
                            </vdl-table>
                        </vdl-column>
                    </vdl-row>
                </vdl-column>
                <!-- Display 'flow' solution values as a stacked bar chart -->
                <vdl-column size="6" heading="Chart of result data">
                    <vdl-chart bar-mode="stack">
                        <vdl-chart-series entity="flow" series-set="PLANT"></vdl-chart-series>
                    </vdl-chart>
                </vdl-column>
            </vdl-row>
            <vdl-row>
                <vdl-column size="12">
                    <vdl-container><span vdl-text="Example of an SVG graphic generated by the Mosel model during a scenario run and added into scenario attachments:"></span></vdl-container>
                    <vdl-container><img vdl-attr="={src: scenario.attachments('transport.svg').dataUrl + '?lastModified='+scenario.attachments('transport.svg').lastModifiedDate}" width="400" height="400"  /></vdl-container>
                </vdl-column>
            </vdl-row>
        </vdl-section>
    </vdl-page>
</vdl>

transportressum.vdl
<vdl version="4.7">
    <!-- 'vdl' and 'vdl-page' must always be present -->
    <vdl-page>
        <!-- Structural element 'section': print header text for a section -->
        <vdl-section heading="Comparison of scenario results">
            <vdl-row>
                <vdl-column>
                    <p><span vdl-text="Viewing "></span><span vdl-text="=scenarios.length"></span><span vdl-text=" scenario(s)."></span></p>
                </vdl-column>
            </vdl-row>
            <vdl-row>
                <!-- Display the objective value -->
                <vdl-column heading="Total Cost">
                    <table class="insight-table table-main table-condensed">
                        <thead>
                            <tr>
                                <th vdl-repeat="=s in scenarios" vdl-text="=s.props.name"></th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td vdl-repeat="=s in scenarios" vdl-text="=insight.Formatter.formatNumber(s.entities.MincostSol.value, 
  '#,###.00')"></td>
                            </tr>
                        </tbody>
                    </table>
                </vdl-column>
            </vdl-row>
            <vdl-row>
                <!-- Display 'flow' solution values using the default table format,
                     enabling pagewise display with 10 entries per page -->
                <vdl-column size="12" heading="Quantities transported">
                    <vdl-table page-mode="paged" page-size="10">
                        <vdl-table-column entity="flow" heading="=s.props.name" vdl-repeat="=s,i in scenarios" scenario="=i"></vdl-table-column>
                    </vdl-table>
                </vdl-column>
            </vdl-row>
        </vdl-section>
    </vdl-page>
</vdl>

transport_insight.xml
<?xml version="1.0" encoding="UTF-8"?>
<model-companion xmlns="http://www.fico.com/xpress/optimization-modeler/model-companion" version="3.0">

  <attachment-config>
    <attachment-tags>
      <attachment-tag name="resultgraph" usage="single-file">
        <description>Graph output by running the model.</description>
      </attachment-tag>
    </attachment-tags>
  </attachment-config>

  <client>
    <view-group title="Main">
      <vdl-view title="Input data" default="true" path="transportdata.vdl"/>
      <vdl-view title="Customer selection" default="false" path="transportcustsel.vdl"/>
      <vdl-view title="Transportation plan" default="false" path="transportres.vdl"/>
      <vdl-view title="Result comparison" default="false" path="transportressum.vdl"/>
    </view-group>
  </client>
</model-companion>

transport_graph.mos
(!******************************************************
   Mosel User Guide Example Problems
   ================================= 

   file transport_graph.mos
   ````````````````````````
   Graphical solution output with mmsvg.
   
   (c) 2008 Fair Isaac Corporation
       author: S.Heipcke, 2006, rev. Sep. 2017
*******************************************************!)

model "Transport (Graph)"
 uses "mmxprs", "mmsvg"

 forward procedure draw_solution

 declarations
  REGION: set of string                 ! Set of customer regions
  PLANT: set of string                  ! Set of plants

  DEMAND: array(REGION) of real         ! Demand at regions
  PLANTCAP: array(PLANT) of real        ! Production capacity at plants
  PLANTCOST: array(PLANT) of real       ! Unit production cost at plants
  TRANSCAP: dynamic array(PLANT,REGION) of real
                                        ! Capacity on each route plant->region
  DISTANCE: dynamic array(PLANT,REGION) of real
                                        ! Distance of each route plant->region
  FUELCOST: real                        ! Fuel cost per unit distance

  flow: dynamic array(PLANT,REGION) of mpvar    ! Flow on each route
 end-declarations
 
 initializations from 'transprt.dat'
  DEMAND
  [PLANTCAP,PLANTCOST] as 'PLANTDATA'
  [DISTANCE,TRANSCAP] as 'ROUTES'
  FUELCOST
 end-initializations
 
! Create the flow variables that exist
 forall(p in PLANT, r in REGION | exists(TRANSCAP(p,r)) ) create(flow(p,r))
 
! Objective: minimize total cost
 MinCost:= sum(p in PLANT, r in REGION | exists(flow(p,r))) 
            (FUELCOST * DISTANCE(p,r) + PLANTCOST(p)) * flow(p,r)
 
! Limits on plant capacity
 forall(p in PLANT) sum(r in REGION) flow(p,r) <= PLANTCAP(p)

! Satisfy all demands
 forall(r in REGION) sum(p in PLANT) flow(p,r) = DEMAND(r)
 
! Bounds on flows
 forall(p in PLANT, r in REGION | exists(flow(p,r))) 
  flow(p,r) <= TRANSCAP(p,r)
 
 minimize(MinCost)                       ! Solve the problem

 draw_solution                           ! Solution drawing (SVG)

!***********************************************************************
 procedure draw_solution
  declarations
   YP: array(PLANT) of integer           ! y-coordinates of plants
   YR: array(REGION) of integer          ! y-coordinates of sales regions
  end-declarations
  
  ! Scale the size of the displayed graph
  svgsetgraphviewbox(0.25,0.75,3.75,getsize(REGION)+1)
  svgsetgraphscale(100)

  ! Determine y-coordinates for plants and regions  
  ct:= 1+floor((getsize(REGION)-getsize(PLANT))/2)
  forall(p in PLANT, ct as counter) YP(p):= ct

  ct:=1
  forall(r in REGION, ct as counter) YR(r):= ct
  
  ! Draw the plants
  svgaddgroup("PGr", "Plants", svgcolor(0,63,95))
  forall(p in PLANT) svgaddtext(0.55, YP(p)-0.1, p)
  
  ! Draw the sales regions
  svgaddgroup("RGr", "Regions", svgcolor(0,157,169))
  forall(r in REGION) svgaddtext(3.1, YR(r)-0.1, r)
  
  ! Draw all transport routes
  svgaddgroup("TGr", "Routes", SVG_GREY)
  forall(p in PLANT, r in REGION | exists(TRANSCAP(p,r)) ) 
   svgaddline(1, YP(p), 3, YR(r))
   
  ! Draw the routes used by the solution
  svgaddgroup("SGr", "Solution", SVG_ORANGE)
  forall(p in PLANT, r in REGION | exists(flow(p,r)) and getsol(flow(p,r)) > 0)
   svgaddarrow(1, YP(p), 3, YR(r))

  ! Save graphic in SVG format
  svgsave("transport.svg")

  ! Display the graphic
  svgrefresh
  svgwaitclose("Close browser window to terminate model execution.", 1)
 end-procedure

end-model