Initializing help system before first use

J. Local authorities and public services


Description:

Problem name and type, features Difficulty
J‑1 Water conveyance / water supply management: Maximum flow problem **
encoding of arcs, finalize, selection with `|'
J‑2 CCTV surveillance: Maximum vertex cover problem **
encoding of network, exists
J‑3 Rigging elections: Partitioning problem ****
algorithm for data preprocessing; file inclusion, 3 nested/recursive procedures, working with sets, if-then, forall-do, exists, finalize
J‑4 Gritting roads: Directed Chinese postman problem ****
algorithm for finding Eulerian path/graph for printing; encoding of arcs, dynamic array, exists, 2 functions implementing Eulerian circuit algorithm, round, getsize, break, while-do, if-then-else
J‑5 Location of income tax offices: p-median problem ****
modeling an implication, all-pairs shortest path algorithm (Floyd-Warshall); dynamic array, exists, procedure for shortest path algorithm, forall-do, if-then, selection with `|'
J‑6 Efficiency of hospitals: Data Envelopment Analysis (DEA) ***
description of DEA method; loop over problem solving with complete re-definition of problem every time, finalize, naming and declaring constraint


File(s): j1water.mos (Mar. 2002), j2bigbro.mos (Mar. 2002), j3elect.mos (Apr. 2002), j3elect_calc.mos (Apr. 2002), j4grit.mos (Mar. 2002), j5tax.mos (Mar. 2002), j6hospit.mos (Mar. 2002)
Data file(s): j1water.dat, j2bigbro.dat, j3elect.dat, j4grit.dat, j5tax.dat, j6hospit.dat

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

   file j1water.mos
   ````````````````
   Water conveyance/water supply management
   
   (c) 2008 Fair Isaac Corporation
       author: S. Heipcke, Mar. 2002
*******************************************************!)

model "J-1 Water supply"
 uses "mmxprs"

 declarations
  ARCS: range                       ! Set of arcs
  NODES=1..12
  
  PIPE: array(ARCS,1..2) of integer ! Definition of arcs (= pipes)
  CAP: array(ARCS) of integer       ! Capacity of arcs
  SOURCE,SINK: integer              ! Number of source and sink nodes
 end-declarations

 initializations from 'j1water.dat'
  PIPE CAP SOURCE SINK
 end-initializations

 finalize(ARCS)

 declarations
  flow: array(ARCS) of mpvar       ! Flow on arcs
 end-declarations

! Objective: total flow
 TotalFlow:= sum(a in ARCS | PIPE(a,2)=SINK) flow(a)

! Flow balances in nodes
 forall(n in NODES | n<>SOURCE and n<>SINK) 
  sum(a in ARCS | PIPE(a,1)=n) flow(a) = sum(a in ARCS | PIPE(a,2)=n) flow(a)

! Capacity limits
 forall(a in ARCS) flow(a) <= CAP(a)

! Solve the problem
 maximize(TotalFlow)
 
! Solution printing
 writeln("Total flow: ", getobjval)
 forall(a in ARCS) writeln(PIPE(a,1), " -> ", PIPE(a,2), ": ", getsol(flow(a)))
 
