Source code for cylp.py.pivots.DualDantzigPivot
'''
As a part of ``cylp.python.pivots`` it implements Dantzig's
Simplex dual pivot rule. Although it already exists in CLP,
for testing purposes we implement one in Python.
'''
from __future__ import print_function
import sys
import numpy as np
from operator import itemgetter
from random import shuffle
from math import floor
from .DualPivotPythonBase import DualPivotPythonBase
#from cylp.py.pivots import DantzigPivot
[docs]class DualDantzigPivot(DualPivotPythonBase):
'''
Dantzig's dual pivot rule implementation.
.. _custom-dual-pivot-usage:
**Usage**
>>> from cylp.cy import CyClpSimplex
>>> from cylp.py.pivots.DualDantzigPivot import DualDantzigPivot
>>> from cylp.py.pivots.DualDantzigPivot import getMpsExample
>>> # Get the path to a sample mps file
>>> f = getMpsExample()
>>> s = CyClpSimplex()
>>> s.readMps(f) # Returns 0 if OK
0
>>> pivot = DualDantzigPivot(s)
>>> s.setDualPivotMethod(pivot)
>>> s.dual()
'optimal'
>>> round(s.objectiveValue, 5)
2520.57174
'''
def __init__(self, clpModel):
self.dim = clpModel.nRows + clpModel.nCols
self.clpModel = clpModel
def pivotRow(self):
model = self.clpModel
nConstraints = model.nConstraints
basicVarInds = model.basicVariables
u = model.upper[basicVarInds]
l = model.lower[basicVarInds]
s = model.solution[basicVarInds]
infeasibilities = np.maximum(s - u, l - s)
m = max(infeasibilities)
if m > model.primalTolerance:
return np.argmax(infeasibilities)
return -1
def updateWeights(self, inp, spare, spare2, updatedColumn):
model = self.clpModel
pr = model.pivotRow()
model.updateColumnFT(spare, updatedColumn)
indices = updatedColumn.indices
elements = updatedColumn.elements
if updatedColumn.isInPackedMode:
if pr in indices:
ind = np.where(indices==pr)[0][0]
return elements[ind]
else:
return elements[pr]
return 0
def updatePrimalSolution(self, primalUpdate, primalRatio, objectiveChange):
model = self.clpModel
nConstraints = model.nConstraints
basicVarInds = model.basicVariables
rowNumbers = primalUpdate.indices
elements = primalUpdate.elements
nElements = primalUpdate.nElements
changeObj = 0
sol = model.solution[basicVarInds[rowNumbers]]
cost = model.cost[basicVarInds[rowNumbers]]
if primalUpdate.isInPackedMode:
change = primalRatio * elements[:nElements]
model.solution[basicVarInds[rowNumbers]] -= change
else:
change = primalRatio * elements[rowNumbers]
model.solution[basicVarInds[rowNumbers]] -= change
changeObj = -np.dot(change, cost)
primalUpdate.clear()
objectiveChange[0] += changeObj
return changeObj
def getMpsExample():
import os
import inspect
import sys
cylpDir = os.environ['CYLP_SOURCE_DIR']
return os.path.join(cylpDir, 'cylp', 'input', 'p0033.mps')
if __name__ == "__main__":
print(sys.argv)
if len(sys.argv) == 1:
import doctest
doctest.testmod()
else:
from cylp.cy import CyClpSimplex
from cylp.py.pivots import DualDantzigPivot
s = CyClpSimplex()
s.readMps(sys.argv[1]) # Returns 0 if OK
pivot = DualDantzigPivot(s)
s.setDualPivotMethod(pivot)
s.dual()