<ahref="markowitz_8h.html">Go to the documentation of this file.</a><divclass="fragment"><divclass="line"><aname="l00001"></a><spanclass="lineno"> 1</span> <spanclass="comment">// Copyright 2010-2021 Google LLC</span></div>
<divclass="line"><aname="l00002"></a><spanclass="lineno"> 2</span> <spanclass="comment">// Licensed under the Apache License, Version 2.0 (the "License");</span></div>
<divclass="line"><aname="l00003"></a><spanclass="lineno"> 3</span> <spanclass="comment">// you may not use this file except in compliance with the License.</span></div>
<divclass="line"><aname="l00004"></a><spanclass="lineno"> 4</span> <spanclass="comment">// You may obtain a copy of the License at</span></div>
<divclass="line"><aname="l00008"></a><spanclass="lineno"> 8</span> <spanclass="comment">// Unless required by applicable law or agreed to in writing, software</span></div>
<divclass="line"><aname="l00009"></a><spanclass="lineno"> 9</span> <spanclass="comment">// distributed under the License is distributed on an "AS IS" BASIS,</span></div>
<divclass="line"><aname="l00010"></a><spanclass="lineno"> 10</span> <spanclass="comment">// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span></div>
<divclass="line"><aname="l00011"></a><spanclass="lineno"> 11</span> <spanclass="comment">// See the License for the specific language governing permissions and</span></div>
<divclass="line"><aname="l00012"></a><spanclass="lineno"> 12</span> <spanclass="comment">// limitations under the License.</span></div>
<divclass="line"><aname="l00014"></a><spanclass="lineno"> 14</span> <spanclass="comment">// LU decomposition algorithm of a sparse matrix B with Markowitz pivot</span></div>
<divclass="line"><aname="l00015"></a><spanclass="lineno"> 15</span> <spanclass="comment">// selection strategy. The algorithm constructs a lower matrix L, upper matrix</span></div>
<divclass="line"><aname="l00016"></a><spanclass="lineno"> 16</span> <spanclass="comment">// U, row permutation P and a column permutation Q such that L.U = P.B.Q^{-1}.</span></div>
<divclass="line"><aname="l00018"></a><spanclass="lineno"> 18</span> <spanclass="comment">// The current algorithm is a mix of ideas that can be found in the literature</span></div>
<divclass="line"><aname="l00019"></a><spanclass="lineno"> 19</span> <spanclass="comment">// and of some optimizations tailored for its use in a revised simplex algorithm</span></div>
<divclass="line"><aname="l00020"></a><spanclass="lineno"> 20</span> <spanclass="comment">// (like a fast processing of the singleton columns present in B). It constructs</span></div>
<divclass="line"><aname="l00021"></a><spanclass="lineno"> 21</span> <spanclass="comment">// L and U column by column from left to right.</span></div>
<divclass="line"><aname="l00023"></a><spanclass="lineno"> 23</span> <spanclass="comment">// A key concept is the one of the residual matrix which is the bottom right</span></div>
<divclass="line"><aname="l00024"></a><spanclass="lineno"> 24</span> <spanclass="comment">// square submatrix that still needs to be factorized during the classical</span></div>
<divclass="line"><aname="l00025"></a><spanclass="lineno"> 25</span> <spanclass="comment">// Gaussian elimination. The algorithm maintains the non-zero pattern of its</span></div>
<divclass="line"><aname="l00026"></a><spanclass="lineno"> 26</span> <spanclass="comment">// rows and its row/column degrees.</span></div>
<divclass="line"><aname="l00028"></a><spanclass="lineno"> 28</span> <spanclass="comment">// At each step, a number of columns equal to 'markowitz_zlatev_parameter' are</span></div>
<divclass="line"><aname="l00029"></a><spanclass="lineno"> 29</span> <spanclass="comment">// chosen as candidates from the residual matrix. They are the ones with minimal</span></div>
<divclass="line"><aname="l00030"></a><spanclass="lineno"> 30</span> <spanclass="comment">// residual column degree. They can be found easily because the columns of the</span></div>
<divclass="line"><aname="l00031"></a><spanclass="lineno"> 31</span> <spanclass="comment">// residual matrix are kept in a priority queue.</span></div>
<divclass="line"><aname="l00033"></a><spanclass="lineno"> 33</span> <spanclass="comment">// We compute the numerical value of these residual columns like in a</span></div>
<divclass="line"><aname="l00034"></a><spanclass="lineno"> 34</span> <spanclass="comment">// left-looking algorithm by solving a sparse lower-triangular system with the</span></div>
<divclass="line"><aname="l00035"></a><spanclass="lineno"> 35</span> <spanclass="comment">// current L constructed so far. Note that this step is highly optimized for</span></div>
<divclass="line"><aname="l00036"></a><spanclass="lineno"> 36</span> <spanclass="comment">// sparsity and we reuse the computations done in the previous steps (if the</span></div>
<divclass="line"><aname="l00037"></a><spanclass="lineno"> 37</span> <spanclass="comment">// candidate column was already considered before). As a by-product, we also</span></div>
<divclass="line"><aname="l00038"></a><spanclass="lineno"> 38</span> <spanclass="comment">// get the corresponding column of U.</span></div>
<divclass="line"><aname="l00040"></a><spanclass="lineno"> 40</span> <spanclass="comment">// Among the entries of these columns, a pivot is chosen such that the product:</span></div>
<divclass="line"><aname="l00042"></a><spanclass="lineno"> 42</span> <spanclass="comment">// is minimized. Only the pivots with a magnitude greater than</span></div>
<divclass="line"><aname="l00043"></a><spanclass="lineno"> 43</span> <spanclass="comment">// 'lu_factorization_pivot_threshold' times the maximum magnitude of the</span></div>
<divclass="line"><aname="l00044"></a><spanclass="lineno"> 44</span> <spanclass="comment">// corresponding residual column are considered for stability reasons.</span></div>
<divclass="line"><aname="l00046"></a><spanclass="lineno"> 46</span> <spanclass="comment">// Once the pivot is chosen, the residual column divided by the pivot becomes a</span></div>
<divclass="line"><aname="l00047"></a><spanclass="lineno"> 47</span> <spanclass="comment">// column of L, and the non-zero pattern of the new residual submatrix is</span></div>
<divclass="line"><aname="l00048"></a><spanclass="lineno"> 48</span> <spanclass="comment">// updated by subtracting the outer product of this pivot column times the pivot</span></div>
<divclass="line"><aname="l00049"></a><spanclass="lineno"> 49</span> <spanclass="comment">// row. The product minimized above is thus an upper bound of the number of</span></div>
<divclass="line"><aname="l00050"></a><spanclass="lineno"> 50</span> <spanclass="comment">// fill-in created during a step.</span></div>
<divclass="line"><aname="l00054"></a><spanclass="lineno"> 54</span> <spanclass="comment">// J. R. Gilbert and T. Peierls, "Sparse partial pivoting in time proportional</span></div>
<divclass="line"><aname="l00055"></a><spanclass="lineno"> 55</span> <spanclass="comment">// to arithmetic operations," SIAM J. Sci. Statist. Comput., 9 (1988): 862-874.</span></div>
<divclass="line"><aname="l00064"></a><spanclass="lineno"> 64</span> <spanclass="comment">// TODO(user): Determine whether any of these would bring any benefit:</span></div>
<divclass="line"><aname="l00065"></a><spanclass="lineno"> 65</span> <spanclass="comment">// - S.C. Eisenstat and J.W.H. Liu, "The theory of elimination trees for</span></div>
<divclass="line"><aname="l00093"></a><spanclass="lineno"> 93</span> <spanclass="comment">// Holds the non-zero positions (by row) and column/row degree of the residual</span></div>
<divclass="line"><aname="l00094"></a><spanclass="lineno"> 94</span> <spanclass="comment">// matrix during the Gaussian elimination.</span></div>
<divclass="line"><aname="l00096"></a><spanclass="lineno"> 96</span> <spanclass="comment">// During each step of Gaussian elimination, a row and a column will be</span></div>
<divclass="line"><aname="l00097"></a><spanclass="lineno"> 97</span> <spanclass="comment">// "removed" from the residual matrix. Note however that the row and column</span></div>
<divclass="line"><aname="l00098"></a><spanclass="lineno"> 98</span> <spanclass="comment">// indices of the non-removed part do not change, so the residual matrix at a</span></div>
<divclass="line"><aname="l00099"></a><spanclass="lineno"> 99</span> <spanclass="comment">// given step will only correspond to a subset of the initial indices.</span></div>
<divclass="line"><aname="l00107"></a><spanclass="lineno"> 107</span> <spanclass="comment">// Resets the pattern to the one of an empty square matrix of the given size.</span></div>
<divclass="line"><aname="l00110"></a><spanclass="lineno"> 110</span> <spanclass="comment">// Resets the pattern to the one of the given matrix but only for the</span></div>
<divclass="line"><aname="l00111"></a><spanclass="lineno"> 111</span> <spanclass="comment">// rows/columns whose given permutation is kInvalidRow or kInvalidCol.</span></div>
<divclass="line"><aname="l00112"></a><spanclass="lineno"> 112</span> <spanclass="comment">// This also fills the singleton columns/rows with the corresponding entries.</span></div>
<divclass="line"><aname="l00119"></a><spanclass="lineno"> 119</span> <spanclass="comment">// Adds a non-zero entry to the matrix. There should be no duplicates.</span></div>
<divclass="line"><aname="l00122"></a><spanclass="lineno"> 122</span> <spanclass="comment">// Marks the given pivot row and column as deleted.</span></div>
<divclass="line"><aname="l00123"></a><spanclass="lineno"> 123</span> <spanclass="comment">// This is called at each step of the Gaussian elimination on the pivot.</span></div>
<divclass="line"><aname="l00126"></a><spanclass="lineno"> 126</span> <spanclass="comment">// Decreases the degree of a row/column. This is the basic operation used to</span></div>
<divclass="line"><aname="l00127"></a><spanclass="lineno"> 127</span> <spanclass="comment">// keep the correct degree after a call to DeleteRowAndColumn(). This is</span></div>
<divclass="line"><aname="l00128"></a><spanclass="lineno"> 128</span> <spanclass="comment">// because row_non_zero_[row] is only lazily cleaned.</span></div>
<divclass="line"><aname="l00132"></a><spanclass="lineno"> 132</span> <spanclass="comment">// Returns true if the column has been deleted by DeleteRowAndColumn().</span></div>
<divclass="line"><aname="l00135"></a><spanclass="lineno"> 135</span> <spanclass="comment">// Removes from the corresponding row_non_zero_[row] the columns that have</span></div>
<divclass="line"><aname="l00136"></a><spanclass="lineno"> 136</span> <spanclass="comment">// been previously deleted by DeleteRowAndColumn().</span></div>
<divclass="line"><aname="l00139"></a><spanclass="lineno"> 139</span> <spanclass="comment">// Returns the first non-deleted column index from this row or kInvalidCol if</span></div>
<divclass="line"><aname="l00140"></a><spanclass="lineno"> 140</span> <spanclass="comment">// none can be found.</span></div>
<divclass="line"><aname="l00143"></a><spanclass="lineno"> 143</span> <spanclass="comment">// Performs a generic Gaussian update of the residual matrix:</span></div>
<divclass="line"><aname="l00144"></a><spanclass="lineno"> 144</span> <spanclass="comment">// - DeleteRowAndColumn() must already have been called.</span></div>
<divclass="line"><aname="l00145"></a><spanclass="lineno"> 145</span> <spanclass="comment">// - The non-zero pattern is augmented (set union) by the one of the</span></div>
<divclass="line"><aname="l00146"></a><spanclass="lineno"> 146</span> <spanclass="comment">// outer product of the pivot column and row.</span></div>
<divclass="line"><aname="l00148"></a><spanclass="lineno"> 148</span> <spanclass="comment">// Important: as a small optimization, this function does not call</span></div>
<divclass="line"><aname="l00149"></a><spanclass="lineno"> 149</span> <spanclass="comment">// DecreaseRowDegree() on the row in the pivot column. This has to be done by</span></div>
<divclass="line"><aname="l00150"></a><spanclass="lineno"> 150</span> <spanclass="comment">// the client.</span></div>
<divclass="line"><aname="l00154"></a><spanclass="lineno"> 154</span> <spanclass="comment">// Returns the degree (i.e. the number of non-zeros) of the given column.</span></div>
<divclass="line"><aname="l00155"></a><spanclass="lineno"> 155</span> <spanclass="comment">// This is only valid for the column indices still in the residual matrix.</span></div>
<divclass="line"><aname="l00161"></a><spanclass="lineno"> 161</span> <spanclass="comment">// Returns the degree (i.e. the number of non-zeros) of the given row.</span></div>
<divclass="line"><aname="l00162"></a><spanclass="lineno"> 162</span> <spanclass="comment">// This is only valid for the row indices still in the residual matrix.</span></div>
<divclass="line"><aname="l00165"></a><spanclass="lineno"> 165</span> <spanclass="comment">// Returns the set of non-zeros of the given row (unsorted).</span></div>
<divclass="line"><aname="l00166"></a><spanclass="lineno"> 166</span> <spanclass="comment">// Call RemoveDeletedColumnsFromRow(row) to clean the row first.</span></div>
<divclass="line"><aname="l00167"></a><spanclass="lineno"> 167</span> <spanclass="comment">// This is only valid for the row indices still in the residual matrix.</span></div>
<divclass="line"><aname="l00173"></a><spanclass="lineno"> 173</span> <spanclass="comment">// Augments the non-zero pattern of the given row by taking its union with the</span></div>
<divclass="line"><aname="l00174"></a><spanclass="lineno"> 174</span> <spanclass="comment">// non-zero pattern of the given pivot_row.</span></div>
<divclass="line"><aname="l00177"></a><spanclass="lineno"> 177</span> <spanclass="comment">// Different version of MergeInto() that works only if the non-zeros position</span></div>
<divclass="line"><aname="l00178"></a><spanclass="lineno"> 178</span> <spanclass="comment">// of each row are sorted in increasing order. The output will also be sorted.</span></div>
<divclass="line"><aname="l00180"></a><spanclass="lineno"> 180</span> <spanclass="comment">// TODO(user): This is currently not used but about the same speed as the</span></div>
<divclass="line"><aname="l00184"></a><spanclass="lineno"> 184</span> <spanclass="comment">// Using InlinedVector helps because we usually have many rows with just a few</span></div>
<divclass="line"><aname="l00185"></a><spanclass="lineno"> 185</span> <spanclass="comment">// non-zeros. Note that on a 64 bits computer we get exactly 6 inlined int32_t</span></div>
<divclass="line"><aname="l00186"></a><spanclass="lineno"> 186</span> <spanclass="comment">// elements without extra space, and the size of the inlined vector is 4 times</span></div>
<divclass="line"><aname="l00189"></a><spanclass="lineno"> 189</span> <spanclass="comment">// TODO(user): We could be even more efficient since a size of int32_t is</span></div>
<divclass="line"><aname="l00190"></a><spanclass="lineno"> 190</span> <spanclass="comment">// enough for us and we could store in common the inlined/not-inlined size.</span></div>
<divclass="line"><aname="l00202"></a><spanclass="lineno"> 202</span> <spanclass="comment">// Adjustable priority queue of columns. Pop() returns a column with the</span></div>
<divclass="line"><aname="l00203"></a><spanclass="lineno"> 203</span> <spanclass="comment">// smallest degree first (degree = number of entries in the column).</span></div>
<divclass="line"><aname="l00204"></a><spanclass="lineno"> 204</span> <spanclass="comment">// Empty columns (i.e. with degree 0) are not stored in the queue.</span></div>
<divclass="line"><aname="l00212"></a><spanclass="lineno"> 212</span> <spanclass="comment">// Clears the queue and prepares it to store up to num_cols column indices</span></div>
<divclass="line"><aname="l00213"></a><spanclass="lineno"> 213</span> <spanclass="comment">// with a degree from 1 to max_degree included.</span></div>
<divclass="line"><aname="l00216"></a><spanclass="lineno"> 216</span> <spanclass="comment">// Changes the degree of a column and make sure it is in the queue. The degree</span></div>
<divclass="line"><aname="l00217"></a><spanclass="lineno"> 217</span> <spanclass="comment">// must be non-negative (>= 0) and at most equal to the value of num_cols used</span></div>
<divclass="line"><aname="l00218"></a><spanclass="lineno"> 218</span> <spanclass="comment">// in Reset(). A degree of zero will remove the column from the queue.</span></div>
<divclass="line"><aname="l00221"></a><spanclass="lineno"> 221</span> <spanclass="comment">// Removes the column index with higher priority from the queue and returns</span></div>
<divclass="line"><aname="l00222"></a><spanclass="lineno"> 222</span> <spanclass="comment">// it. Returns kInvalidCol if the queue is empty.</span></div>
<divclass="line"><aname="l00233"></a><spanclass="lineno"> 233</span> <spanclass="comment">// Contains a set of columns indexed by ColIndex. This is like a SparseMatrix</span></div>
<divclass="line"><aname="l00234"></a><spanclass="lineno"> 234</span> <spanclass="comment">// but this class is optimized for the case where only a small subset of columns</span></div>
<divclass="line"><aname="l00235"></a><spanclass="lineno"> 235</span> <spanclass="comment">// is needed at the same time (like it is the case in our LU algorithm). It</span></div>
<divclass="line"><aname="l00236"></a><spanclass="lineno"> 236</span> <spanclass="comment">// reuses the memory of the columns that are no longer needed.</span></div>
<divclass="line"><aname="l00241"></a><spanclass="lineno"> 241</span> <spanclass="comment">// Resets the repository to num_cols empty columns.</span></div>
<divclass="line"><aname="l00247"></a><spanclass="lineno"> 247</span> <spanclass="comment">// Gets the mutable column with given column index. The returned vector</span></div>
<divclass="line"><aname="l00248"></a><spanclass="lineno"> 248</span> <spanclass="comment">// address is only valid until the next call to mutable_column().</span></div>
<divclass="line"><aname="l00251"></a><spanclass="lineno"> 251</span> <spanclass="comment">// Clears the column with given index and releases its memory to the common</span></div>
<divclass="line"><aname="l00252"></a><spanclass="lineno"> 252</span> <spanclass="comment">// memory pool that is used to create new mutable_column() on demand.</span></div>
<divclass="line"><aname="l00255"></a><spanclass="lineno"> 255</span> <spanclass="comment">// Reverts this class to its initial state. This releases the memory of the</span></div>
<divclass="line"><aname="l00256"></a><spanclass="lineno"> 256</span> <spanclass="comment">// columns that were used but not the memory of this class member (this should</span></div>
<divclass="line"><aname="l00257"></a><spanclass="lineno"> 257</span> <spanclass="comment">// be fine).</span></div>
<divclass="line"><aname="l00261"></a><spanclass="lineno"> 261</span> <spanclass="comment">// mutable_column(col) is stored in columns_[mapping_[col]].</span></div>
<divclass="line"><aname="l00262"></a><spanclass="lineno"> 262</span> <spanclass="comment">// The columns_ that can be reused have their index stored in free_columns_.</span></div>
<divclass="line"><aname="l00270"></a><spanclass="lineno"> 270</span> <spanclass="comment">// The class that computes either the actual L.U decomposition, or the</span></div>
<divclass="line"><aname="l00271"></a><spanclass="lineno"> 271</span> <spanclass="comment">// permutation P and Q such that P.B.Q^{-1} will have a sparse L.U</span></div>
<divclass="line"><aname="l00277"></a><spanclass="lineno"> 277</span> <spanclass="comment">// Computes the full factorization with P, Q, L and U.</span></div>
<divclass="line"><aname="l00279"></a><spanclass="lineno"> 279</span> <spanclass="comment">// If the matrix is singular, the returned status will indicate it and the</span></div>
<divclass="line"><aname="l00280"></a><spanclass="lineno"> 280</span> <spanclass="comment">// permutation (col_perm) will contain a maximum non-singular set of columns</span></div>
<divclass="line"><aname="l00281"></a><spanclass="lineno"> 281</span> <spanclass="comment">// of the matrix. Moreover, by adding singleton columns with a one at the rows</span></div>
<divclass="line"><aname="l00282"></a><spanclass="lineno"> 282</span> <spanclass="comment">// such that 'row_perm[row] == kInvalidRow', then the matrix will be</span></div>
<divclass="line"><aname="l00289"></a><spanclass="lineno"> 289</span> <spanclass="comment">// Only computes P and Q^{-1}, L and U can be computed later from these</span></div>
<divclass="line"><aname="l00290"></a><spanclass="lineno"> 290</span> <spanclass="comment">// permutations using another algorithm (for instance left-looking L.U). This</span></div>
<divclass="line"><aname="l00291"></a><spanclass="lineno"> 291</span> <spanclass="comment">// may be faster than computing the full L and U at the same time but the</span></div>
<divclass="line"><aname="l00292"></a><spanclass="lineno"> 292</span> <spanclass="comment">// current implementation is not optimized for this.</span></div>
<divclass="line"><aname="l00294"></a><spanclass="lineno"> 294</span> <spanclass="comment">// It behaves the same as ComputeLU() for singular matrices.</span></div>
<divclass="line"><aname="l00296"></a><spanclass="lineno"> 296</span> <spanclass="comment">// This function also works with a non-square matrix. It will return a set of</span></div>
<divclass="line"><aname="l00297"></a><spanclass="lineno"> 297</span> <spanclass="comment">// independent columns of maximum size. If all the given columns are</span></div>
<divclass="line"><aname="l00298"></a><spanclass="lineno"> 298</span> <spanclass="comment">// independent, the returned Status will be OK.</span></div>
<divclass="line"><aname="l00306"></a><spanclass="lineno"> 306</span> <spanclass="comment">// Returns an estimate of the time spent in the last factorization.</span></div>
<divclass="line"><aname="l00309"></a><spanclass="lineno"> 309</span> <spanclass="comment">// Returns a string containing the statistics for this class.</span></div>
<divclass="line"><aname="l00334"></a><spanclass="lineno"> 334</span> <spanclass="comment">// Fast track for singleton columns of the matrix. Fills a part of the row and</span></div>
<divclass="line"><aname="l00335"></a><spanclass="lineno"> 335</span> <spanclass="comment">// column permutation that move these columns in order to form an identity</span></div>
<divclass="line"><aname="l00336"></a><spanclass="lineno"> 336</span> <spanclass="comment">// sub-matrix on the upper left.</span></div>
<divclass="line"><aname="l00338"></a><spanclass="lineno"> 338</span> <spanclass="comment">// Note(user): Linear programming bases usually have a resonable percentage of</span></div>
<divclass="line"><aname="l00339"></a><spanclass="lineno"> 339</span> <spanclass="comment">// slack columns in them, so this gives a big speedup.</span></div>
<divclass="line"><aname="l00344"></a><spanclass="lineno"> 344</span> <spanclass="comment">// Fast track for columns that form a triangular matrix. This does not find</span></div>
<divclass="line"><aname="l00345"></a><spanclass="lineno"> 345</span> <spanclass="comment">// all of them, but because the column are ordered in the same way they were</span></div>
<divclass="line"><aname="l00346"></a><spanclass="lineno"> 346</span> <spanclass="comment">// ordered at the end of the previous factorization, this is likely to find</span></div>
<divclass="line"><aname="l00347"></a><spanclass="lineno"> 347</span> <spanclass="comment">// quite a few.</span></div>
<divclass="line"><aname="l00349"></a><spanclass="lineno"> 349</span> <spanclass="comment">// The main gain here is that it avoids taking these columns into account in</span></div>
<divclass="line"><aname="l00350"></a><spanclass="lineno"> 350</span> <spanclass="comment">// InitializeResidualMatrix() and later in RemoveRowFromResidualMatrix().</span></div>
<divclass="line"><aname="l00355"></a><spanclass="lineno"> 355</span> <spanclass="comment">// Helper function for determining if a column is a residual singleton column.</span></div>
<divclass="line"><aname="l00356"></a><spanclass="lineno"> 356</span> <spanclass="comment">// If it is, RowIndex* row contains the index of the single residual edge.</span></div>
<divclass="line"><aname="l00360"></a><spanclass="lineno"> 360</span> <spanclass="comment">// Returns the column of the current residual matrix with an index 'col' in</span></div>
<divclass="line"><aname="l00361"></a><spanclass="lineno"> 361</span> <spanclass="comment">// the initial matrix. We compute it by solving a linear system with the</span></div>
<divclass="line"><aname="l00362"></a><spanclass="lineno"> 362</span> <spanclass="comment">// current lower_ and the last computed column 'col' of a previous residual</span></div>
<divclass="line"><aname="l00363"></a><spanclass="lineno"> 363</span> <spanclass="comment">// matrix. This uses the same algorithm as a left-looking factorization (see</span></div>
<divclass="line"><aname="l00364"></a><spanclass="lineno"> 364</span> <spanclass="comment">// lu_factorization.h for more details).</span></div>
<divclass="line"><aname="l00368"></a><spanclass="lineno"> 368</span> <spanclass="comment">// Finds an entry in the residual matrix with a low Markowitz score and a high</span></div>
<divclass="line"><aname="l00369"></a><spanclass="lineno"> 369</span> <spanclass="comment">// enough magnitude. Returns its Markowitz score and updates the given</span></div>
<divclass="line"><aname="l00372"></a><spanclass="lineno"> 372</span> <spanclass="comment">// We use the strategy of Zlatev, "On some pivotal strategies in Gaussian</span></div>
<divclass="line"><aname="l00373"></a><spanclass="lineno"> 373</span> <spanclass="comment">// elimination by sparse technique" (1980). SIAM J. Numer. Anal. 17 18-30. It</span></div>
<divclass="line"><aname="l00374"></a><spanclass="lineno"> 374</span> <spanclass="comment">// consists of looking for the best pivot in only a few columns (usually 3</span></div>
<divclass="line"><aname="l00375"></a><spanclass="lineno"> 375</span> <spanclass="comment">// or 4) amongst the ones which have the lowest number of entries.</span></div>
<divclass="line"><aname="l00377"></a><spanclass="lineno"> 377</span> <spanclass="comment">// Amongst the pivots with a minimum Markowitz number, we choose the one</span></div>
<divclass="line"><aname="l00378"></a><spanclass="lineno"> 378</span> <spanclass="comment">// with highest magnitude. This doesn't apply to pivots with a 0 Markowitz</span></div>
<divclass="line"><aname="l00379"></a><spanclass="lineno"> 379</span> <spanclass="comment">// number because all such pivots will have to be taken at some point anyway.</span></div>
<divclass="line"><aname="l00384"></a><spanclass="lineno"> 384</span> <spanclass="comment">// Updates the degree of a given column in the internal structure of the</span></div>
<divclass="line"><aname="l00388"></a><spanclass="lineno"> 388</span> <spanclass="comment">// Removes all the coefficients in the residual matrix that are on the given</span></div>
<divclass="line"><aname="l00389"></a><spanclass="lineno"> 389</span> <spanclass="comment">// row or column. In both cases, the pivot row or column is ignored.</span></div>
<divclass="line"><aname="l00393"></a><spanclass="lineno"> 393</span> <spanclass="comment">// Updates the residual matrix given the pivot position. This is needed if the</span></div>
<divclass="line"><aname="l00394"></a><spanclass="lineno"> 394</span> <spanclass="comment">// pivot row and pivot column both have more than one entry. Otherwise, the</span></div>
<divclass="line"><aname="l00395"></a><spanclass="lineno"> 395</span> <spanclass="comment">// residual matrix can be updated more efficiently by calling one of the</span></div>
<divclass="line"><aname="l00402"></a><spanclass="lineno"> 402</span> <spanclass="comment">// These matrices are transformed during the algorithm into the final L and U</span></div>
<divclass="line"><aname="l00403"></a><spanclass="lineno"> 403</span> <spanclass="comment">// matrices modulo some row and column permutations. Note that the columns of</span></div>
<divclass="line"><aname="l00404"></a><spanclass="lineno"> 404</span> <spanclass="comment">// these matrices stay in the initial order.</span></div>
<divclass="line"><aname="l00408"></a><spanclass="lineno"> 408</span> <spanclass="comment">// These matrices will hold the final L and U. The are created columns by</span></div>
<divclass="line"><aname="l00409"></a><spanclass="lineno"> 409</span> <spanclass="comment">// columns from left to right, and at the end, their rows are permuted by</span></div>
<divclass="line"><aname="l00410"></a><spanclass="lineno"> 410</span> <spanclass="comment">// ComputeLU() to become triangular.</span></div>
<divclass="line"><aname="l00414"></a><spanclass="lineno"> 414</span> <spanclass="comment">// The columns of permuted_lower_ for which we do need a call to</span></div>
<divclass="line"><aname="l00415"></a><spanclass="lineno"> 415</span> <spanclass="comment">// PermutedLowerSparseSolve(). This speeds up ComputeColumn().</span></div>
<divclass="line"><aname="l00418"></a><spanclass="lineno"> 418</span> <spanclass="comment">// Contains the non-zero positions of the current residual matrix (the</span></div>
<divclass="line"><aname="l00419"></a><spanclass="lineno"> 419</span> <spanclass="comment">// lower-right square matrix that gets smaller by one row and column at each</span></div>
<divclass="line"><aname="l00423"></a><spanclass="lineno"> 423</span> <spanclass="comment">// Data structure to access the columns by increasing degree.</span></div>
<divclass="line"><aname="l00426"></a><spanclass="lineno"> 426</span> <spanclass="comment">// True as long as only singleton columns of the residual matrix are used.</span></div>
<divclass="line"><aname="l00429"></a><spanclass="lineno"> 429</span> <spanclass="comment">// Boolean used to know when col_by_degree_ become useful.</span></div>
<divclass="line"><aname="l00432"></a><spanclass="lineno"> 432</span> <spanclass="comment">// FindPivot() needs to look at the first entries of col_by_degree_, it</span></div>
<divclass="line"><aname="l00433"></a><spanclass="lineno"> 433</span> <spanclass="comment">// temporary put them here before pushing them back to col_by_degree_.</span></div>
<divclass="line"><aname="l00436"></a><spanclass="lineno"> 436</span> <spanclass="comment">// Singleton column indices are kept here rather than in col_by_degree_ to</span></div>
<divclass="line"><aname="l00437"></a><spanclass="lineno"> 437</span> <spanclass="comment">// optimize the algorithm: as long as this or singleton_row_ are not empty,</span></div>
<divclass="line"><aname="l00438"></a><spanclass="lineno"> 438</span> <spanclass="comment">// col_by_degree_ do not need to be initialized nor updated.</span></div>
<divclass="line"><aname="l00444"></a><spanclass="lineno"> 444</span> <spanclass="comment">// Proto holding all the parameters of this algorithm.</span></div>
<divclass="line"><aname="l00447"></a><spanclass="lineno"> 447</span> <spanclass="comment">// Number of floating point operations of the last factorization.</span></div>
<divclass="ttc"id="anamespaceoperations__research_html"><divclass="ttname"><ahref="namespaceoperations__research.html">operations_research</a></div><divclass="ttdoc">Collection of objects used to extend the Constraint Solver library.</div><divclass="ttdef"><b>Definition:</b><ahref="dense__doubly__linked__list_8h_source.html#l00021">dense_doubly_linked_list.h:21</a></div></div>