end-model

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

   file j2bigbro.mos
   `````````````````
   CCTV surveillance
   
   (c) 2008 Fair Isaac Corporation
       author: S. Heipcke, Mar. 2002
*******************************************************!)

model "J-2 CCTV surveillance"
 uses "mmxprs"

 declarations
  NODES=1..49
  STREET: dynamic array(NODES,NODES) of integer  ! 1 if a street connects 
                                                 ! two nodes, 0 otherwise
  
  place: array(NODES) of mpvar     ! 1 if camera at node, 0 otherwise
 end-declarations

 initializations from 'j2bigbro.dat'
  STREET
 end-initializations

 forall(n,m in NODES | exists(STREET(n,m)) and n<m ) 
  STREET(m,n):= STREET(n,m)

! Objective: number of cameras to install
 Total:= sum(n in NODES) place(n)

! Flow balances in nodes
 forall(n,m in NODES | exists(STREET(n,m)) ) place(n)+place(m) >= 1

 forall(n in NODES) place(n) is_binary

! Solve the problem
 minimize(Total)
 
! Solution printing
 writeln("Total number of cameras: ", getobjval)
 forall(n in NODES) write( if(getsol(place(n))>0, " "+n, ""))
 writeln
 
end-model

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

   file j3elect.mos
   ````````````````
   Grouping quarters to election districts
   
   (c) 2008 Fair Isaac Corporation
       author: S. Heipcke, Apr. 2002
*******************************************************!)

model "J-3 Rigging elections"
 uses "mmxprs"

 parameters
  REQD = 6                            ! Required number of districts 
 end-parameters

 declarations
  QUARTERS = 1..14                    ! Number of quarters
  RDIST: range                        ! Set of election districts
  
  MAJ: array(RDIST) of integer        ! 1 if majority of votes, 0 otherwise
  DISTR: array(RDIST,QUARTERS) of integer  ! 1 if quarter is in district, 
                                           ! 0 otherwise
 end-declarations

 include "j3elect_calc.mos"

 declarations
  choose: array(RDIST) of mpvar      ! 1 if district chosen, 0 otherwise
 end-declarations

! Objective: number of votes
 Votes:= sum(d in RDIST) MAJ(d)*choose(d)

! Partitioning
 forall(q in QUARTERS) sum(d in RDIST) DISTR(d,q)*choose(d) = 1
 
! Desired number of districts 
 sum(d in RDIST) choose(d) = REQD

 forall(d in RDIST) choose(d) is_binary

! Solve the problem
 maximize(Votes)
 
! Solution printing
 if(getprobstat<>XPRS_OPT) then
  writeln("Problem is infeasible")
 else 
  writeln("Total number of votes: ", getobjval)
  forall(r in RDIST) if getsol(choose(r))>0 then
   write(r, ": ")
   forall(q in QUARTERS) write(if(DISTR(r,q)>0, " "+q, ""))
   writeln(" (", MAJ(r), ")") 
  end-if
 end-if
  
end-model

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

   file j3elect_calc.mos
   ````````````````''''`
   Include file for data pre-processing

   (c) 2008 Fair Isaac Corporation
       author: S. Heipcke, Apr. 2002
*******************************************************!)

 declarations
  NUMD: integer                         ! Number of possible districts
  RN: range                             ! Neighboring quarters
  
  NEIGHB: dynamic array(QUARTERS,RN) of integer ! Set of neighboring quarters
  POP: array(QUARTERS) of integer       ! Number of electors (in 1000)
  VOTES: array(QUARTERS) of real        ! Number of favorable votes (in 1000)
  MINPOP,MAXPOP,MINSINGLE: integer      ! Limits on electors per district
 end-declarations

 initializations from 'j3elect.dat'
  NEIGHB POP VOTES MINPOP MAXPOP MINSINGLE
 end-initializations

!**** Save a new entry in the list of districts ****
 procedure save_distr(sQ: set of integer)
  NUMD+=1
  forall(q in sQ) DISTR(NUMD,q):=1 
 end-procedure  

!**** Add a neighboring quarter to the current set of quarters ****
 procedure add_neighb(toadd:integer, sQ:set of integer)
  declarations
   nQ: set of integer
  end-declarations
   
  nQ:=sQ+{toadd}
  if(sum(q in nQ) POP(q) >= MINPOP) then      ! Large enough to form distr.
   save_distr(nQ) 
  end-if 
  forall(p in RN | exists(NEIGHB(toadd,p)))   ! Try adding every neighbor
   if(sum(q in nQ) POP(q)+POP(NEIGHB(toadd,p))<=MAXPOP) then
    add_neighb(NEIGHB(toadd,p), nQ)
   end-if   
 end-procedure

!**** Calculate the list of possible districts ****
 procedure calculate_distr
  NUMD:=0
  forall(q in QUARTERS) do
   if (POP(q) >= MINSINGLE and q<>10) then    ! Single quarter districts
    save_distr({q})
   end-if
   forall(p in RN | exists(NEIGHB(q,p)))      ! Try adding every neighbor
    if(POP(q)+POP(NEIGHB(q,p))<=MAXPOP) then
     add_neighb(NEIGHB(q,p),{q})
    end-if 
  end-do
  
  forall(d in 1..NUMD) do                     ! Print the resulting list
   write(d,":")
   forall(q in QUARTERS) write(if(DISTR(d,q)>0, " "+q, ""))
   writeln(" ", (sum(q in QUARTERS | DISTR(d,q)>0) VOTES(q)) *100 / 
                (sum(q in QUARTERS | DISTR(d,q)>0) POP(q)), "%")
  end-do 
  writeln("Number of possible districts: ",NUMD)

  forall(d in 1..NUMD)                        ! Calculate majorities
   MAJ(d):= if(((sum(q in QUARTERS | DISTR(d,q)>0) VOTES(q)) / 
                (sum(q in QUARTERS | DISTR(d,q)>0) POP(q))    >= 0.5), 1, 0)
  finalize(RDIST)
 end-procedure


