fixanddive.py


#!/usr/bin/python

# Copyright 2012, Gurobi Optimization, Inc.

# Implement a simple MIP heuristic.  Relax the model,
# sort variables based on fractionality, and fix the 25% of
# the fractional variables that are closest to integer variables.
# Repeat until either the relaxation is integer feasible or
# linearly infeasible.

import sys
from gurobipy import *


# Comparison function used to sort variable list based on relaxation
# fractionality

def compare(v1, v2):
    sol1 = v1.x
    sol2 = v2.x
    frac1 = abs(sol1-int(sol1+0.5))
    frac2 = abs(sol2-int(sol2+0.5))
    if frac1 <= frac2:
        return -1
    else:
        return +1


if len(sys.argv) < 2:
    print 'Usage: fixanddive.py filename'
    quit()

# Read model

model = gurobi.read(sys.argv[1])

# Collect integer variables and relax them
intvars = []
for v in model.getVars():
    if v.vType != GRB.CONTINUOUS:
        intvars += [v]
        v.vType = GRB.CONTINUOUS

model.params.outputFlag = 0

model.optimize()


# Perform multiple iterations.  In each iteration, identify the first
# quartile of integer variables that are closest to an integer value in the
# relaxation, fix them to the nearest integer, and repeat.

for iter in range(1000):

# create a list of fractional variables, sorted in order of increasing
# distance from the relaxation solution to the nearest integer value

    fractional = []
    for v in intvars:
        sol = v.x
        if abs(sol - int(sol+0.5)) > 1e-5:
            fractional += [v]

    fractional.sort(compare)

    print 'Iteration', iter, ', obj ', model.objVal, ', fractional',
    print len(fractional)

    if len(fractional) == 0:
        print 'Found feasible solution - objective', model.objVal
        break


# Fix the first quartile to the nearest integer value
    nfix = max(len(fractional)/4, 1)
    for i in range(nfix):
        v = fractional[i]
        fixval = int(v.x+0.5)
        v.lb = fixval
        v.ub = fixval
        print '  Fix', v.varName, 'to', fixval, '( rel', v.x, ')'

    model.optimize()

# Check optimization result

    if model.status != GRB.status.OPTIMAL:
        print 'Relaxation is infeasible'
        break