1# cython: embedsignature=True
2
3
4import numpy as np
5cimport numpy as np
6cimport CyDantzigPivot
7#cimport CyClpSimplex
8
9# varStatus defined to mimic 'enum ClpSimplex::Status'.
10# But is too slow obviously
11varStatus = ['isFree', 'basic', 'atUpperBound',
12             'atLowerBound', 'superBasic', 'isFixed']
13
14cdef class CyDantzigPivot(CyClpPrimalColumnPivotBase):
15    def __init__(self, cyModel):
16        self.cyModel = cyModel
17        CyClpPrimalColumnPivotBase.__init__(self)
18
19    cdef pivotColumn(self, CppCoinIndexedVector* cppupdates, CppCoinIndexedVector* cppspareRow1,
20                    CppCoinIndexedVector* cppspareRow2, CppCoinIndexedVector* cppspareCol1,
21                    CppCoinIndexedVector* cppspareCol2):
22        updates = CyCoinIndexedVector()
23        updates.setCppSelf(cppupdates)
24        spareRow1 = CyCoinIndexedVector()
25        spareRow1.setCppSelf(cppspareRow1)
26        spareRow2 = CyCoinIndexedVector()
27        spareRow2.setCppSelf(cppspareRow2)
28        spareCol1 = CyCoinIndexedVector()
29        spareCol1.setCppSelf(cppspareCol1)
30        spareCol2 = CyCoinIndexedVector()
31        spareCol2.setCppSelf(cppspareCol2)
32
33        #self.DantzigDualUpdate(v1, v2, v3, v4, v5)
34        s = self.cyModel
35
36        # Update the reduced costs, for both the original and the slack variables
37        if updates.nElements:
38            s.updateColumnTranspose(spareRow2, updates)
39            s.transposeTimes(-1, updates, spareCol2, spareCol1)
40            s.reducedCosts[s.nVariables:][updates.indices] -= updates.elements[:updates.nElements]
41            s.reducedCosts[:s.nVariables][spareCol1.indices] -= spareCol1.elements[:spareCol1.nElements]
42        updates.clear()
43        spareCol1.clear()
44
45        rc = s.reducedCosts
46
47        cdef double tol = s.dualTolerance
48
49        #incides of vars not fixed and not flagged
50        #indicesToConsider = np.where((status & 7 != 1) & (status & 7 != 5) &
51        #        (status & 64 == 0) & (((rc > tol) & (status & 7 == 2)) |
52        #            ((rc < -tol) & (status & 7 == 3))) )[0]
53
54        cdef np.ndarray indicesToConsider = \
55                                np.where(s.varNotFlagged & s.varNotFixed &
56                                     s.varNotBasic &
57                                     (((rc > tol) & s.varIsAtUpperBound) |
58                                     ((rc < -tol) & s.varIsAtLowerBound) |
59                                     s.varIsFree))[0]
60
61        #freeVarInds = np.where(s.varIsFree)
62        #rc[freeVarInds] *= 10
63
64        cdef np.ndarray rc2 = abs(rc[indicesToConsider])
65
66        cdef int checkFree = 0
67        cdef int ind
68        #rc2[np.where((status & 7 == 4) | (status & 7 == 0))] *= 10
69        if rc2.shape[0] > 0:
70            if checkFree:
71                w = np.where(s.varIsFree)[0]
72                if w.shape[0] > 0:
73                    ind = s.argWeightedMax(rc2, indicesToConsider, 1, w)
74                else:
75                    ind = np.argmax(rc2)
76            else:
77                    ind = np.argmax(rc2)
78            return  indicesToConsider[ind]
79        return -1
80
81    cdef CyClpPrimalColumnPivot* clone(self, bint copyData):
82        cdef CyClpPrimalColumnPivot* ret =  \
83                <CyClpPrimalColumnPivot*> new CppClpPrimalColumnPivotBase(
84                                <cpy_ref.PyObject*>self,
85                                <runPivotColumn_t>RunPivotColumn,
86                                <runClone_t>RunClone,
87                                <runSaveWeights_t>RunSaveWeights)
88        return ret
89
90    cdef void saveWeights(self, CyClpSimplex.CppIClpSimplex * model, int mode):
91        self.CppSelf.setModel(model)
92