(!****************************************************** 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 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