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

© 2001-2020 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.