#!/usr/bin/python
# Copyright 2013, Gurobi Optimization, Inc.
# A heuristic to find alternate solutions to an LP or MILP model.
# This example reads a model from a file and solves it. If a solution is
# found, it modifies the model to look for alternate solutions that are
# far from the prior solutions. Uses Model.getAttr() to retrieve attributes
# in bulk.
solfn = "alternate"
eps = 1e-4
import sys
from gurobipy import *
if len(sys.argv) < 3:
print('Usage: alternate.py filename numsols')
quit()
try:
# Solve model to determine objective value
numsols = int(sys.argv[2])
model = read(sys.argv[1])
vars = model.getVars()
if model.IsQP == 1 or model.IsQCP == 1:
print('Error: only supports LP and MILP models')
exit(0)
model.optimize()
if model.SolCount < 1:
print('No solution found, stopping')
exit(0)
print('\nInitial solution has objective %f\n' % model.ObjVal)
model.write("%s%i.sol" % (solfn, 0))
# Initialize storage for previous solutions
PrevX = [model.getAttr('X', vars)]
if model.IsMIP == 0:
# For LPs, fix variables with non-zero reduced costs
# and slacks with non-zero duals
cons = model.getConstrs()
RC = model.getAttr('RC', vars)
Pi = model.getAttr('Pi', cons)
for i in range(len(vars)):
if abs(RC[i]) > model.Params.OptimalityTol:
vars[i].LB = PrevX[0][i]
vars[i].UB = PrevX[0][i]
for i in range(len(cons)):
if abs(Pi[i]) > model.Params.OptimalityTol:
cons[i].Sense = '='
else:
# For MIPs, convert objective to a constraint
Obj = model.getAttr('Obj', vars)
objexp = 0
for i in range(len(vars)):
if Obj[i] != 0:
objexp += vars[i]*Obj[i]
model.addConstr(objexp == model.ObjVal, "OrigObj")
# Initialize new objective
model.ModelSense = GRB.MINIMIZE
Obj = list(PrevX[0]) # make a copy
for i in range(len(vars)):
vars[i].Obj = Obj[i]
# Solve iteratively with different objectives
model.Params.SolutionLimit = 1
while len(PrevX) < numsols:
model.optimize()
ThisX = model.getAttr('X', vars)
# Test that the solution is new
for k in range(len(PrevX)):
notNew = True
for i in range(len(vars)):
if abs(ThisX[i]-PrevX[k][i]) > eps:
notNew = False
break
if notNew:
break
if notNew:
if model.IsMIP == 1 and model.Status == GRB.SOLUTION_LIMIT:
print('\nSolution %i is same as solution %i, continuing\n' %
(len(PrevX),k) )
model.Params.SolutionLimit += 1
else:
print('\nSolution %i is same as solution %i, stopping\n' %
(len(PrevX),k) )
break
else:
# Store and write current solution, modify objective and resolve
for i in range(len(vars)):
Obj[i] = 0.8*ThisX[i]+0.2*Obj[i]
vars[i].Obj = Obj[i]
print('\nAlternate solution %i found' % len(PrevX))
model.write("%s%i.sol" % (solfn, len(PrevX)))
PrevX.append(ThisX)
model.Params.SolutionLimit = 1
except GurobiError as e:
print('Gurobi error: %s' % str(e))
Note that the code line
model.addConstr(objexp == model.ObjVal, "OrigObj")
means that you are only looking for alternate solutions that have exactly (up to feasibility tolerance) the same objective value as the optimal solution. My guess is that you want to replace this by something like
model.addConstr(objexp <= model.ObjVal + 1.05 * abs(model.ObjVal), "OrigObj")
which means (provided that you are minimizing) that you are looking for solutions that are at most 5% away from the optimal value.
model.addConstr(objexp <= model.ObjVal + 1.05 * abs(model.ObjVal), "OrigObj")
--
---
You received this message because you are subscribed to a topic in the Google Groups "Gurobi Optimization" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/gurobi/BsJm4thVtfI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to gurobi+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Maximize
10 X_1
Subject To
1 - X_1 > 1
Binary
X_1
End