Transport - Insight GUI, user graph
|
|
|
| Type: | Transportation problem |
| Rating: | 3 (intermediate) |
| Description: |
|
| 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: £"></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
|
