Initializing help system before first use

Contract allocation


Type: Contract allocation
Rating: 2 (easy-medium)
Description: A public utility, which is divided into six regional districts, wishes to allocate ten power generation contracts to its regions as cheaply as possible. The cost per unit of power generated by each region for each contract is known. If part of a contract is allocated to a region then it must be at least as big as a certain minimum size (5 units). For reliability reasons, no contract may be placed exclusively with only one district. Each district has a limited power generation capacity.
File(s): contract_graph.mos
Data file(s): contract.dat


contract_graph.mos
(!******************************************************
   Mosel Example Problems
   ======================

   file contract.mos
   `````````````````
   TYPE:         Contract allocation problem
   DIFFICULTY:   2
   FEATURES:     simple MIP problem, semi-continuous variables,
                 graphical representation of results
   DESCRIPTION:  A public utility, which is divided into six regional 
                 districts, wishes to allocate ten power generation 
                 contracts to its regions as cheaply as possible. The cost 
                 per unit of power generated by each region for each 
                 contract is known. If part of a contract is allocated to 
                 a region than it must be at least as big as a certain 
                 minimum size (5 units). For reliability reasons, no 
                 contract may be placed exclusively with only one district. 
                 Each district has a limited power generation capacity.     
   FURTHER INFO: `Applications of optimization with Xpress-MP teaching 
                 material', Section 2.2 `Semi-continuous variables: 
                 contract allocation';
                 `Applications of optimization with Xpress-MP', 
                 Section 3.4.3 `Semi-continuous variables'

   (c) 2008 Fair Isaac Corporation
       author: S. Heipcke, Jan. 2001, rev. Sep. 2017
*******************************************************!)

model "Contract allocation"
 uses "mmxprs", "mmsvg"

 declarations
  DISTRICT = 1..6                          ! Districts
  CONTRACT = 1..10                         ! Contracts
  OUTPUT: array(DISTRICT) of integer       ! Maximum output per district
  COST  : array(DISTRICT) of integer       ! Cost per district
  VOLUME: array(CONTRACT) of integer       ! Volume of contracts

  alloc: array(DISTRICT,CONTRACT) of mpvar ! 1 if a bid is chosen, 0 otherwise
  quant: array(DISTRICT,CONTRACT) of mpvar ! Quantities allocated to contractors
 end-declarations

 initializations from 'contract.dat'
  OUTPUT COST VOLUME
 end-initializations
 
! Objective function: total cost
 Cost:= sum(d in DISTRICT, c in CONTRACT) COST(d)*quant(d,c)

 forall(c in CONTRACT) do
  sum(d in DISTRICT) quant(d,c) >= VOLUME(c) ! Cover the req. contract volume
  sum(d in DISTRICT) alloc(d,c) >= 2         ! At least 2 districts per contract
 end-do 

! Do not exceed maximum output of any district
 forall(d in DISTRICT) Output(d):= sum(c in CONTRACT) quant(d,c) <= OUTPUT(d)

! If a contract is allocated to a district, then at least 1 unit is 
! allocated to it
 forall(d in DISTRICT, c in CONTRACT) MinAlloc(d,c):= alloc(d,c) <= quant(d,c) 

 forall(d in DISTRICT, c in CONTRACT) do
  alloc(d,c) is_binary
  quant(d,c) is_semcont 5
  quant(d,c) <= OUTPUT(d)
 end-do
   
! Solve the problem
 minimize(Cost)

! Solution printing
 writeln("Total cost: ", getobjval)
 writeln("Contract  Districts")
 forall(c in CONTRACT) do
  write(strfmt(c,3), " (", VOLUME(c), "):")
  forall(d in DISTRICT) 
   write(if(getsol(quant(d,c))>0, " "+d+"("+getsol(quant(d,c))+")", "")) 
  writeln
 end-do

! Solution drawing
 declarations
  DistrGraph: array(DISTRICT) of string
 end-declarations


 forall(d in DISTRICT) do
   DistrGraph(d):= "D"+d
   svgaddgroup(DistrGraph(d), "District "+d)
   svgsetstyle(SVG_STROKEWIDTH, "0.3")
 end-do
 forall(c in CONTRACT) do
  ct:=0.0
  forall(d in DISTRICT) 
   if getsol(quant(d,c))>0 then
!    svgaddrectangle(DistrGraph(d), 2*c-0.2, ct, 0.4, getsol(quant(d,c)))
    svgaddrectangle(DistrGraph(d), c-0.1, ct, 0.2, getsol(quant(d,c))/2)
    ct+=getsol(quant(d,c))/2
   end-if 
 end-do

 svgsetgraphlabels("Contracts", "Contract volume")
 svgsetgraphviewbox(0, 0, CONTRACT.size+1, 0.5*max(c in CONTRACT) VOLUME(c))

 svgsave("contract.svg")
 svgrefresh
 svgwaitclose("Close browser window to terminate model execution.", 1)
end-model

© 2001-2026 Fair Isaac Corporation. All rights reserved. This documentation is the property of Fair Isaac Corporation (“FICO”). Receipt or possession of this documentation does not convey rights to disclose, reproduce, make derivative works, use, or allow others to use it except solely for internal evaluation purposes to determine whether to purchase a license to the software described in this documentation, or as otherwise set forth in a written software license agreement between you and FICO (or a FICO affiliate). Use of this documentation and the software described in it must conform strictly to the foregoing permitted uses, and no other use is permitted.