<ahref="markowitz_8h.html">Go to the documentation of this file.</a><divclass="fragment"><divclass="line"><aid="l00001"name="l00001"></a><spanclass="lineno"> 1</span><spanclass="comment">// Copyright 2010-2021 Google LLC</span></div>
<divclass="line"><aid="l00002"name="l00002"></a><spanclass="lineno"> 2</span><spanclass="comment">// Licensed under the Apache License, Version 2.0 (the "License");</span></div>
<divclass="line"><aid="l00003"name="l00003"></a><spanclass="lineno"> 3</span><spanclass="comment">// you may not use this file except in compliance with the License.</span></div>
<divclass="line"><aid="l00004"name="l00004"></a><spanclass="lineno"> 4</span><spanclass="comment">// You may obtain a copy of the License at</span></div>
<divclass="line"><aid="l00008"name="l00008"></a><spanclass="lineno"> 8</span><spanclass="comment">// Unless required by applicable law or agreed to in writing, software</span></div>
<divclass="line"><aid="l00009"name="l00009"></a><spanclass="lineno"> 9</span><spanclass="comment">// distributed under the License is distributed on an "AS IS" BASIS,</span></div>
<divclass="line"><aid="l00010"name="l00010"></a><spanclass="lineno"> 10</span><spanclass="comment">// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span></div>
<divclass="line"><aid="l00011"name="l00011"></a><spanclass="lineno"> 11</span><spanclass="comment">// See the License for the specific language governing permissions and</span></div>
<divclass="line"><aid="l00012"name="l00012"></a><spanclass="lineno"> 12</span><spanclass="comment">// limitations under the License.</span></div>
<divclass="line"><aid="l00014"name="l00014"></a><spanclass="lineno"> 14</span><spanclass="comment">// LU decomposition algorithm of a sparse matrix B with Markowitz pivot</span></div>
<divclass="line"><aid="l00015"name="l00015"></a><spanclass="lineno"> 15</span><spanclass="comment">// selection strategy. The algorithm constructs a lower matrix L, upper matrix</span></div>
<divclass="line"><aid="l00016"name="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"><aid="l00018"name="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"><aid="l00019"name="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"><aid="l00020"name="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"><aid="l00021"name="l00021"></a><spanclass="lineno"> 21</span><spanclass="comment">// L and U column by column from left to right.</span></div>
<divclass="line"><aid="l00023"name="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"><aid="l00024"name="l00024"></a><spanclass="lineno"> 24</span><spanclass="comment">// square submatrix that still needs to be factorized during the classical</span></div>
<divclass="line"><aid="l00025"name="l00025"></a><spanclass="lineno"> 25</span><spanclass="comment">// Gaussian elimination. The algorithm maintains the non-zero pattern of its</span></div>
<divclass="line"><aid="l00026"name="l00026"></a><spanclass="lineno"> 26</span><spanclass="comment">// rows and its row/column degrees.</span></div>
<divclass="line"><aid="l00028"name="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"><aid="l00029"name="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"><aid="l00030"name="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"><aid="l00031"name="l00031"></a><spanclass="lineno"> 31</span><spanclass="comment">// residual matrix are kept in a priority queue.</span></div>
<divclass="line"><aid="l00033"name="l00033"></a><spanclass="lineno"> 33</span><spanclass="comment">// We compute the numerical value of these residual columns like in a</span></div>
<divclass="line"><aid="l00034"name="l00034"></a><spanclass="lineno"> 34</span><spanclass="comment">// left-looking algorithm by solving a sparse lower-triangular system with the</span></div>
<divclass="line"><aid="l00035"name="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"><aid="l00036"name="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"><aid="l00037"name="l00037"></a><spanclass="lineno"> 37</span><spanclass="comment">// candidate column was already considered before). As a by-product, we also</span></div>
<divclass="line"><aid="l00038"name="l00038"></a><spanclass="lineno"> 38</span><spanclass="comment">// get the corresponding column of U.</span></div>
<divclass="line"><aid="l00040"name="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"><aid="l00042"name="l00042"></a><spanclass="lineno"> 42</span><spanclass="comment">// is minimized. Only the pivots with a magnitude greater than</span></div>
<divclass="line"><aid="l00043"name="l00043"></a><spanclass="lineno"> 43</span><spanclass="comment">// 'lu_factorization_pivot_threshold' times the maximum magnitude of the</span></div>
<divclass="line"><aid="l00044"name="l00044"></a><spanclass="lineno"> 44</span><spanclass="comment">// corresponding residual column are considered for stability reasons.</span></div>
<divclass="line"><aid="l00046"name="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"><aid="l00047"name="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"><aid="l00048"name="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"><aid="l00049"name="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"><aid="l00050"name="l00050"></a><spanclass="lineno"> 50</span><spanclass="comment">// fill-in created during a step.</span></div>
<divclass="line"><aid="l00054"name="l00054"></a><spanclass="lineno"> 54</span><spanclass="comment">// J. R. Gilbert and T. Peierls, "Sparse partial pivoting in time proportional</span></div>
<divclass="line"><aid="l00055"name="l00055"></a><spanclass="lineno"> 55</span><spanclass="comment">// to arithmetic operations," SIAM J. Sci. Statist. Comput., 9 (1988): 862-874.</span></div>
<divclass="line"><aid="l00064"name="l00064"></a><spanclass="lineno"> 64</span><spanclass="comment">// TODO(user): Determine whether any of these would bring any benefit:</span></div>
<divclass="line"><aid="l00065"name="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"><aid="l00093"name="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"><aid="l00094"name="l00094"></a><spanclass="lineno"> 94</span><spanclass="comment">// matrix during the Gaussian elimination.</span></div>
<divclass="line"><aid="l00096"name="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"><aid="l00097"name="l00097"></a><spanclass="lineno"> 97</span><spanclass="comment">// "removed" from the residual matrix. Note however that the row and column</span></div>
<divclass="line"><aid="l00098"name="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"><aid="l00099"name="l00099"></a><spanclass="lineno"> 99</span><spanclass="comment">// given step will only correspond to a subset of the initial indices.</span></div>
<divclass="line"><aid="l00104"name="l00104"></a><spanclass="lineno"> 104</span><spanclass="comment">// Releases the memory used by this class.</span></div>
<divclass="line"><aid="l00107"name="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"><aid="l00110"name="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"><aid="l00111"name="l00111"></a><spanclass="lineno"> 111</span><spanclass="comment">// rows/columns whose given permutation is kInvalidRow or kInvalidCol.</span></div>
<divclass="line"><aid="l00112"name="l00112"></a><spanclass="lineno"> 112</span><spanclass="comment">// This also fills the singleton columns/rows with the corresponding entries.</span></div>
<divclass="line"><aid="l00119"name="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"><aid="l00122"name="l00122"></a><spanclass="lineno"> 122</span><spanclass="comment">// Marks the given pivot row and column as deleted.</span></div>
<divclass="line"><aid="l00123"name="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"><aid="l00126"name="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"><aid="l00127"name="l00127"></a><spanclass="lineno"> 127</span><spanclass="comment">// keep the correct degree after a call to DeleteRowAndColumn(). This is</span></div>
<divclass="line"><aid="l00128"name="l00128"></a><spanclass="lineno"> 128</span><spanclass="comment">// because row_non_zero_[row] is only lazily cleaned.</span></div>
<divclass="line"><aid="l00132"name="l00132"></a><spanclass="lineno"> 132</span><spanclass="comment">// Returns true if the column has been deleted by DeleteRowAndColumn().</span></div>
<divclass="line"><aid="l00135"name="l00135"></a><spanclass="lineno"> 135</span><spanclass="comment">// Removes from the corresponding row_non_zero_[row] the columns that have</span></div>
<divclass="line"><aid="l00136"name="l00136"></a><spanclass="lineno"> 136</span><spanclass="comment">// been previously deleted by DeleteRowAndColumn().</span></div>
<divclass="line"><aid="l00139"name="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"><aid="l00140"name="l00140"></a><spanclass="lineno"> 140</span><spanclass="comment">// none can be found.</span></div>
<divclass="line"><aid="l00143"name="l00143"></a><spanclass="lineno"> 143</span><spanclass="comment">// Performs a generic Gaussian update of the residual matrix:</span></div>
<divclass="line"><aid="l00144"name="l00144"></a><spanclass="lineno"> 144</span><spanclass="comment">// - DeleteRowAndColumn() must already have been called.</span></div>
<divclass="line"><aid="l00145"name="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"><aid="l00146"name="l00146"></a><spanclass="lineno"> 146</span><spanclass="comment">// outer product of the pivot column and row.</span></div>
<divclass="line"><aid="l00148"name="l00148"></a><spanclass="lineno"> 148</span><spanclass="comment">// Important: as a small optimization, this function does not call</span></div>
<divclass="line"><aid="l00149"name="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"><aid="l00150"name="l00150"></a><spanclass="lineno"> 150</span><spanclass="comment">// the client.</span></div>
<divclass="line"><aid="l00154"name="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"><aid="l00155"name="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"><aid="l00161"name="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"><aid="l00162"name="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"><aid="l00165"name="l00165"></a><spanclass="lineno"> 165</span><spanclass="comment">// Returns the set of non-zeros of the given row (unsorted).</span></div>
<divclass="line"><aid="l00166"name="l00166"></a><spanclass="lineno"> 166</span><spanclass="comment">// Call RemoveDeletedColumnsFromRow(row) to clean the row first.</span></div>
<divclass="line"><aid="l00167"name="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"><aid="l00173"name="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"><aid="l00174"name="l00174"></a><spanclass="lineno"> 174</span><spanclass="comment">// non-zero pattern of the given pivot_row.</span></div>
<divclass="line"><aid="l00177"name="l00177"></a><spanclass="lineno"> 177</span><spanclass="comment">// Different version of MergeInto() that works only if the non-zeros position</span></div>
<divclass="line"><aid="l00178"name="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"><aid="l00180"name="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"><aid="l00184"name="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"><aid="l00185"name="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"><aid="l00186"name="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"><aid="l00189"name="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"><aid="l00190"name="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"><aid="l00202"name="l00202"></a><spanclass="lineno"> 202</span><spanclass="comment">// Adjustable priority queue of columns. Pop() returns a column with the</span></div>
<divclass="line"><aid="l00203"name="l00203"></a><spanclass="lineno"> 203</span><spanclass="comment">// smallest degree first (degree = number of entries in the column).</span></div>
<divclass="line"><aid="l00204"name="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"><aid="l00209"name="l00209"></a><spanclass="lineno"> 209</span><spanclass="comment">// Releases the memory used by this class.</span></div>
<divclass="line"><aid="l00212"name="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"><aid="l00213"name="l00213"></a><spanclass="lineno"> 213</span><spanclass="comment">// with a degree from 1 to max_degree included.</span></div>
<divclass="line"><aid="l00216"name="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"><aid="l00217"name="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"><aid="l00218"name="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"><aid="l00221"name="l00221"></a><spanclass="lineno"> 221</span><spanclass="comment">// Removes the column index with higher priority from the queue and returns</span></div>
<divclass="line"><aid="l00222"name="l00222"></a><spanclass="lineno"> 222</span><spanclass="comment">// it. Returns kInvalidCol if the queue is empty.</span></div>
<divclass="line"><aid="l00233"name="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"><aid="l00234"name="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"><aid="l00235"name="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"><aid="l00236"name="l00236"></a><spanclass="lineno"> 236</span><spanclass="comment">// reuses the memory of the columns that are no longer needed.</span></div>
<divclass="line"><aid="l00241"name="l00241"></a><spanclass="lineno"> 241</span><spanclass="comment">// Resets the repository to num_cols empty columns.</span></div>
<divclass="line"><aid="l00244"name="l00244"></a><spanclass="lineno"> 244</span><spanclass="comment">// Returns the column with given index.</span></div>
<divclass="line"><aid="l00247"name="l00247"></a><spanclass="lineno"> 247</span><spanclass="comment">// Gets the mutable column with given column index. The returned vector</span></div>
<divclass="line"><aid="l00248"name="l00248"></a><spanclass="lineno"> 248</span><spanclass="comment">// address is only valid until the next call to mutable_column().</span></div>
<divclass="line"><aid="l00251"name="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"><aid="l00252"name="l00252"></a><spanclass="lineno"> 252</span><spanclass="comment">// memory pool that is used to create new mutable_column() on demand.</span></div>
<divclass="line"><aid="l00255"name="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"><aid="l00256"name="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"><aid="l00257"name="l00257"></a><spanclass="lineno"> 257</span><spanclass="comment">// be fine).</span></div>
<divclass="line"><aid="l00261"name="l00261"></a><spanclass="lineno"> 261</span><spanclass="comment">// mutable_column(col) is stored in columns_[mapping_[col]].</span></div>
<divclass="line"><aid="l00262"name="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"><aid="l00270"name="l00270"></a><spanclass="lineno"> 270</span><spanclass="comment">// The class that computes either the actual L.U decomposition, or the</span></div>
<divclass="line"><aid="l00271"name="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"><aid="l00277"name="l00277"></a><spanclass="lineno"> 277</span><spanclass="comment">// Computes the full factorization with P, Q, L and U.</span></div>
<divclass="line"><aid="l00279"name="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"><aid="l00280"name="l00280"></a><spanclass="lineno"> 280</span><spanclass="comment">// permutation (col_perm) will contain a maximum non-singular set of columns</span></div>
<divclass="line"><aid="l00281"name="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"><aid="l00282"name="l00282"></a><spanclass="lineno"> 282</span><spanclass="comment">// such that 'row_perm[row] == kInvalidRow', then the matrix will be</span></div>
<divclass="line"><aid="l00289"name="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"><aid="l00290"name="l00290"></a><spanclass="lineno"> 290</span><spanclass="comment">// permutations using another algorithm (for instance left-looking L.U). This</span></div>
<divclass="line"><aid="l00291"name="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"><aid="l00292"name="l00292"></a><spanclass="lineno"> 292</span><spanclass="comment">// current implementation is not optimized for this.</span></div>
<divclass="line"><aid="l00294"name="l00294"></a><spanclass="lineno"> 294</span><spanclass="comment">// It behaves the same as ComputeLU() for singular matrices.</span></div>
<divclass="line"><aid="l00296"name="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"><aid="l00297"name="l00297"></a><spanclass="lineno"> 297</span><spanclass="comment">// independent columns of maximum size. If all the given columns are</span></div>
<divclass="line"><aid="l00298"name="l00298"></a><spanclass="lineno"> 298</span><spanclass="comment">// independent, the returned Status will be OK.</span></div>
<divclass="line"><aid="l00303"name="l00303"></a><spanclass="lineno"> 303</span><spanclass="comment">// Releases the memory used by this class.</span></div>
<divclass="line"><aid="l00306"name="l00306"></a><spanclass="lineno"> 306</span><spanclass="comment">// Returns an estimate of the time spent in the last factorization.</span></div>
<divclass="line"><aid="l00309"name="l00309"></a><spanclass="lineno"> 309</span><spanclass="comment">// Returns a string containing the statistics for this class.</span></div>
<divclass="line"><aid="l00334"name="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"><aid="l00335"name="l00335"></a><spanclass="lineno"> 335</span><spanclass="comment">// column permutation that move these columns in order to form an identity</span></div>
<divclass="line"><aid="l00336"name="l00336"></a><spanclass="lineno"> 336</span><spanclass="comment">// sub-matrix on the upper left.</span></div>
<divclass="line"><aid="l00338"name="l00338"></a><spanclass="lineno"> 338</span><spanclass="comment">// Note(user): Linear programming bases usually have a resonable percentage of</span></div>
<divclass="line"><aid="l00339"name="l00339"></a><spanclass="lineno"> 339</span><spanclass="comment">// slack columns in them, so this gives a big speedup.</span></div>
<divclass="line"><aid="l00344"name="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"><aid="l00345"name="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"><aid="l00346"name="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"><aid="l00347"name="l00347"></a><spanclass="lineno"> 347</span><spanclass="comment">// quite a few.</span></div>
<divclass="line"><aid="l00349"name="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"><aid="l00350"name="l00350"></a><spanclass="lineno"> 350</span><spanclass="comment">// InitializeResidualMatrix() and later in RemoveRowFromResidualMatrix().</span></div>
<divclass="line"><aid="l00355"name="l00355"></a><spanclass="lineno"> 355</span><spanclass="comment">// Helper function for determining if a column is a residual singleton column.</span></div>
<divclass="line"><aid="l00356"name="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"><aid="l00360"name="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"><aid="l00361"name="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"><aid="l00362"name="l00362"></a><spanclass="lineno"> 362</span><spanclass="comment">// current lower_ and the last computed column 'col' of a previous residual</span></div>
<divclass="line"><aid="l00363"name="l00363"></a><spanclass="lineno"> 363</span><spanclass="comment">// matrix. This uses the same algorithm as a left-looking factorization (see</span></div>
<divclass="line"><aid="l00364"name="l00364"></a><spanclass="lineno"> 364</span><spanclass="comment">// lu_factorization.h for more details).</span></div>
<divclass="line"><aid="l00368"name="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"><aid="l00369"name="l00369"></a><spanclass="lineno"> 369</span><spanclass="comment">// enough magnitude. Returns its Markowitz score and updates the given</span></div>
<divclass="line"><aid="l00372"name="l00372"></a><spanclass="lineno"> 372</span><spanclass="comment">// We use the strategy of Zlatev, "On some pivotal strategies in Gaussian</span></div>
<divclass="line"><aid="l00373"name="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"><aid="l00374"name="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"><aid="l00375"name="l00375"></a><spanclass="lineno"> 375</span><spanclass="comment">// or 4) amongst the ones which have the lowest number of entries.</span></div>
<divclass="line"><aid="l00377"name="l00377"></a><spanclass="lineno"> 377</span><spanclass="comment">// Amongst the pivots with a minimum Markowitz number, we choose the one</span></div>
<divclass="line"><aid="l00378"name="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"><aid="l00379"name="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"><aid="l00384"name="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"><aid="l00388"name="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"><aid="l00389"name="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"><aid="l00393"name="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"><aid="l00394"name="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"><aid="l00395"name="l00395"></a><spanclass="lineno"> 395</span><spanclass="comment">// residual matrix can be updated more efficiently by calling one of the</span></div>
<divclass="line"><aid="l00399"name="l00399"></a><spanclass="lineno"> 399</span><spanclass="comment">// Pointer to the matrix to factorize.</span></div>
<divclass="line"><aid="l00402"name="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"><aid="l00403"name="l00403"></a><spanclass="lineno"> 403</span><spanclass="comment">// matrices modulo some row and column permutations. Note that the columns of</span></div>
<divclass="line"><aid="l00404"name="l00404"></a><spanclass="lineno"> 404</span><spanclass="comment">// these matrices stay in the initial order.</span></div>
<divclass="line"><aid="l00408"name="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"><aid="l00409"name="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"><aid="l00410"name="l00410"></a><spanclass="lineno"> 410</span><spanclass="comment">// ComputeLU() to become triangular.</span></div>
<divclass="line"><aid="l00414"name="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"><aid="l00415"name="l00415"></a><spanclass="lineno"> 415</span><spanclass="comment">// PermutedLowerSparseSolve(). This speeds up ComputeColumn().</span></div>
<divclass="line"><aid="l00418"name="l00418"></a><spanclass="lineno"> 418</span><spanclass="comment">// Contains the non-zero positions of the current residual matrix (the</span></div>
<divclass="line"><aid="l00419"name="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"><aid="l00423"name="l00423"></a><spanclass="lineno"> 423</span><spanclass="comment">// Data structure to access the columns by increasing degree.</span></div>
<divclass="line"><aid="l00426"name="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"><aid="l00429"name="l00429"></a><spanclass="lineno"> 429</span><spanclass="comment">// Boolean used to know when col_by_degree_ become useful.</span></div>
<divclass="line"><aid="l00432"name="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"><aid="l00433"name="l00433"></a><spanclass="lineno"> 433</span><spanclass="comment">// temporary put them here before pushing them back to col_by_degree_.</span></div>
<divclass="line"><aid="l00436"name="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"><aid="l00437"name="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"><aid="l00438"name="l00438"></a><spanclass="lineno"> 438</span><spanclass="comment">// col_by_degree_ do not need to be initialized nor updated.</span></div>
<divclass="line"><aid="l00444"name="l00444"></a><spanclass="lineno"> 444</span><spanclass="comment">// Proto holding all the parameters of this algorithm.</span></div>
<divclass="line"><aid="l00447"name="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>