(!******************************************************
   Mosel User Guide Example Problems
   ================================= 

   file transport2.mos 
   ``````````````````` 
   Formatted output printing.
 
   (c) 2008 Fair Isaac Corporation
       author: S. Heipcke, 2001, rev. Dec. 2020
*******************************************************!)

model "Transport 2"
 uses "mmxprs", "mmsystem"

 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

!***********************************************************************
 procedure printtable
  declarations
   rsum: array(REGION) of integer    ! Auxiliary data table for printing
   psum,ct,iflow: integer            ! Counters
  end-declarations

          ! Print heading and the first line of the table
  writeln("\nProduct Distribution\n", "="*20)
  writeln(strfmt("Sales Region",48))
  write(strfmt("",15), "| ")
  forall(r in REGION) write(strfmt(r,9))
  writeln(" |", strfmt("TOTAL",6), " Capacity") 
  writeln("-"*80)

         ! Print the solution values of the flow variables and
         ! calculate totals per region and per plant
  ct:=0
  forall(p in PLANT, ct as counter) do
    if ct=2 then 
      write(" Plant ", strfmt(p,-8), "|")
    else
      write("       ", strfmt(p,-8), "|")
    end-if
    psum:=0
    forall(r in REGION) do
      iflow:=round(getsol(flow(p,r)))
      psum += iflow
      rsum(r) += iflow
      if iflow<>0 then 
        write(strfmt(iflow,9))
      else
        write("      -- ")
      end-if
    end-do
    writeln("  |", strfmt(psum,6), strfmt(round(PLANTCAP(p)),8))
  end-do

         ! Print the column totals
  writeln("-"*80)
  write(strfmt(" TOTAL",-15), "|") 
  forall(r in REGION) write(strfmt(rsum(r),9))
  writeln("  |", strfmt(sum(r in REGION) rsum(r),6),
          strfmt(sum(p in PLANT) PLANTCAP(p),8)) 

         ! Print demand of every region
  write(strfmt(" Demand",-15), "|") 
  forall(r in REGION) write(strfmt(round(DEMAND(r)),9))

         ! Print objective function value
  writeln("\n\nTotal cost of distribution = ", strfmt(getobjval/1e6,0,3), 
          " million.")

 end-procedure
!***********************************************************************
 
 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

 printtable                              ! Solution printout
 
end-model