!**** Start the calculation of the list of possible districts ****
 calculate_distr


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

   file j4grit.mos
   ```````````````
   Gritting roads in a village
   
   (c) 2008 Fair Isaac Corporation
       author: S. Heipcke, Mar. 2002
*******************************************************!)

model "J-4 Gritting circuit"
 uses "mmxprs"

 forward function find_unused(J: array(range) of integer):integer
 forward function add_path(node:integer, J: array(range) of integer):integer

 declarations
  ISEC = 1..12                              ! Set of street intersections

  LEN: dynamic array(ISEC,ISEC) of integer  ! Length of streets
  
  use: dynamic array(ISEC,ISEC) of mpvar    ! Frequency of use of streets
 end-declarations

 initializations from 'j4grit.dat'
  LEN
 end-initializations
 
 forall(i,j in ISEC | exists(LEN(i,j))) create(use(i,j))

! Objective: length of circuit
 Length:= sum(i,j in ISEC | exists(LEN(i,j))) LEN(i,j)*use(i,j)
 
! Balance traffic flow through intersections 
 forall(i in ISEC) sum(j in ISEC) use(i,j) = sum(j in ISEC) use(j,i)
 
! Grit every street
 forall(i,j in ISEC | exists(LEN(i,j))) use(i,j) >= 1

! Solve the problem
 minimize(Length)
 
! Solution printing
 writeln("Total length: ", getobjval)

 ct:=round(getsol(sum(i,j in ISEC) use(i,j)))

 declarations
  TOUR: array(1..ct+1) of integer
  TCOUNT: array(ISEC,ISEC) of integer
 end-declarations
 
! Main loop of the Eulerian circuit algorithm 
 forall(i,j in ISEC | exists(LEN(i,j))) TCOUNT(i,j):=round(getsol(use(i,j)))
 TOUR(1):=1
 ct-=add_path(1,TOUR)
 while(ct>0)
  ct-=add_path(find_unused(TOUR),TOUR)
 writeln("Tour: ", TOUR)

!-----------------------------------------------------------------

! Find first node in list with free path(s)
 function find_unused(J: array(range) of integer):integer
  i:=1
  returned:=1
  while(J(i)>0 and i<getsize(J))
   if (sum(j in ISEC) TCOUNT(J(i),j) > 0) then
    returned:=J(i)
    break
   else
    i+=1 
   end-if 
 end-function

!-----------------------------------------------------------------

! Add a subtour to the current tour
 function add_path(node:integer, J: array(range) of integer):integer
  declarations
   NEWJ: array(1..getsize(J)) of integer
  end-declarations

 ! Insertion position
  pos:=1
  while(J(pos)<>node and pos<getsize(J)) pos+=1

 ! Find a new path
  cur:=node; newct:=0
  while(sum(j in ISEC) TCOUNT(cur,j) > 0) do
   forall(j in ISEC) if(TCOUNT(cur,j) > 0) then
     TCOUNT(cur,j)-=1
     newct+=1; NEWJ(newct):=j
     cur:=j
     break
    end-if 
  end-do

 ! Add the new path to main journey 
  i:=getsize(J)-newct
  while(i>pos) do
   J(i+newct):=J(i)
   i-=1
  end-do 
  forall(j in 1..newct) J(pos+j):=NEWJ(j)
  returned:=newct
 end-function
 
end-model

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

   file j5tax.mos
   ``````````````
   Choice of locations for income tax offices
   
   (c) 2008 Fair Isaac Corporation
       author: S. Heipcke, Mar. 2002
*******************************************************!)

model "J-5 Tax office location"
 uses "mmxprs"

 forward procedure calculate_dist

 declarations
  CITIES = 1..12                        ! Set of cities

  DIST: array(CITIES,CITIES) of integer ! Distance matrix
  POP: array(CITIES) of integer         ! Population of cities
  LEN: dynamic array(CITIES,CITIES) of integer ! Road lengths
  NUMLOC: integer                       ! Desired number of tax offices
  
  build: array(CITIES) of mpvar         ! 1 if office in city, 0 otherwise
  depend: array(CITIES,CITIES) of mpvar ! (c,d) 1 if city c depends on office
                                        ! in city d, 0 otherwise
 end-declarations

 initializations from 'j5tax.dat'
  LEN POP NUMLOC
 end-initializations

! Calculate the distance matrix
 calculate_dist    

! Objective: weighted total distance
 TotDist:= sum(c,d in CITIES) POP(c)*DIST(c,d)*depend(c,d)

! Assign cities to offices
 forall(c in CITIES) sum(d in CITIES) depend(c,d) = 1
 
! Limit total number of offices
 sum(c in CITIES) build(c) <= NUMLOC
 
! Relations between dependencies and offices built
 forall(c,d in CITIES) depend(c,d) <= build(d)  
 
 forall(c in CITIES) build(c) is_binary

! Solve the problem
 minimize(TotDist)
 
! Solution printing
 writeln("Total weighted distance: ", getobjval, 
        " (average per inhabitant: ", getobjval/sum(c in CITIES) POP(c), ")")
 forall(c in CITIES) if(getsol(build(c))>0) then
  write("Office in ",c,": ")
  forall(d in CITIES) write(if(getsol(depend(d,c))>0, " "+d, ""))
  writeln
 end-if

!-----------------------------------------------------------------

! Calculate the distance matrix using Floyd-Warshall algorithm
 procedure calculate_dist
 ! Initialize all distance labels with a sufficiently large value
  BIGM:=sum(c,d in CITIES | exists(LEN(c,d))) LEN(c,d)
  forall(c,d in CITIES) DIST(c,d):=BIGM

  forall(c in CITIES) DIST(c,c):=0    ! Set values on the diagonal to 0
 
! Length of existing road connections
  forall(c,d in CITIES | exists(LEN(c,d))) do
   DIST(c,d):=LEN(c,d)
   DIST(d,c):=LEN(c,d)
  end-do
 
! Update shortest distance for every node triple 
  forall(b,c,d in CITIES | c<d )
   if DIST(c,d) > DIST(c,b)+DIST(b,d) then
    DIST(c,d):= DIST(c,b)+DIST(b,d)
    DIST(d,c):= DIST(c,b)+DIST(b,d)
   end-if 
 end-procedure 
 
end-model

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

   file j6hospit.mos
   `````````````````
   Compare the efficiency of hospitals (DEA method)
   
   (c) 2008 Fair Isaac Corporation
       author: S. Heipcke, Mar. 2002
