from ortools.linear_solver.pywraplp import Solver
# cost[c][j] = cost for CPU c to run job j
cost = [[90, 76, 75, 70],
[35, 85, 55, 65],
[125, 95, 90, 105],
[45, 110, 95, 115],
[60, 105, 80, 75],
[45, 65, 110, 95]]
clusters = [
[0, 2, 4],
[1, 3, 5]
]
num_cpus = len(cost)
num_jobs = len(cost[0])
model = Solver('cpu_job', Solver.CBC_MIXED_INTEGER_PROGRAMMING)
# x[c, j] if CPU c gets job j
x = {}
for c in range(num_cpus):
for j in range(num_jobs):
x[c, j] = model.IntVar(0, 1, f'cpu {c} gets job {j}')
# Each cpu gets at most one job
for c in range(num_cpus):
model.Add(
sum(x[c, j] for j in range(num_jobs)) <= 1
)
# Each job gets exactly one CPU
for j in range(num_jobs):
model.Add(
sum(x[c, j] for c in range(num_cpus)) == 1
)
# Each cluster gets at most two jobs
for cluster in clusters:
model.Add(
sum(x[c, j] for c in cluster for j in range(num_jobs)) <= 2
)
total_cost = sum(x[c, j] * cost[c][j] for c in range(num_cpus) for j in range(num_jobs))
model.Minimize(total_cost)
if model.Solve() == Solver.OPTIMAL:
print([v for v in x.values() if v.solution_value() == 1])
print('Min cost:', total_cost.solution_value())