1''' 2This module interface COIN-OR's ``CoinMpsIO``. When you call 3:func:`cylp.cy.CyClpSimplex.readMps` then ``CoinMpsIO``'s ``readMps`` is 4called. The main reason why cylp interfaces this class is to be able to read 5an ``mps`` file without creating a Simplex object. This way it is possible to 6read a QP using CoinMpsIO and work on the elements of the problem, e.g. the 7Hessian,... 8''' 9# cython: embedsignature=True 10 11import numpy as np 12from scipy import sparse 13from scipy.sparse import identity, dia_matrix 14from cylp.py.utils.sparseUtil import csc_matrixPlus, csr_matrixPlus 15 16cdef class CyCoinMpsIO: 17 def __cinit__(self): 18 self.CppSelf = new CppICoinMpsIO() 19 self.Hessian = 0 20 21 def readMps(self, filename): 22 ''' 23 Read an mps file. Check if the file is a QP symmetrisize its Hessian 24 and store it. 25 26 >>> import numpy as np 27 >>> from cylp.cy import CyCoinMpsIO 28 >>> from cylp.cy.CyCoinMpsIO import getQpsExample 29 >>> problem = CyCoinMpsIO() 30 >>> problem.readMps(getQpsExample()) 31 0 32 >>> problem.nVariables 33 5 34 >>> problem.nConstraints 35 5 36 >>> signs = problem.constraintSigns 37 >>> [chr(i) for i in signs] == problem.nConstraints * ['G'] 38 True 39 >>> c = problem.matrixByRow 40 >>> (abs(c.elements - 41 ... np.array([-1., -1., -1., -1., -1., 10., 10., -3., 42 ... 5., 4., -8., 1., -2., -5., 3., 8., -1., 2., 43 ... 5., -3., -4., -2., 3., -5., 1.])) < 44 ... 10 ** -8).all() 45 True 46 >>> (c.indices == 47 ... np.array([0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 48 ... 2, 3, 4, 0, 1, 2, 3, 4], dtype=np.int32)).all() 49 True 50 >>> (c.vectorStarts == 51 ... np.array([0, 5, 10, 15, 20, 25], dtype=np.int32)).all() 52 True 53 >>> (problem.rightHandSide == 54 ... np.array([-5., 20., -40., 11., -30.])).all() 55 True 56 >>> H = problem.Hessian.todense() 57 >>> (abs(H - 58 ... np.matrix([[20394., -24908., -2026., 3896., 658.], 59 ... [-24908., 41818., -3466., -9828., -372.], 60 ... [-2026., -3466., 3510., 2178., -348.], 61 ... [3896., -9828., 2178., 3030., -44.], 62 ... [658., -372., -348., -44., 54.]])) < 63 ... 10 ** -8).all() 64 True 65 66 ''' 67 if isinstance(filename, str): 68 # Cast strings/unicode to bytes 69 filename = filename.encode('utf-8') 70 71 ret = self.CppSelf.readMps(filename) 72 if ret == 0 and self.CppSelf.IreadQuadraticMps(NULL, 0) == 0: 73 start = self.QPColumnStarts 74 col = self.QPColumns 75 el = self.QPElements 76 77 n = self.nVariables 78 m = self.nConstraints 79 80 Hessian = csr_matrixPlus((el, col, start), shape=(n, n)) 81 # Fill the other half of the symmetric Hessian 82 Hessian = Hessian + Hessian.T - dia_matrix((Hessian.diagonal(),[0]), shape=(n, n)) 83 self.Hessian = Hessian 84 85 return ret 86 87 def readQuadraticMps(self, filename, checkSymmetry): 88 return self.CppSelf.IreadQuadraticMps(NULL, checkSymmetry) 89 90 property Hessian: 91 def __get__(self): 92 return self.Hessian 93 94 def __set__(self, h): 95 self.Hessian = h 96 97 property variableLower: 98 def __get__(self): 99 return <object>self.CppSelf.np_getColLower() 100 101 property variableUpper: 102 def __get__(self): 103 return <object>self.CppSelf.np_getColUpper() 104 105 property constraintSigns: 106 def __get__(self): 107 return <object>self.CppSelf.np_getRowSense() 108 109 property rightHandSide: 110 def __get__(self): 111 return <object>self.CppSelf.np_getRightHandSide() 112 113 property constraintRange: 114 def __get__(self): 115 return <object>self.CppSelf.np_getRowRange() 116 117 property constraintLower: 118 def __get__(self): 119 return <object>self.CppSelf.np_getRowLower() 120 121 property constraintUpper: 122 def __get__(self): 123 return <object>self.CppSelf.np_getRowUpper() 124 125 property objCoefficients: 126 def __get__(self): 127 return <object>self.CppSelf.np_getObjCoefficients() 128 129 property integerColumns: 130 def __get__(self): 131 return <object>self.CppSelf.np_integerColumns() 132 133 property QPColumnStarts: 134 def __get__(self): 135 return <object>self.CppSelf.getQPColumnStarts() 136 137 property QPColumns: 138 def __get__(self): 139 return <object>self.CppSelf.getQPColumns() 140 141 property QPElements: 142 def __get__(self): 143 return <object>self.CppSelf.getQPElements() 144 145 property matrixByRow: 146 def __get__(self): 147 cdef CppCoinPackedMatrix* m = self.CppSelf.IgetMatrixByRow() 148 cym = CyCoinPackedMatrix() 149 cym.CppSelf = m 150 return cym 151 152 property matrixByCol: 153 def __get__(self): 154 cdef CppCoinPackedMatrix* m = self.CppSelf.IgetMatrixByCol() 155 cym = CyCoinPackedMatrix() 156 cym.CppSelf = m 157 return cym 158 159 property objectiveOffset: 160 def __get__(self): 161 return self.CppSelf.getObjectiveOffset() 162 163 property nVariables: 164 def __get__(self): 165 return self.CppSelf.getNumCols() 166 167 property nConstraints: 168 def __get__(self): 169 return self.CppSelf.getNumRows() 170 171 172def getQpsExample(): 173 ''' 174 Return full path to a QPS example file for doctests 175 ''' 176 import os 177 import inspect 178 curpath = os.path.dirname(inspect.getfile(inspect.currentframe())) 179 return os.path.join(curpath, '../input/hs268.qps') 180 181 182# cdef int CLP_readQuadraticMps(self, char* filename, 183# int * columnStart, int * column2, double * elements, 184# int checkSymmetry): 185# return self.CppSelf.readQuadraticMps(filename, columnStart, 186# column2, elements, checkSymmetry) 187 188# def readQuadraticMps(self, 189# filename, 190# np.ndarray[np.int32_t,ndim=1] columnStart, 191# np.ndarray[np.int32_t,ndim=1] column2, 192# np.ndarray[np.double_t,ndim=1] elements, 193# checkSymmetry): 194# return self.CLP_readQuadraticMps(filename, 195# <int*>columnStart.data, 196# <int*>column2.data, 197# <double*>elements.data, 198# checkSymmetry) 199