*******************************************************!)

model "J-6 Hospital efficiency"
 uses "mmxprs"

 declarations
  HOSP = 1..4                           ! Set of hospitals
  SERV: set of string                   ! Service indicators
  RES: set of string                    ! Resource indicators

  INDSERV: array(SERV,HOSP) of real     ! Service indicator values
  INDRES: array(RES,HOSP) of real       ! Resource indicator values
 end-declarations

 initializations from 'j6hospit.dat'
  INDSERV INDRES
 end-initializations

 finalize(SERV); finalize(RES)

 declarations
  eff: mpvar                            ! Efficiency value
  coef: array(HOSP) of mpvar            ! Coefficients for DEA method
  fserv: array(SERV) of mpvar           ! Service indicator of fict. hospital
  fres: array(RES) of mpvar             ! Resource indicator of fict. hospit.
  LimServ: array(SERV) of linctr        ! Hospital-specific service constr.
  LimRes: array(RES) of linctr          ! Hospital-specific resource constr.
 end-declarations

! DEA coefficients
 sum(h in HOSP) coef(h) = 1
 
! Relations between service and resource indicators
 forall(s in SERV) fserv(s) = sum(h in HOSP) INDSERV(s,h)*coef(h)
 forall(r in RES) fres(r) = sum(h in HOSP) INDRES(r,h)*coef(h)

! Solve the problem for every hospital 
 forall(h in HOSP) do
 ! Limits on services and resources for the hospital currently looked at
  forall(s in SERV) LimServ(s):= fserv(s) >= INDSERV(s,h)  
  forall(r in RES) LimRes(r):= fres(r) <= INDRES(r,h)*eff  
 
 ! Minimize efficiency index
  minimize(eff)
  writeln("Evaluation of hospital ", h, ": ", getobjval)
 end-do

end-model