# Assignment Problem
# Written in pymprog by Yingjie Lan <ylan@umd.edu>
# The assignment problem is one of the fundamental combinatorial
# optimization problems.
# In its most general form, the problem is as follows:
# There are a number of agents and a number of tasks. Any agent can be
# assigned to perform any task, incurring some cost that may vary
# depending on the agent-task assignment. It is required to perform all
# tasks by assigning exactly one agent to each task in such a way that
# the total cost of the assignment is minimized.
# (From Wikipedia, the free encyclopedia.)
m = 8 # agents
M = range(m) #set of agents
n = 8 # tasks
N = range(n) #set of tasks
c = [ #cost
(13,21,20,12,8,26,22,11),
(12,36,25,41,40,11,4,8),
(35,32,13,36,26,21,13,37),
(34,54,7,8,12,22,11,40),
(21,6,45,18,24,34,12,48),
(42,19,39,15,14,16,28,46),
(16,34,38,3,34,40,22,24),
(26,20,5,17,45,31,37,43)]
from pymprog import *
p = model("assign")
p.verb = True
A = iprod(M, N)
x = p.var(A, 'x') #assignment decision vars
tc = {}
for i,j in A: tc[i,j] = c[i][j]
tc = p.par(tc, 'c')
p.min(sum(tc[t]*x[t] for t in A), 'totalcost')
p.st([sum(x[k,j] for j in N)<=1 for k in M], 'agent')
p.st([sum(x[i,k] for i in M)==1 for k in N], 'task')
p.solve()
print("Total Cost = %g"%p.vobj())
assign = [(i,j) for i in M for j in N
if x[i,j].primal>0.5]
for i,j in assign:
print "Agent %d gets Task %d with Cost %g"%(i, j, c[i][j])
t = assign[0]
tc[t].value = tc[t].value + 10
print "set cost c%s to higher value %s"%(str(t),str(tc[t].value))
p.solve() #this takes care of model update
print("Total Cost = %g"%p.vobj())
assign = [(i,j) for i in M for j in N
if x[i,j].primal>0.5]
for i,j in assign:
print "Agent %d gets Task %d with Cost %g"%(i, j, c[i][j])