i1assign.mos |
(!******************************************************
Mosel Example Problems
======================
file i1assign.mos
`````````````````
Assigning workers to machines
(c) 2008 Fair Isaac Corporation
author: S. Heipcke, Mar. 2002
*******************************************************!)
model "I-1 Personnel assignment"
uses "mmxprs"
forward procedure parallel_heur
forward procedure print_sol(text1,text2:string)
declarations
PERS = 1..6 ! Personnel
MACH = 1..6 ! Machines
OUTP: array(PERS,MACH) of integer ! Productivity
end-declarations
initializations from 'i1assign.dat'
OUTP
end-initializations
! **** Heuristic solution for parallel assignment ****
parallel_heur
! **** Exact solution for parallel assignment ****
declarations
assign: array(PERS,MACH) of mpvar ! 1 if person assigned to machine,
! 0 otherwise
end-declarations
! Objective: total productivity
TotalProd:= sum(p in PERS, m in MACH) OUTP(p,m)*assign(p,m)
! One machine per person
forall(p in PERS) sum(m in MACH) assign(p,m) = 1
! One person per machine
forall(m in MACH) sum(p in PERS) assign(p,m) = 1
! Solve the problem
maximize(TotalProd)
print_sol("Exact solution (parallel assignment)", "Total")
! **** Exact solution for serial machines ****
declarations
pmin: mpvar ! Minimum productivity
end-declarations
! Calculate minimum productivity
forall(p in PERS) sum(m in MACH) OUTP(p,m)*assign(p,m) >= pmin
forall(p in PERS, m in MACH) assign(p,m) is_binary
! Solve the problem
maximize(pmin)
print_sol("Exact solution (serial machines)", "Minimum")
!-----------------------------------------------------------------
! Heuristic solution for parallel assignment
procedure parallel_heur
declarations
ALLP, ALLM: set of integer ! Copies of sets PERS and MACH
HProd: integer ! Total productivity value
pmax,omax,mmax: integer
end-declarations
! Copy the sets of workers and machines
forall(p in PERS) ALLP+={p}
forall(m in MACH) ALLM+={m}
! Assign workers to machines as long as there are unassigned persons
while (ALLP<>{}) do
pmax:=0; mmax:=0; omax:=0
! Find the highest productivity among the remaining workers and machines
forall(p in ALLP, m in ALLM)
if OUTP(p,m) > omax then
omax:=OUTP(p,m)
pmax:=p; mmax:=m
end-if
HProd+=omax ! Add to total productivity
ALLP-={pmax}; ALLM-={mmax} ! Remove person and machine from sets
writeln(" ",pmax, " operates machine ", mmax, " (", omax, ")")
end-do
writeln(" Total productivity: ", HProd)
end-procedure
!-----------------------------------------------------------------
! Solution printing
procedure print_sol(text1,text2:string)
writeln(text1,":")
forall(p in PERS) do
mp:=round(getsol(sum(m in MACH) m*assign(p,m)))
writeln(" ",p, " operates machine ", mp, " (", OUTP(p,mp), ")")
end-do
writeln(" ", text2, " productivity: ", getobjval)
end-procedure
end-model
|
|
i2nurse.mos |
(!******************************************************
Mosel Example Problems
======================
file i2nurse.mos
````````````````
Work schedule for nurses
(c) 2008 Fair Isaac Corporation
author: S. Heipcke, Mar. 2002
*******************************************************!)
model "I-2 Scheduling nurses"
uses "mmxprs"
declarations
NT = 12 ! Number of time periods
TIME = 0..NT-1
WORK: set of integer ! Nurses started in other time periods
! that are working during a period
REQ: array(TIME) of integer ! Required number of nurses per time period
Period: array(TIME) of linctr ! Constraints on personnel per period
start: array(TIME) of mpvar ! Nurses starting work in a period
end-declarations
initializations from 'i2nurse.dat'
REQ
end-initializations
WORK:= {0, -1, -3, -4}
! Objective: total personnel required
Total:= sum(t in TIME) start(t)
! Nurses working per time period
forall(t in TIME) Period(t):= sum(i in WORK) start((t+i+NT) mod NT) >= REQ(t)
forall(t in TIME) start(t) is_integer
! Solve the problem
minimize(Total)
! Solution printing
writeln("Total personnel: ", getobjval)
forall(t in TIME)
writeln(strfmt(t*2,2), ":00-",strfmt((t+1)*2,2), ":00 : starting: ",
getsol(start(t)),
" total: ", getsol(sum(i in WORK) start((t+i+NT) mod NT)))
! **** Second problem: minimize overtime with given staff level ****
declarations
NUM: integer ! Available total staff
overt: array(TIME) of mpvar ! Nurses working overtime
end-declarations
initializations from 'i2nurse.dat'
NUM
end-initializations
! Objective: total overtime worked
TotalOvert:= sum(t in TIME) overt(t)
! Nurses working per time period
forall(t in TIME)
Period(t):= overt((t-5+NT) mod NT) + sum(i in WORK) start((t+i+NT) mod NT) >=
REQ(t)
! Limit on total number of nurses
Total <= NUM
forall(t in TIME) do
overt(t) is_integer
overt(t) <= start(t)
end-do
! Solve the problem
minimize(TotalOvert)
! Solution printing
writeln("\nPersonnel working overtime: ", getobjval)
forall(t in TIME)
writeln(strfmt(t*2,2), ":00-",strfmt((t+1)*2,2), ":00 : starting: ",
getsol(start(t)), " total: ", getsol(Period(t)+REQ(t)),
" overtime: ", getsol(overt((t-5+NT) mod NT)))
end-model
|
|
i3school.mos |
(!******************************************************
Mosel Example Problems
======================
file i3school.mos
`````````````````
Determine a timetable for 2 classes
(c) 2008 Fair Isaac Corporation
author: S. Heipcke, Mar. 2002
*******************************************************!)
model "I-3 School timetable"
uses "mmxprs"
declarations
TEACHERS: set of string ! Set of teachers
CLASS = 1..2 ! Set of classes
NP = 4 ! Number of time periods for courses
ND = 5 ! Days per week
SLOTS=1..NP*ND ! Set of time slots for the entire week
COURSE: array(TEACHERS,CLASS) of integer ! Lessons per teacher and class
end-declarations
initializations from 'i3school.dat'
COURSE
end-initializations
finalize(TEACHERS)
declarations
teach: array(TEACHERS,CLASS,SLOTS) of mpvar
! teach(t,c,l) = 1 if teacher t gives a
! lesson to class c during time period l
end-declarations
! Objective: number of "holes" in the class timetables
Hole:=
sum(t in TEACHERS, c in CLASS, d in 0..ND-1) (teach(t,c,d*NP+1) +
teach(t,c,(d+1)*NP))
! Plan all courses
forall(t in TEACHERS, c in CLASS) sum(l in SLOTS) teach(t,c,l) = COURSE(t,c)
! For every class, one course at a time
forall(c in CLASS, l in SLOTS) sum(t in TEACHERS) teach(t,c,l) <= 1
! Teacher teaches one course at a time
forall(t in TEACHERS, l in SLOTS) sum(c in CLASS) teach(t,c,l) <= 1
! Every subject only once per day
forall(t in TEACHERS, c in CLASS, d in 0..ND-1)
sum(l in d*NP+1..(d+1)*NP) teach(t,c,l) <= 1
! Sport Thursday afternoon (slot 15)
teach("Mr Muscle",1,15) = 1
teach("Mrs Biceps",2,15) = 1
! No course during first period of Monday morning
forall(t in TEACHERS, c in CLASS) teach(t,c,1) = 0
! No course by Mr Effofecks Monday morning
forall(l in 1..2) teach("Mr Effofecks",2,l) = 0
! No Biology on Wednesday
forall(c in CLASS, l in 2*NP+1..3*NP) teach("Mrs Insulin",c,l) = 0
forall(t in TEACHERS, c in CLASS, l in SLOTS) teach(t,c,l) is_binary
! Solve the problem
minimize(Hole)
! Solution printing
declarations
DAYS=1..ND
NAMES: array(DAYS) of string
end-declarations
initializations from 'i3school.dat'
NAMES
end-initializations
writeln("Courses at begin or end of day: ", getobjval)
forall(c in CLASS) do
writeln("Class ",c)
forall(d in DAYS) do
write(NAMES(d), ": ")
forall(l in (d-1)*NP+1..d*NP)
if (getsol(sum(t in TEACHERS) teach(t,c,l))>0) then
forall(t in TEACHERS)
write( if(getsol(teach(t,c,l))>0, strfmt(t,-14), ""))
else
write(strfmt("",14))
end-if
writeln
end-do
end-do
end-model
|
|
i4exam.mos |
(!******************************************************
Mosel Example Problems
======================
file i4exam.mos
```````````````
Scheduling exams
(c) 2008 Fair Isaac Corporation
author: S. Heipcke, Mar. 2002
*******************************************************!)
model "I-4 Scheduling exams"
uses "mmxprs"
declarations
EXAM = {"DA","NA","C++","SE","PM","J","GMA","LP","MP","S","DSE"}
! Set of exams
TIME = 1..8 ! Set of time slots
INCOMP: array(EXAM,EXAM) of integer ! Incompatibility between exams
plan: array(EXAM,TIME) of mpvar ! 1 if exam in a time slot, 0 otherwise
end-declarations
initializations from 'i4exam.dat'
INCOMP
end-initializations
! Schedule all exams
forall(e in EXAM) sum(t in TIME) plan(e,t) = 1
! Respect incompatibilities
forall(d,e in EXAM, t in TIME | d<e and INCOMP(d,e)=1)
plan(e,t) + plan(d,t) <= 1
forall(e in EXAM, t in TIME) plan(e,t) is_binary
! Breaking symmetries
(!
plan("DA",1)=1
plan("NA",2)=1
plan("PM",3)=1
plan("GMA",4)=1
plan("S",5)=1
plan("DSE",6)=1
!)
! Solve the problem (no objective)
minimize(0)
! Solution printing
forall(e in EXAM)
writeln(strfmt(e+":",4) ," slot ", getsol(sum(t in TIME) t*plan(e,t)))
end-model
|
|
i5pplan.mos |
(!******************************************************
Mosel Example Problems
======================
file i5pplan.mos
````````````````
Production planning with personnel assignment
(c) 2008 Fair Isaac Corporation
author: S. Heipcke, Mar. 2002
*******************************************************!)
model "I-5 Production planning with personnel"
uses "mmxprs"
forward procedure print_sol
declarations
PRODS = 1..4 ! Set of products
LINES = 1..5 ! Set of production lines
PROFIT: array(PRODS) of integer ! Profit per product
DUR: array(PRODS,LINES) of real ! Duration of production per line
CAP: array(LINES) of integer ! Working hours available per line
Load: array(LINES) of linctr ! Workload constraints
produce: array(PRODS) of mpvar ! Quantity produced
end-declarations
initializations from 'i5pplan.dat'
PROFIT DUR CAP
end-initializations
! Objective: Total profit
Profit:= sum(p in PRODS) PROFIT(p)*produce(p)
! Capacity constraints on lines
forall(l in LINES) Load(l):=sum(p in PRODS) DUR(p,l)*produce(p) <= CAP(l)
! Solve the problem
maximize(Profit)
print_sol
! **** Allow transfer of working hours between lines ****
declarations
TRANSF: dynamic array(LINES,LINES) of integer ! 1 if transfer is allowed,
! 0 otherwise
TMAX: array(LINES) of integer ! Maximum no. of hours to transfer
hours: array(LINES) of mpvar ! Initial working hours per line
transfer: dynamic array(LINES,LINES) of mpvar ! Hours transferred
end-declarations
initializations from 'i5pplan.dat'
TRANSF TMAX
end-initializations
forall(k,l in LINES | exists(TRANSF(k,l))) create(transfer(k,l))
! Re-define capacity constraints on lines
forall(l in LINES) Load(l):=sum(p in PRODS) DUR(p,l)*produce(p) <= hours(l)
! Balance constraints
forall(l in LINES)
hours(l) = CAP(l) + sum(k in LINES) transfer(k,l) -
sum(k in LINES) transfer(l,k)
! Limit on transfer
forall(l in LINES) sum(k in LINES) transfer(l,k) <= TMAX(l)
! Solve the problem
maximize(Profit)
writeln("Solution with transfer of working hours:")
print_sol
forall(l,k in LINES | exists(TRANSF(l,k)))
write(if(getsol(transfer(l,k))>0,
" " + l + "->" + k + ": " + getsol(transfer(l,k)) + "\n", ""))
!-----------------------------------------------------------------
! Solution printing
procedure print_sol
writeln("Total profit: ", getobjval)
forall(p in PRODS)
writeln("Product ", p, ": ", getsol(produce(p)))
forall(l in LINES)
writeln("Line ", l, ": ", getsol(sum(p in PRODS) DUR(p,l)*produce(p)))
end-procedure
end-model
|
|
i6build.mos |
(!******************************************************
Mosel Example Problems
======================
file i6build.mos
````````````````
Personnel planning at a construction site
(c) 2008 Fair Isaac Corporation
author: S. Heipcke, Mar. 2002
*******************************************************!)
model "I-6 Construction site personnel"
uses "mmxprs"
declarations
FIRST = 3; LAST = 8
MONTHS = FIRST..LAST ! Set of time periods (months)
CARR, CLEAVE: integer ! Cost per arrival/departure
COVER, CUNDER: integer ! Cost of over-/understaffing
NSTART, NFINAL: integer ! No. of workers at begin/end of plan
REQ: array(MONTHS) of integer ! Requirement of workers per month
onsite: array(MONTHS) of mpvar ! Workers on site
arrive,leave: array(MONTHS) of mpvar ! Workers arriving/leaving
over,under: array(MONTHS) of mpvar ! Over-/understaffing
end-declarations
initializations from 'i6build.dat'
CARR CLEAVE COVER CUNDER NSTART NFINAL REQ
end-initializations
! Objective: total cost
Cost:= sum(m in MONTHS) (CARR*arrive(m) + CLEAVE*leave(m) +
COVER*over(m) + CUNDER*under(m))
! Satisfy monthly need of workers
forall(m in MONTHS) onsite(m) - over(m) + under(m) = REQ(m)
! Balances
forall(m in MONTHS)
onsite(m) = if(m>FIRST, onsite(m-1) - leave(m-1), NSTART) + arrive(m)
NFINAL = onsite(LAST) - leave(LAST)
! Limits on departures, understaffing, arrivals; integrality constraints
forall(m in MONTHS) do
leave(m) <= 1/3*onsite(m)
under(m) <= 1/4*onsite(m)
arrive(m) <= 3
arrive(m) is_integer; leave(m) is_integer; onsite(m) is_integer
under(m) is_integer; over(m) is_integer
end-do
! Solve the problem
minimize(Cost)
! Solution printing
declarations
NAMES: array(MONTHS) of string ! Names of months
end-declarations
initializations from 'i6build.dat'
NAMES
end-initializations
writeln("Total cost: ", getobjval)
write("Month ")
forall(m in MONTHS) write(NAMES(m)," ")
write("\nOn site ")
forall(m in MONTHS) write(strfmt(getsol(onsite(m)),4))
write("\nArrive ")
forall(m in MONTHS) write(strfmt(getsol(arrive(m)),4))
write("\nLeave ")
forall(m in MONTHS) write(strfmt(getsol(leave(m)),4))
write("\nOverst. ")
forall(m in MONTHS) write(strfmt(getsol(over(m)),4))
write("\nUnderst.")
forall(m in MONTHS) write(strfmt(getsol(under(m)),4))
writeln
end-model
|
|