From f7dc28152ebe001c56c37d2e6898ac67135f924c Mon Sep 17 00:00:00 2001 From: Stuart Mitchell Date: Thu, 7 Jun 2012 20:32:28 +1200 Subject: [PATCH] added dual information to cbc --- src/pulp/pulp.py | 9 +++++++-- src/pulp/solvers.py | 43 ++++++++++++++++++++++++++++++++++++------- src/pulp/tests.py | 2 +- 3 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/pulp/pulp.py b/src/pulp/pulp.py index 7b2e5c0..9ba9afb 100755 --- a/src/pulp/pulp.py +++ b/src/pulp/pulp.py @@ -1553,9 +1553,14 @@ class LpProblem(object): for name in values: self.constraints[name].pi = values[name] - def assignConsSlack(self, values): + def assignConsSlack(self, values, activity=False): for name in values: - self.constraints[name].slack = float(values[name]) + if activity: + #reports the activitynot the slack + self.constraints[name].slack = -1 * ( + self.constraints[name].constant + float(values[name])) + else: + self.constraints[name].slack = float(values[name]) def get_dummyVar(self): if self.dummyVar is None: diff --git a/src/pulp/solvers.py b/src/pulp/solvers.py index e242afe..519f1ff 100644 --- a/src/pulp/solvers.py +++ b/src/pulp/solvers.py @@ -1274,6 +1274,8 @@ class COIN_CMD(LpSolver_CMD): cmds += "branch " else: cmds += "initialSolve " + if lp.isMIP: + cmds += "printingOptions rows " cmds += "solution "+tmpSol+" " if self.msg: pipe = None @@ -1288,11 +1290,16 @@ class COIN_CMD(LpSolver_CMD): if not os.path.exists(tmpSol): raise PulpSolverError, "Pulp: Error while executing "+self.path if use_mps: - lp.status, values = self.readsol_MPS(tmpSol, lp, lp.variables(), + lp.status, values, reducedCosts, shadowPrices, slacks = self.readsol_MPS( + tmpSol, lp, lp.variables(), variablesNames, constraintsNames, objectiveName) else: - lp.status, values = self.readsol_LP(tmpSol, lp, lp.variables()) + lp.status, values, reducedCosts, shadowPrices, slacks = self.readsol_LP( + tmpSol, lp, lp.variables()) lp.assignVarsVals(values) + lp.assignVarsDj(reducedCosts) + lp.assignConsPi(shadowPrices) + lp.assignConsSlack(slacks, activity=True) if not self.keepFiles: try: os.remove(tmpLp) @@ -1312,12 +1319,19 @@ class COIN_CMD(LpSolver_CMD): values = {} reverseVn = {} - for k,n in variablesNames.iteritems(): + for k, n in variablesNames.iteritems(): reverseVn[n] = k + reverseCn = {} + for k, n in constraintsNames.iteritems(): + reverseCn[n] = k + for v in vs: values[v.name] = 0.0 + reducedCosts = {} + shadowPrices = {} + slacks = {} cbcStatus = {'Optimal': LpStatusOptimal, 'Infeasible': LpStatusInfeasible, 'Unbounded': LpStatusUnbounded, @@ -1330,15 +1344,24 @@ class COIN_CMD(LpSolver_CMD): break l = l.split() vn = l[1] + val = l[2] + dj = l[3] if vn in reverseVn: - values[reverseVn[vn]] = float(l[2]) - return status, values + values[reverseVn[vn]] = float(val) + reducedCosts[reverseVn[vn]] = float(dj) + if vn in reverseCn: + slacks[reverseCn[vn]] = float(val) + shadowPrices[reverseCn[vn]] = float(dj) + return status, values, reducedCosts, shadowPrices, slacks def readsol_LP(self, filename, lp, vs): """ Read a CBC solution file generated from an lp (good names) """ values = {} + reducedCosts = {} + shadowPrices = {} + slacks = {} for v in vs: values[v.name] = 0.0 cbcStatus = {'Optimal': LpStatusOptimal, @@ -1353,9 +1376,15 @@ class COIN_CMD(LpSolver_CMD): break l = l.split() vn = l[1] + val = l[2] + dj = l[3] if vn in values: - values[vn] = float(l[2]) - return status, values + values[vn] = float(val) + reducedCosts[vn] = float(dj) + if vn in lp.constraints: + slacks[vn] = float(val) + shadowPrices[vn] = float(dj) + return status, values, reducedCosts, shadowPrices, slacks COIN = COIN_CMD diff --git a/src/pulp/tests.py b/src/pulp/tests.py index 5a786ad..bb56126 100644 --- a/src/pulp/tests.py +++ b/src/pulp/tests.py @@ -378,7 +378,7 @@ def pulpTest080(solver): prob += c2,"c2" prob += c3,"c3" - if solver.__class__ in [CPLEX_DLL, CPLEX_CMD, COINMP_DLL]: + if solver.__class__ in [CPLEX_DLL, CPLEX_CMD, COINMP_DLL, PULP_CBC_CMD]: print "\t Testing dual variables and slacks reporting" pulpTestCheck(prob, solver, [LpStatusOptimal], sol = {x:4, y:-1, z:6},