SparseSolver.h 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601
  1. #define NO_TAUCS
  2. #ifdef NO_TAUCS
  3. typedef double taucsType;
  4. # include <vector>
  5. # include <map>
  6. #else
  7. # include "taucsaddon.h"
  8. #endif
  9. class SparseSolver {
  10. protected:
  11. // is set to true iff m_A is symmetric positive definite
  12. bool m_SPD;
  13. #ifndef NO_TAUCS
  14. taucs_ccs_matrix * m_A;
  15. taucs_ccs_matrix * m_AT;
  16. taucs_ccs_matrix * m_ATA;
  17. #endif
  18. #ifndef NO_TAUCS
  19. void * m_factorATA;
  20. void * m_factorA;
  21. void * m_etree; // for the factor update
  22. #endif
  23. // placeholder, so that we don't need to allocate space every time
  24. // the space is allocated when a factor for ATA is created
  25. std::vector<taucsType> m_ATb;
  26. // helper map to create A
  27. std::vector< std::map<int,taucsType> > m_colsA;
  28. // the dimensions of the A matrix
  29. int m_numRows;
  30. int m_numCols;
  31. public:
  32. SparseSolver(const int numRows = 0, const int numCols = 0, const bool isSPD = false)
  33. :
  34. m_SPD(isSPD)
  35. ,
  36. #ifndef NO_TAUCS
  37. m_A(NULL)
  38. , m_AT(NULL)
  39. , m_ATA(NULL)
  40. , m_factorATA(NULL)
  41. , m_factorA(NULL)
  42. , m_etree(NULL)
  43. , m_ATb(NULL)
  44. ,
  45. #endif
  46. m_colsA(numCols)
  47. , m_numRows(numRows)
  48. , m_numCols(numCols)
  49. {};
  50. ~SparseSolver() { ClearObject();}
  51. //Operators
  52. public:
  53. /** Copies the matrix.
  54. However, factorizations are not copied.
  55. This is because the factorizations are actually owned by taucs
  56. and we have to call taucs to release them.
  57. If we would release them from two different objects,
  58. we would run into trouble.
  59. */
  60. SparseSolver& operator=(const SparseSolver& other)
  61. {
  62. //Reset ourselves
  63. Reset(other.GetNumRows(), other.GetNumColumns());
  64. //Copy the sparse matrix
  65. m_colsA = other.m_colsA;
  66. m_SPD = other.m_SPD;
  67. m_numRows = other.m_numRows;
  68. m_numCols = other.m_numCols;
  69. return *this;
  70. }
  71. //Methods
  72. public:
  73. ///Resets all internal data structures and sets the new size of this matrix
  74. void Reset(const int numRows, const int numCols);
  75. ///Returns the number of rows of the \c A matrix.
  76. inline int GetNumRows() const {return m_numRows;}
  77. ///Returns the number of columns of the \c A matrix.
  78. inline int GetNumColumns() const {return m_numCols;}
  79. ///Returns the dimensions of the \c A matrix.
  80. inline void GetAMatrixSize(int & numRows, int & numCols) const
  81. {
  82. numRows = m_numRows;
  83. numCols = m_numCols;
  84. }
  85. ///Returns true if no rows or columns are in the matrix.
  86. inline bool IsEmpty() const {return m_numRows == 0 || m_numCols == 0;}
  87. ///Clears all data structures.
  88. void ClearObject();
  89. // adds a new entry to the sparse matrix A
  90. // i and j are 0-based
  91. // if the A^T A matrix had been factored, this will destroy the factor
  92. void AddIJV(const int i, const int j, const taucsType v);
  93. // updates the entry in A by adding the value v to the current value
  94. // i and j are 0-based
  95. // if the A^T A matrix had been factored, this will destroy the factor
  96. void AddToIJV(const int i, const int j, const taucsType v);
  97. // updates the entries in A by adding the values v in B to the current
  98. // Value
  99. // if the A^T A matrix had been factored, this will destroy the factor
  100. void AddMatrix(SparseSolver & B);
  101. // updates the entries in A by adding the values v in B to the current
  102. // Value in A offset by (i,j)
  103. // like matlab's A[i:m,j:n] = B, where [m,n] = size(B);
  104. // i and j are 0-based
  105. // if the A^T A matrix had been factored, this will destroy the factor
  106. void AddMatrix(const int i, const int j, SparseSolver & B);
  107. ///Removes all entries from the given row.
  108. ///If the A^T A matrix had been factored, this will destroy the factor.
  109. inline bool ClearRow(const int iRow)
  110. {
  111. if (iRow >= 0 && iRow < m_numRows)
  112. {
  113. #ifndef NO_TAUCS
  114. ClearFactorATA();
  115. ClearFactorA();
  116. ClearMatricesATA();
  117. ClearMatricesA();
  118. #endif
  119. //Go over all columns, try to find the respective row and delete it
  120. for(std::vector< std::map<int,taucsType> >::iterator itCol=m_colsA.begin();itCol!=m_colsA.end();itCol++)
  121. {
  122. //Find the row
  123. std::map<int,taucsType>::iterator itRow = itCol->find(iRow);
  124. if (itRow != itCol->end())
  125. {
  126. itCol->erase(itRow);
  127. }
  128. }
  129. return true;
  130. }
  131. return false;
  132. }
  133. ///Removes all entries from the given column.
  134. ///If the A^T A matrix had been factored, this will destroy the factor.
  135. inline bool ClearColumn(const int iColumn)
  136. {
  137. if (iColumn >= 0 && iColumn < m_numCols)
  138. {
  139. #ifndef NO_TAUCS
  140. ClearFactorATA();
  141. ClearFactorA();
  142. ClearMatricesATA();
  143. ClearMatricesA();
  144. #endif
  145. m_colsA[iColumn].clear();
  146. return true;
  147. }
  148. return false;
  149. }
  150. // Sets the status of a matrix - whether SPD or not
  151. void SetSPD(bool isSPD) {m_SPD = isSPD;}
  152. // Return true only if symmetric, automatically true if isSPD flag is
  153. // set to true, otherwise actually determine if matrix is symmetric
  154. bool IsSymmetric();
  155. #ifndef NO_TAUCS
  156. // allows to add an anchored vertex without destroying the factor, if there was one
  157. // i is the anchor's number (i.e. the index of the mesh vertex that is anchored is i)
  158. // w is the weight of the anchor in the original Ax=b system. HAS TO BE POSITIVE!!
  159. // if there was no factor for A^T A, this will simply add an anchor row to the Ax=b system
  160. // if there was a factor, the factor will be updated, approximately at the cost of
  161. // a single solve.
  162. void AddAnchor(const int i, const taucsType w);
  163. // Will create A^T A and its factorization, as well as store A^T
  164. // returns true on success, false otherwise
  165. bool FactorATA();
  166. // Will create A and its factorization. If A is spd then Cholesky factor, otherwise LU
  167. // returns true on success, false otherwise
  168. // Assumes A is square and invertible
  169. bool FactorA();
  170. // Will create *symbolic* factorization of ATA and return it; returns NULL on failure
  171. void * SymbolicFactorATA();
  172. taucs_ccs_matrix * GetATA_Copy();
  173. // Will create the actual numerical factorization of the present ATA matrix
  174. // with the same non-zero pattern as created by SymbolicFactorATA()
  175. bool FactorATA_UseSymbolic(void * symbFactor,
  176. taucs_ccs_matrix ** PAP,
  177. int * perm,
  178. int * invperm);
  179. // Solves the normal equations for Ax = b, namely A^T A x = A^T b
  180. // it is assumed that enough space is allocated in x
  181. // Uses the factorization provided in factor
  182. // numRhs should be the the number of right-hand sides stored in b (and respectively,
  183. // there should be enough space allocated in the solution vector x)
  184. // returns true on success, false otherwise
  185. bool SolveATA_UseFactor(void * factor,
  186. taucs_ccs_matrix * PAP,
  187. int * perm,
  188. int * invperm,
  189. const taucsType * b, taucsType * x, const int numRhs);
  190. // Solves the normal equations for Ax = b, namely A^T A x = A^T b
  191. // it is assumed that enough space is allocated in x
  192. // If a factorization of A^T A exists, it will be used, otherwise it will be created
  193. // numRhs should be the the number of right-hand sides stored in b (and respectively,
  194. // there should be enough space allocated in the solution vector x)
  195. // returns true on success, false otherwise
  196. bool SolveATA(const taucsType * b, taucsType * x, const int numRhs);
  197. // Same as SolveATA only that this solves the actual system Ax = b
  198. // It is assumed that A is rectangular and invertible
  199. bool SolveA(const taucsType * b, taucsType * x, const int numRhs);
  200. // The version of SolveATA with 3 right-hand sides
  201. // returns true on success, false otherwise
  202. bool SolveATA3(const taucsType * bx, const taucsType * by, const taucsType * bz,
  203. taucsType * x, taucsType * y, taucsType * z);
  204. // The version of SolveATA with 2 right-hand sides
  205. // returns true on success, false otherwise
  206. bool SolveATA2(const taucsType * bx, const taucsType * by,
  207. taucsType * x, taucsType * y);
  208. #endif
  209. // Matrix utility routines
  210. // Stores the result of Matrix*v in result.
  211. // v can have numCols columns; then the result is stored column-wise as well
  212. // It is assumed space is allocaed in result!
  213. // v cannot be the same pointer as result
  214. void MultiplyMatrixVector(const taucsType * v, taucsType * result, const int numCols) const;
  215. // Multiplies the matrix by diagonal matrix D from the left, stores the result
  216. // in the columns of res
  217. void MultiplyDiagMatrixMatrix(const taucsType * D, SparseSolver & res) const;
  218. // Multiplies the matrix by the given matrix B from the right
  219. // and stores the result in the columns of res
  220. // isSPD tells us whether the result should be SPD or not
  221. // retuns false if the dimensions didn't match (in such case res is unaltered), otherwise true
  222. bool MultiplyMatrixRight(const SparseSolver & B, SparseSolver & res,const bool isSPD) const;
  223. // Transposes the matrix
  224. // and stores the result in the columns of res
  225. bool Transpose(SparseSolver & res) const;
  226. // will remove the rows startInd-endInd (including ends, zero-based) from the matrix
  227. // will discard any factors
  228. bool DeleteRowRange(const int startInd, const int endInd);
  229. // will remove the columns startInd-endInd (including ends, zero-based) from the matrix
  230. // will discard any factors
  231. bool DeleteColumnRange(const int startInd, const int endInd);
  232. // copies columns startInd through endInd (including, zero-based) from the matrix to res matrix
  233. // previous data in res, including factors, is erased.
  234. bool CopyColumnRange(const int startInd, const int endInd, SparseSolver & res) const;
  235. // copies rows startInd through endInd (including, zero-based) from the matrix to res matrix
  236. // previous data in res, including factors, is erased.
  237. bool CopyRowRange(const int startInd, const int endInd, SparseSolver & res) const;
  238. ///Multiplies the given range of rows (zero-based, including startInd and endInd) with the given scalar.
  239. bool MultiplyRows(const int startInd, const int endInd, const taucsType val);
  240. ///Multiplies all entries of the matrix with the given scalar. Will discard any factors.
  241. void MultiplyMatrixScalar(const taucsType val);
  242. /** Computes IdentityMatrix minus this matrix in-place. Will discard any factors.
  243. If an entry on the diagonal is missing, it will be created.
  244. */
  245. void IdentityMinusMatrix();
  246. /** Computes IdentityMatrix plus this matrix in-place. Will discard any factors.
  247. If an entry on the diagonal is missing, it will be created.
  248. */
  249. void IdentityPlusMatrix();
  250. // Alec:
  251. // Note on splice methods:
  252. // The following splice methods act like matlabs splicing and
  253. // reordering via index lists and the operator()
  254. // Both SpliceColumns and SpliceRows are ignorant of SPD, meaning that
  255. // they will not give "correct" splices for SPD matrices: splices of
  256. // This only matters if you are not setting all
  257. // SPD matrices are just splices of the lower triangle
  258. //
  259. // This only matters if you are not setting the upper half of the
  260. // matrix. To get correct splices you need to set both upper and lower
  261. // triangles before splicing.
  262. // Alec:
  263. // Copies certain cols in any order to a new matrix res
  264. // Like in Matlab B = A(:,column_indices)
  265. // Previous data in res is erased.
  266. // Returns false on error. As in column_indices are invalid
  267. // Result is always NOT SPD
  268. //
  269. // WARNING: If your matrix is only the lower half of an SPD matrix
  270. // then the result will only be a copy of the lower half of the
  271. // spliced columns. See note above (Note on splice methods)
  272. bool SpliceColumns(
  273. const std::vector<size_t> column_indices,
  274. SparseSolver & res) const;
  275. // Alec:
  276. // Copies certain rows in any order to a new matrix res
  277. // Like in Matlab B = A(:,row_indices)
  278. // Previous data in res is erased.
  279. // Returns false on error. As in row_indices are invalid
  280. // Result is always NOT SPD
  281. //
  282. // WARNING: If your matrix is only the lower half of an SPD matrix
  283. // then the result will only be a copy of the lower half of the
  284. // spliced rows. See note above (Note on splice methods)
  285. bool SpliceRows(
  286. const std::vector<size_t> row_indices,
  287. SparseSolver & res) const;
  288. // Wrapper than calls
  289. // SpliceColumns(column_indices, temp)
  290. // then
  291. // temp.SpliceRows(row_indices, res);
  292. bool SpliceColumnsThenRows(
  293. const std::vector<size_t> column_indices,
  294. const std::vector<size_t> row_indices,
  295. SparseSolver & res) const;
  296. // Vertical concatenation, works like matlab:
  297. // C = [A ; B];
  298. // If this matrix is A in the above the result is the concatenation of
  299. // this matrix on top of the supplied other matrix into the result
  300. // number of columns in A must equal number of columns in B
  301. //
  302. bool VerticalConcatenation(
  303. SparseSolver & other,
  304. SparseSolver & res);
  305. // Convert the matrix to IJV aka Coordinate format,
  306. // Outputs:
  307. // vals non-zero values, in no particular order
  308. // row_indices row indices corresponding to vals
  309. // column_indices column indices corresponding to vals
  310. //
  311. // All indices are 0-based
  312. void ConvertToIJV(
  313. std::vector<int> & row_indices,
  314. std::vector<int> & column_indices,
  315. std::vector<taucsType> & vals);
  316. // Convert lower triangle (including diagonal) of the matrix to IJV aka
  317. // Coordinate format,
  318. // Outputs:
  319. // vals non-zero values, in no particular order
  320. // row_indices row indices corresponding to vals
  321. // column_indices column indices corresponding to vals
  322. //
  323. // All indices are 0-based
  324. void ConvertLowerTriangleToIJV(
  325. std::vector<int> & row_indices,
  326. std::vector<int> & column_indices,
  327. std::vector<taucsType> & vals);
  328. // Convert the matrix to Compressed sparse column (CSC or CCS) format,
  329. // also known as Harwell Boeing format. As described:
  330. // http://netlib.org/linalg/html_templates/node92.html
  331. // or
  332. // http://en.wikipedia.org/wiki/Sparse_matrix
  333. // #Compressed_sparse_column_.28CSC_or_CCS.29
  334. // Outputs:
  335. // nnz number of non zero entries
  336. // num_rows number of rows
  337. // num_cols number of cols
  338. // vals non-zero values, row indices running fastest,
  339. // size(vals) = nnz
  340. // row_indices row indices corresponding to vals,
  341. // size(row_indices) = nnz
  342. // column_pointers index in vals of first entry in each column,
  343. // size(column_pointers) = num_cols+1
  344. //
  345. // All indices and pointers are 0-based
  346. void ConvertToHarwellBoeing(
  347. int & nnz,
  348. int & num_rows,
  349. int & num_cols,
  350. std::vector<taucsType> & vals,
  351. std::vector<int> & row_indices,
  352. std::vector<int> & column_pointers);
  353. #ifdef PRINTMODE
  354. // Print the matrix in IJV form
  355. void PrintIJV();
  356. #endif
  357. protected:
  358. #ifndef NO_TAUCS
  359. // Will create ATA matrix and AT matrix (in ccs format).
  360. void CreateATA();
  361. // Will create A matrix (in ccs format)
  362. void CreateA();
  363. void ClearFactorATA();
  364. void ClearFactorA();
  365. void ClearMatricesATA(); // clears m_A, m_ATA, m_AT
  366. void ClearMatricesA(); // clears the m_A matrix
  367. #endif
  368. };
  369. #ifdef PRINTMODE
  370. #include <cstdio>
  371. inline void SparseSolver::PrintIJV(){
  372. std::map<int,taucsType>::iterator it;
  373. for (int c = 0; c < m_numCols; ++c)
  374. {
  375. it = m_colsA[c].begin();
  376. while (it != m_colsA[c].end())
  377. {
  378. printf("%d %d %g\n",it->first,c, it->second);
  379. ++it;
  380. }
  381. }
  382. }
  383. #endif
  384. inline void SparseSolver::ClearObject() {
  385. #ifndef NO_TAUCS
  386. ClearFactorATA();
  387. ClearFactorA();
  388. ClearMatricesATA();
  389. ClearMatricesA();
  390. m_ATb.clear();
  391. m_etree = NULL;
  392. #endif
  393. m_numCols = 0;
  394. m_numRows = 0;
  395. m_colsA.clear();
  396. }
  397. // adds a new entry to the sparse matrix A
  398. // i and j are 0-based
  399. // if the A^T A matrix had been factored, this will destroy the factor
  400. inline void SparseSolver::AddIJV(const int i, const int j, const taucsType v) {
  401. #ifndef NO_TAUCS
  402. ClearFactorATA();
  403. ClearFactorA();
  404. ClearMatricesATA();
  405. ClearMatricesA();
  406. #endif
  407. m_colsA[j][i] = v;
  408. // update number of rows
  409. if ((i+1) > m_numRows)
  410. m_numRows = i+1;
  411. }
  412. // updates the entry in A by adding the value v to the current value
  413. // i and j are 0-based
  414. // if the A^T A matrix had been factored, this will destroy the factor
  415. inline void SparseSolver::AddToIJV(const int i, const int j, const taucsType v) {
  416. #ifndef NO_TAUCS
  417. ClearFactorATA();
  418. ClearFactorA();
  419. ClearMatricesATA();
  420. ClearMatricesA();
  421. #endif
  422. // if no such entry existed
  423. if (m_colsA[j].find(i) == m_colsA[j].end())
  424. m_colsA[j][i] = 0;
  425. m_colsA[j][i] += v;
  426. // update number of rows
  427. if ((i+1) > m_numRows)
  428. m_numRows = i+1;
  429. }
  430. #ifndef NO_TAUCS
  431. inline taucs_ccs_matrix * SparseSolver::GetATA_Copy() {
  432. if (! m_ATA) {
  433. CreateATA();
  434. }
  435. return MatrixCopy(m_ATA);
  436. }
  437. #endif
  438. // Implementation
  439. #define PRINTMODE
  440. #ifndef NO_TAUCS
  441. extern "C" {
  442. void chol_update(void *vF, int index, double val,void**vetree);
  443. }
  444. #endif
  445. void SparseSolver::Reset(const int numRows, const int numCols)
  446. {
  447. ClearObject();
  448. m_numRows = numRows;
  449. m_numCols = numCols;
  450. m_colsA.resize(m_numCols);
  451. }
  452. #ifndef NO_TAUCS
  453. // Will create A^T A and its factorization, as well as store A^T
  454. // returns true on success, false otherwise
  455. bool SparseSolver::FactorATA() {
  456. if (m_SPD)
  457. return FactorA();
  458. ClearFactorATA();
  459. if (m_ATA == NULL)
  460. CreateATA();
  461. // factorization
  462. int rc = taucs_linsolve(m_ATA, &m_factorATA,0,NULL,NULL,SIVANfactor,SIVANopt_arg);
  463. if (rc != TAUCS_SUCCESS)
  464. return false;
  465. return true;
  466. }
  467. // Will create ATA matrix and AT matrix.
  468. // returns true on success, false otherwise
  469. void SparseSolver::CreateATA() {
  470. if (m_A == NULL)
  471. CreateA();
  472. ClearMatricesATA();
  473. if (m_SPD) {
  474. // don't need to multiply because m_A is invertible and symmetric
  475. return;
  476. }
  477. else {
  478. m_AT = MatrixTranspose(m_A);
  479. // Multiply to get ATA:
  480. m_ATA = Mul2NonSymmMatSymmResult(m_AT, m_A);
  481. }
  482. }
  483. // Will create A matrix (in ccs format)
  484. void SparseSolver::CreateA() {
  485. ClearMatricesA();
  486. if (m_SPD)
  487. m_A = CreateTaucsMatrixFromColumns(m_colsA, m_numRows, TAUCS_DOUBLE|TAUCS_SYMMETRIC|TAUCS_LOWER);
  488. else
  489. m_A = CreateTaucsMatrixFromColumns(m_colsA, m_numRows, TAUCS_DOUBLE);
  490. }
  491. // Will create *symbolic* factorization of ATA and return it; returns NULL on failure
  492. void * SparseSolver::SymbolicFactorATA() {
  493. if (m_SPD) {
  494. if (m_A == NULL)
  495. CreateA();
  496. return taucs_ccs_factor_llt_symbolic(m_A);
  497. }
  498. else {
  499. if (m_ATA == NULL)
  500. CreateATA();
  501. return taucs_ccs_factor_llt_symbolic(m_ATA);
  502. }
  503. }
  504. // Will create the actual numerical factorization of the present ATA matrix
  505. // with the same non-zero pattern as created by SymbolicFactorATA()
  506. bool SparseSolver::FactorATA_UseSymbolic(void * symbFactor,
  507. taucs_ccs_matrix ** PAP,
  508. int * perm,
  509. int * invperm)
  510. {
  511. if (m_SPD) {
  512. if (m_A == NULL)
  513. CreateA();
  514. *PAP = taucs_ccs_permute_symmetrically(m_A, perm, invperm);
  515. }
  516. else {
  517. if (m_ATA == NULL)
  518. CreateATA();
  519. *PAP = taucs_ccs_permute_symmetrically(m_ATA, perm, invperm);
  520. }
  521. // compute numerical factorization
  522. if (taucs_ccs_factor_llt_numeric(*PAP, symbFactor) != 0) {
  523. return false;
  524. }
  525. else {
  526. return true;
  527. }
  528. }
  529. // Will create A and its factorization. If A is spd Cholesky factor, otherwise LU
  530. // returns true on success, false otherwise
  531. // Assumes A is square and invertible
  532. bool SparseSolver::FactorA() {
  533. ClearFactorA();
  534. if (m_A == NULL)
  535. CreateA();
  536. // factorization
  537. int rc;
  538. if (m_SPD)
  539. rc = taucs_linsolve(m_A, &m_factorA,0,NULL,NULL,SIVANfactor,SIVANopt_arg);
  540. else
  541. rc = taucs_linsolve(m_A, &m_factorA,0,NULL,NULL,SIVANfactorLU,SIVANopt_arg);
  542. if (rc != TAUCS_SUCCESS)
  543. return false;
  544. return true;
  545. }
  546. // Solves the normal equations for Ax = b, namely A^T A x = A^T b
  547. // it is assumed that enough space is allocated in x
  548. // Uses the factorization provided in factor
  549. // numRhs should be the the number of right-hand sides stored in b (and respectively,
  550. // there should be enough space allocated in the solution vector x)
  551. // returns true on success, false otherwise
  552. bool SparseSolver::SolveATA_UseFactor(void * factor,
  553. taucs_ccs_matrix * PAP,
  554. int * perm,
  555. int * invperm,
  556. const taucsType * b, taucsType * x, const int numRhs) {
  557. if (factor == NULL) {
  558. return false;
  559. }
  560. if (! m_SPD) {
  561. // prepare right-hand side
  562. if ((int)m_ATb.size() != m_numCols*numRhs)
  563. m_ATb.resize(m_numCols*numRhs);
  564. // multiply right-hand side
  565. for (int i = 0; i < numRhs; ++i) {
  566. MulMatrixVector(m_AT, b + i*m_numRows, (taucsType *)&(m_ATb.front()) + i*m_numCols);
  567. }
  568. }
  569. // solve the system:
  570. std::vector<taucsType> PB(m_numCols*numRhs), PX(m_numCols*numRhs);
  571. // permute rhs
  572. for (int c = 0; c < numRhs; ++c) {
  573. taucsType * curPB = &PB[0] + c*m_numCols;
  574. const taucsType * curB = (m_SPD)? (b + c*m_numCols) : (&(m_ATb.front()) + c*m_numCols);
  575. for (int i=0; i<m_numCols; ++i)
  576. curPB[i] = curB[perm[i]];
  577. }
  578. // solve by back-substitution
  579. int rc;
  580. for (int c = 0; c < numRhs; ++c) {
  581. rc = taucs_supernodal_solve_llt(factor, &PX[0] + c*m_numCols, &PB[0] + c*m_numCols);
  582. if (rc != TAUCS_SUCCESS) {
  583. return false;
  584. }
  585. }
  586. // re-permute x
  587. for (int c = 0; c < numRhs; ++c) {
  588. taucsType * curX = x + c*m_numCols;
  589. taucsType * curPX = &PX[0] + c*m_numCols;
  590. for (int i=0; i<m_numCols; ++i)
  591. curX[i] = curPX[invperm[i]];
  592. }
  593. return true;
  594. }
  595. // Solves the normal equations for Ax = b, namely A^T A x = A^T b
  596. // it is assumed that enough space is allocated in x
  597. // If a factorization of A^T A exists, it will be used, otherwise it will be created
  598. // numRhs should be the the number of right-hand sides stored in b (and respectively,
  599. // there should be enough space allocated in the solution vector x)
  600. // returns true on success, false otherwise
  601. bool SparseSolver::SolveATA(const taucsType * b, taucsType * x, const int numRhs) {
  602. if (m_SPD) {
  603. return SolveA(b, x, numRhs);
  604. }
  605. else {
  606. if (m_factorATA == NULL) {
  607. bool rc = FactorATA();
  608. if (!rc)
  609. return false;
  610. }
  611. }
  612. // prepare right-hand side
  613. if ((int)m_ATb.size() != m_numCols*numRhs)
  614. m_ATb.resize(m_numCols*numRhs);
  615. // multiply right-hand side
  616. for (int i = 0; i < numRhs; ++i) {
  617. MulMatrixVector(m_AT, b + i*m_numRows, (taucsType *)&(m_ATb.front()) + i*m_numCols);
  618. }
  619. int rc;
  620. // solve the system
  621. rc = taucs_linsolve(m_ATA,
  622. &m_factorATA,
  623. numRhs,
  624. x,
  625. (taucsType *)&(m_ATb.front()),
  626. SIVANsolve,
  627. SIVANopt_arg);
  628. return (rc == TAUCS_SUCCESS);
  629. }
  630. // Same as SolveATA only that this solves the actual system Ax = b
  631. // It is assumed that A is rectangular and invertible
  632. bool SparseSolver::SolveA(const taucsType * b, taucsType * x, const int numRhs) {
  633. if (m_factorA == NULL)
  634. if (!FactorA())
  635. return false;
  636. // solve the system
  637. int rc = taucs_linsolve(m_A,
  638. &m_factorA,
  639. numRhs,
  640. x,
  641. (void *)b,
  642. SIVANsolve,
  643. SIVANopt_arg);
  644. return (rc == TAUCS_SUCCESS);
  645. }
  646. // The version of SolveATA with 3 right-hand sides
  647. // returns true on success, false otherwise
  648. bool SparseSolver::SolveATA3(const taucsType * bx, const taucsType * by, const taucsType * bz,
  649. taucsType * x, taucsType * y, taucsType * z)
  650. {
  651. if (m_factorATA == NULL) {
  652. bool rc = FactorATA();
  653. if (!rc)
  654. return false;
  655. }
  656. // prepare right-hand side
  657. if ((int)m_ATb.size() != m_numCols*3)
  658. m_ATb.resize(m_numCols*3);
  659. // multiply right-hand side
  660. MulMatrixVector(m_AT, bx, (taucsType *)&(m_ATb.front()));
  661. MulMatrixVector(m_AT, by, (taucsType *)&(m_ATb.front()) + m_numCols);
  662. MulMatrixVector(m_AT, bz, (taucsType *)&(m_ATb.front()) + 2*m_numCols);
  663. // solve the system
  664. int rc = taucs_linsolve(m_ATA,
  665. &m_factorATA,
  666. 1,
  667. x,
  668. (taucsType *)&(m_ATb.front()),
  669. SIVANsolve,
  670. SIVANopt_arg);
  671. if (rc != TAUCS_SUCCESS)
  672. return false;
  673. rc = taucs_linsolve(m_ATA,
  674. &m_factorATA,
  675. 1,
  676. y,
  677. (taucsType *)&(m_ATb.front()) + m_numCols,
  678. SIVANsolve,
  679. SIVANopt_arg);
  680. if (rc != TAUCS_SUCCESS)
  681. return false;
  682. rc = taucs_linsolve(m_ATA,
  683. &m_factorATA,
  684. 1,
  685. z,
  686. (taucsType *)&(m_ATb.front()) + 2*m_numCols,
  687. SIVANsolve,
  688. SIVANopt_arg);
  689. return (rc == TAUCS_SUCCESS);
  690. }
  691. // The version of SolveATA with 2 right-hand sides
  692. // returns true on success, false otherwise
  693. bool SparseSolver::SolveATA2(const taucsType * bx, const taucsType * by,
  694. taucsType * x, taucsType * y)
  695. {
  696. if (m_factorATA == NULL) {
  697. bool rc = FactorATA();
  698. if (!rc)
  699. return false;
  700. }
  701. // prepare right-hand side
  702. if ((int)m_ATb.size() != m_numCols*2)
  703. m_ATb.resize(m_numCols*2);
  704. // multiply right-hand side
  705. MulMatrixVector(m_AT, bx, (taucsType *)&(m_ATb.front()));
  706. MulMatrixVector(m_AT, by, (taucsType *)&(m_ATb.front()) + m_numCols);
  707. // solve the system
  708. int rc = taucs_linsolve(m_ATA,
  709. &m_factorATA,
  710. 1,
  711. x,
  712. (taucsType *)&(m_ATb.front()),
  713. SIVANsolve,
  714. SIVANopt_arg);
  715. if (rc != TAUCS_SUCCESS)
  716. return false;
  717. rc = taucs_linsolve(m_ATA,
  718. &m_factorATA,
  719. 1,
  720. y,
  721. (taucsType *)&(m_ATb.front()) + m_numCols,
  722. SIVANsolve,
  723. SIVANopt_arg);
  724. return (rc == TAUCS_SUCCESS);
  725. }
  726. void SparseSolver::ClearFactorATA() {
  727. // release the factor
  728. taucs_linsolve(NULL,&m_factorATA,0, NULL,NULL,SIVANfactor,SIVANopt_arg);
  729. m_factorATA = NULL;
  730. m_etree = NULL;
  731. }
  732. void SparseSolver::ClearFactorA() {
  733. // release the factor
  734. if (m_SPD)
  735. taucs_linsolve(NULL,&m_factorA,0, NULL,NULL,SIVANfactor,SIVANopt_arg);
  736. else
  737. taucs_linsolve(NULL,&m_factorA,0, NULL,NULL,SIVANfactorLU,SIVANopt_arg);
  738. m_factorA = NULL;
  739. }
  740. void SparseSolver::ClearMatricesATA() {
  741. // free the matrices
  742. taucs_free(m_AT);
  743. m_AT = NULL;
  744. taucs_free(m_ATA);
  745. m_ATA = NULL;
  746. }
  747. void SparseSolver::ClearMatricesA() {
  748. // free the matrices
  749. taucs_free(m_A);
  750. m_A = NULL;
  751. }
  752. #endif
  753. void SparseSolver::AddMatrix(SparseSolver & B)
  754. {
  755. AddMatrix(0,0,B);
  756. }
  757. void SparseSolver::AddMatrix(const int i, const int j, SparseSolver & B)
  758. {
  759. std::map<int,taucsType>::iterator it;
  760. for (int c = 0; c < B.m_numCols; ++c)
  761. {
  762. it = B.m_colsA[c].begin();
  763. while (it != B.m_colsA[c].end())
  764. {
  765. // because AddToIJV is not O(1), this algorithm is O(Bnnz * Amaxrows),
  766. // ideally it would be O(Bnnz)
  767. AddToIJV(i+it->first,j+c,it->second);
  768. ++it;
  769. }
  770. }
  771. }
  772. bool SparseSolver::IsSymmetric()
  773. {
  774. if(m_SPD)
  775. {
  776. return true;
  777. }
  778. if(GetNumColumns() != GetNumRows())
  779. {
  780. return false;
  781. }
  782. // Cheapskate way to test if symmetric
  783. SparseSolver AT;
  784. if(!Transpose(AT))
  785. {
  786. return false;
  787. }
  788. // loop over columns
  789. std::map<int,taucsType>::iterator it;
  790. std::map<int,taucsType>::iterator ATit;
  791. for (int c = 0; c < m_numCols; ++c)
  792. {
  793. it = m_colsA[c].begin();
  794. ATit = AT.m_colsA[c].begin();
  795. while (it != m_colsA[c].end() && ATit !=AT.m_colsA[c].end())
  796. {
  797. if( it->first != ATit->first || it->second != ATit->second)
  798. {
  799. return false;
  800. }
  801. ++it;
  802. ++ATit;
  803. }
  804. }
  805. return true;
  806. }
  807. #ifndef NO_TAUCS
  808. // allows to add an anchored vertex without destroying the factor, if there was one
  809. // i is the anchor's number (i.e. the index of the mesh vertex that is anchored is i)
  810. // w is the weight of the anchor in the original Ax=b system. HAS TO BE POSITIVE!!
  811. // if there was no factor for A^T A, this will simply add an anchor row to the Ax=b system
  812. // if there was a factor, the factor will be updated, approximately at the cost of
  813. // a single solve.
  814. void SparseSolver::AddAnchor(const int i, const taucsType w) {
  815. if (m_SPD) {
  816. // update the columns
  817. if (m_colsA[i].find(i) == m_colsA[i].end())
  818. m_colsA[i][i] = w*w;
  819. else
  820. m_colsA[i][i] += w*w;
  821. if (m_factorA != NULL) {
  822. // the matrix is SPD so we update the factor of A
  823. chol_update(m_factorA, i, w, &m_etree);
  824. // update the matrix
  825. m_A->taucs_values[ m_A->colptr[i] ] += w*w;
  826. }
  827. }
  828. else {
  829. m_colsA[i][m_numRows] = w;
  830. m_numRows++;
  831. if (m_factorATA != NULL) {
  832. // update the ATA factor
  833. chol_update(m_factorATA, i, w, &m_etree);
  834. // update ATA
  835. m_ATA->taucs_values[ m_ATA->colptr[i] ] += w*w;
  836. // update A and AT (for multiplying rhs)
  837. CreateA();
  838. taucs_free(m_AT);
  839. m_AT = MatrixTranspose(m_A);
  840. }
  841. }
  842. }
  843. #endif
  844. void SparseSolver::MultiplyMatrixVector(const taucsType * v, taucsType * result, const int numCols) const {
  845. // make result all zero
  846. memset(result, 0, m_numRows * numCols * sizeof(taucsType));
  847. std::map<int,taucsType>::const_iterator iter;
  848. int offset_v;
  849. int offset_r;
  850. if (m_SPD) { // the matrix is symmetric
  851. for (int c = 0; c < numCols; ++c) {
  852. offset_v = m_numCols*c;
  853. for (int col = 0; col < m_numCols; ++col) {
  854. // going over column col of the matrix, multiplying
  855. // it by v[col] and setting the appropriate values
  856. // of vector result; also mirroring the other triangle
  857. for (iter = m_colsA[col].begin(); iter->first < col; ++iter) {
  858. result[iter->first + offset_v] += v[col + offset_v]*(iter->second);
  859. // mirroring
  860. result[col + offset_v] += v[iter->first + offset_v]*(iter->second);
  861. }
  862. if (iter->first == col)
  863. result[iter->first + offset_v] += v[col + offset_v]*(iter->second);
  864. }
  865. }
  866. }
  867. else {
  868. for (int c = 0; c < numCols; ++c) {
  869. offset_v = m_numCols*c;
  870. offset_r = m_numRows*c;
  871. for (int col = 0; col < m_numCols; ++col) {
  872. // going over column col of the matrix, multiplying
  873. // it by v[col] and setting the appropriate values
  874. // of vector result
  875. for (iter = m_colsA[col].begin(); iter != m_colsA[col].end(); ++iter) {
  876. result[iter->first + offset_r] += v[col + offset_v]*(iter->second);
  877. }
  878. }
  879. }
  880. }
  881. }
  882. // Multiplies the matrix by diagonal matrix D from the left, stores the result
  883. // in the columns of res
  884. void SparseSolver::MultiplyDiagMatrixMatrix(const taucsType * D, SparseSolver & res) const {
  885. res = SparseSolver(m_numRows, m_numCols, false);
  886. std::map<int,taucsType>::const_iterator iterA;
  887. std::map<int,taucsType>::iterator iterRes;
  888. res.m_colsA = m_colsA;
  889. if (m_SPD) {
  890. for (int col = 0; col < m_numCols; ++col) {
  891. iterA = m_colsA[col].begin();
  892. iterRes = res.m_colsA[col].begin();
  893. for ( ; iterA != m_colsA[col].end() && iterA->first <= col; ++iterA, ++iterRes) {
  894. iterRes->second = (iterA->second) * D[iterA->first];
  895. // mirroring
  896. res.m_colsA[iterA->first][col] = (iterA->second) * D[col];
  897. }
  898. }
  899. }
  900. else {
  901. for (int col = 0; col < m_numCols; ++col) {
  902. iterA = m_colsA[col].begin();
  903. iterRes = res.m_colsA[col].begin();
  904. for ( ; iterA != m_colsA[col].end(); ++iterA, ++iterRes) {
  905. iterRes->second = (iterA->second) * D[iterA->first];
  906. }
  907. }
  908. }
  909. }
  910. // Multiplies the matrix by the given matrix B from the right
  911. // and stores the result in the columns of res
  912. // isSPD tells us whether the result should be SPD or not
  913. // retuns false if the dimensions didn't match (in such case res is unaltered), otherwise true
  914. bool SparseSolver::MultiplyMatrixRight(const SparseSolver & B, SparseSolver & res,const bool isSPD) const {
  915. // for now ignore the option that one of the involved matrices is symmetric and doesn't have
  916. // stored under-diagonal values in m_colsA
  917. // we assume both matrices have all the values in m_colsA
  918. // (m x n) * (n x k)
  919. int m = m_numRows;
  920. int n = m_numCols;
  921. int k = B.m_numCols;
  922. if (B.m_numRows != n)
  923. return false;
  924. std::map<int,taucsType>::const_iterator iterBi, iterA;
  925. std::map<int,taucsType>::iterator iterRes;
  926. int rowInd;
  927. taucsType BiVal;
  928. res = SparseSolver(m, k, isSPD);
  929. for (int i = 0; i < k; ++i) { // go over the columns of res; res(i) = A*B(i)
  930. for (iterBi = B.m_colsA[i].begin(); iterBi != B.m_colsA[i].end(); ++iterBi) { // go over column B(i)
  931. // iterBi->second multiplies column A(iterBi->first)
  932. BiVal = iterBi->second;
  933. rowInd = iterBi->first;
  934. for (iterA = m_colsA[rowInd].begin(); iterA != m_colsA[rowInd].end(); ++iterA) { // go over column of A
  935. iterRes = res.m_colsA[i].find(iterA->first);
  936. if (iterRes == res.m_colsA[i].end()) // first occurence of this row number
  937. res.m_colsA[i][iterA->first] = (iterA->second)*BiVal;
  938. else
  939. iterRes->second += (iterA->second)*BiVal;
  940. }
  941. }
  942. }
  943. return true;
  944. }
  945. // Transposes the matrix
  946. // and stores the result in the columns of res
  947. bool SparseSolver::Transpose(SparseSolver & res) const {
  948. res = SparseSolver(m_numCols, m_numRows, m_SPD);
  949. // if the matrix was symmetric to begin with, just copy the columns
  950. if (m_SPD) {
  951. res.m_colsA = m_colsA;
  952. return true;
  953. }
  954. // else need to transpose
  955. std::map<int,taucsType>::const_iterator iterA;
  956. for (int i=0; i < m_numCols; ++i) {
  957. for (iterA = m_colsA[i].begin(); iterA != m_colsA[i].end(); ++iterA) {
  958. res.m_colsA[iterA->first][i] = iterA->second;
  959. }
  960. }
  961. return true;
  962. }
  963. // will remove the rows startInd-endInd (including ends, zero-based) from the matrix
  964. // will discard any factors
  965. bool SparseSolver::DeleteRowRange(const int startInd, const int endInd) {
  966. if (startInd < 0 || endInd >= m_numRows || startInd > endInd)
  967. return false;
  968. #ifndef NO_TAUCS
  969. ClearFactorATA();
  970. ClearFactorA();
  971. ClearMatricesATA();
  972. ClearMatricesA();
  973. #endif
  974. std::map<int,taucsType>::iterator it;
  975. std::map<int,taucsType>::iterator tempIt;
  976. int diff = endInd - startInd + 1;
  977. for (int c = 0; c < m_numCols; ++c) {
  978. it = m_colsA[c].begin();
  979. while (it != m_colsA[c].end()) {
  980. if (it->first >= startInd && it->first <= endInd) { // row that should be erased
  981. m_colsA[c].erase(it++);
  982. } else {
  983. if (it->first > endInd) {// row number must be updated
  984. m_colsA[c][it->first - diff] = it->second;
  985. m_colsA[c].erase(it++);
  986. }
  987. else
  988. ++it;
  989. }
  990. }
  991. }
  992. m_numRows -= diff;
  993. m_SPD = false;
  994. return true;
  995. }
  996. bool SparseSolver::MultiplyRows(const int startInd, const int endInd, const taucsType val)
  997. {
  998. if (startInd < 0 || endInd >= m_numRows || startInd > endInd) return false;
  999. #ifndef NO_TAUCS
  1000. ClearFactorATA();
  1001. ClearFactorA();
  1002. ClearMatricesATA();
  1003. ClearMatricesA();
  1004. #endif
  1005. std::map<int,taucsType>::iterator it;
  1006. for (int c = 0; c < m_numCols; ++c)
  1007. {
  1008. it = m_colsA[c].begin();
  1009. while (it != m_colsA[c].end())
  1010. {
  1011. if (it->first >= startInd && it->first <= endInd) // row that should be multiplied
  1012. {
  1013. it->second *= val;
  1014. }
  1015. it++;
  1016. }
  1017. }
  1018. return true;
  1019. }
  1020. // will remove the columns startInd-endInd (including ends, zero-based) from the matrix
  1021. // will discard any factors
  1022. bool SparseSolver::DeleteColumnRange(const int startInd, const int endInd) {
  1023. if (startInd < 0 || endInd >= m_numCols || startInd > endInd)
  1024. return false;
  1025. #ifndef NO_TAUCS
  1026. ClearFactorATA();
  1027. ClearFactorA();
  1028. ClearMatricesATA();
  1029. ClearMatricesA();
  1030. #endif
  1031. m_colsA.erase(m_colsA.begin() + startInd, m_colsA.begin() + (endInd+1));
  1032. m_numCols -= (endInd - startInd + 1);
  1033. return true;
  1034. }
  1035. // copies columns startInd through endInd (including, zero-based) from the matrix to res matrix
  1036. // previous data in res, including factors, is erased.
  1037. bool SparseSolver::CopyColumnRange(const int startInd, const int endInd, SparseSolver & res) const {
  1038. if (startInd < 0 || endInd >= m_numCols || startInd > endInd)
  1039. return false;
  1040. int k = endInd - startInd + 1;
  1041. res = SparseSolver(m_numRows, k, false);
  1042. for (int c = startInd; c <= endInd; ++c)
  1043. res.m_colsA[c - startInd] = m_colsA[c];
  1044. return true;
  1045. }
  1046. // copies rows startInd through endInd (including, zero-based) from the matrix to res matrix
  1047. // previous data in res, including factors, is erased.
  1048. bool SparseSolver::CopyRowRange(const int startInd, const int endInd, SparseSolver & res) const {
  1049. if (startInd < 0 || endInd >= m_numRows || startInd > endInd)
  1050. return false;
  1051. res.m_colsA = m_colsA;
  1052. for (int c = 0; c < m_numCols; ++c) {
  1053. std::map<int,taucsType>::iterator it = res.m_colsA[c].begin();
  1054. std::map<int,taucsType>::iterator tempIt;
  1055. for ( ; it != res.m_colsA[c].end(); ++it) {
  1056. if (it->first < startInd || it->first > endInd) {
  1057. tempIt = it;
  1058. it++;
  1059. res.m_colsA[c].erase(tempIt);
  1060. continue;
  1061. }
  1062. }
  1063. }
  1064. return true;
  1065. }
  1066. void SparseSolver::MultiplyMatrixScalar(const taucsType val)
  1067. {
  1068. #ifndef NO_TAUCS
  1069. ClearFactorATA();
  1070. ClearFactorA();
  1071. ClearMatricesATA();
  1072. ClearMatricesA();
  1073. #endif
  1074. //Over all entries
  1075. for (int c=0;c<m_numCols;c++)
  1076. {
  1077. for(std::map< int, taucsType >::iterator it=m_colsA[c].begin();it!=m_colsA[c].end();it++)
  1078. {
  1079. it->second *= val; //Multiply
  1080. }
  1081. }
  1082. }
  1083. void SparseSolver::IdentityMinusMatrix()
  1084. {
  1085. #ifndef NO_TAUCS
  1086. ClearFactorATA();
  1087. ClearFactorA();
  1088. ClearMatricesATA();
  1089. ClearMatricesA();
  1090. #endif
  1091. //Over the diagonal
  1092. for (int c=0;c<m_numCols;c++)
  1093. {
  1094. std::map< int, taucsType >::iterator it = m_colsA[c].find(c);
  1095. if (it != m_colsA[c].end())
  1096. {
  1097. it->second = 1.0 - it->second;
  1098. }
  1099. else
  1100. {
  1101. AddIJV(c, c, 1.0);
  1102. }
  1103. }
  1104. }
  1105. void SparseSolver::IdentityPlusMatrix()
  1106. {
  1107. #ifndef NO_TAUCS
  1108. ClearFactorATA();
  1109. ClearFactorA();
  1110. ClearMatricesATA();
  1111. ClearMatricesA();
  1112. #endif
  1113. //Over the diagonal
  1114. for (int c=0;c<m_numCols;c++)
  1115. {
  1116. std::map< int, taucsType >::iterator it = m_colsA[c].find(c);
  1117. if (it != m_colsA[c].end())
  1118. {
  1119. it->second += 1.0;
  1120. }
  1121. else
  1122. {
  1123. AddIJV(c, c, 1.0);
  1124. }
  1125. }
  1126. }
  1127. //
  1128. // Memory: 1*spliced = 1*O(column_indices.size * numRows)
  1129. // Runtime: O(size of spliced) = O(column_indices.size * numRows)
  1130. bool SparseSolver::SpliceColumns(
  1131. const std::vector<size_t> column_indices,
  1132. SparseSolver & res) const
  1133. {
  1134. // Check that all indices in column_indices are valid
  1135. for(
  1136. std::vector<size_t>::const_iterator old_index = column_indices.begin();
  1137. old_index != column_indices.end();
  1138. old_index++)
  1139. {
  1140. if((*old_index) >= (size_t)m_numCols)
  1141. {
  1142. return false;
  1143. }
  1144. }
  1145. // create result
  1146. res = SparseSolver(m_numRows,column_indices.size(),false);
  1147. // splice (and reorder) columns
  1148. size_t new_index = 0;
  1149. for(
  1150. std::vector<size_t>::const_iterator old_index = column_indices.begin();
  1151. old_index != column_indices.end();
  1152. old_index++,new_index++)
  1153. {
  1154. res.m_colsA[new_index] = m_colsA[(*old_index)];
  1155. }
  1156. return true;
  1157. }
  1158. // Cheating way of handling SpliceRows.
  1159. // SpliceRows = Transpose -> SpliceColumns -> Transpose
  1160. //
  1161. // Sparse (not dense), but not perfect implementation:
  1162. // Memory: 1*original + 2*spliced
  1163. // Runtime: O(
  1164. // transpose of original +
  1165. // splicecolumns of original +
  1166. // transpose of spliced)
  1167. // = O(
  1168. // size of original +
  1169. // size of spliced
  1170. // size of spliced)
  1171. // = O( size of original )
  1172. //
  1173. // A good implementation should be:
  1174. // Memory: 1*spliced = 1*O(row_indices.size * numCols)
  1175. // Runtime: O(size of spliced) = O(row_indices.size * numCols)
  1176. bool SparseSolver::SpliceRows(
  1177. const std::vector<size_t> row_indices,
  1178. SparseSolver & res) const
  1179. {
  1180. // Check that all indices in row_indices are valid
  1181. for(
  1182. std::vector<size_t>::const_iterator old_index = row_indices.begin();
  1183. old_index != row_indices.end();
  1184. old_index++)
  1185. {
  1186. if((*old_index) >= (size_t)m_numRows)
  1187. {
  1188. return false;
  1189. }
  1190. }
  1191. // transpose (now columns are rows, rows are columns)
  1192. SparseSolver transpose;
  1193. if(!Transpose(transpose))
  1194. {
  1195. return false;
  1196. }
  1197. // Splice columns of transpose
  1198. SparseSolver spliced_transpose;
  1199. if(!transpose.SpliceColumns(row_indices, spliced_transpose))
  1200. {
  1201. return false;
  1202. }
  1203. // Transpose again (rows back to rows, columns back to columns)
  1204. if(!spliced_transpose.Transpose(res))
  1205. {
  1206. return false;
  1207. }
  1208. return true;
  1209. }
  1210. bool SparseSolver::SpliceColumnsThenRows(
  1211. const std::vector<size_t> column_indices,
  1212. const std::vector<size_t> row_indices,
  1213. SparseSolver & res) const
  1214. {
  1215. SparseSolver temp;
  1216. if(!SpliceColumns(column_indices,temp))
  1217. {
  1218. return false;
  1219. }
  1220. if(!temp.SpliceRows(row_indices,res))
  1221. {
  1222. return false;
  1223. }
  1224. return true;
  1225. }
  1226. bool SparseSolver::VerticalConcatenation(
  1227. SparseSolver & other,
  1228. SparseSolver & res)
  1229. {
  1230. // if other if skinnier than we'll padd with zeros
  1231. if(other.GetNumColumns() > m_numCols)
  1232. {
  1233. return false;
  1234. }
  1235. res = SparseSolver(m_numRows+other.GetNumRows(), m_numCols,false);
  1236. // copy all columns from this matrix to result
  1237. res.m_colsA = m_colsA;
  1238. // copy all entries in other to result with rows offset by "m_numRows"
  1239. std::map<int,taucsType>::iterator it;
  1240. for (int c = 0; c < other.m_numCols; ++c)
  1241. {
  1242. it = other.m_colsA[c].begin();
  1243. while (it != other.m_colsA[c].end())
  1244. {
  1245. res.AddIJV(it->first+m_numRows,c,it->second);
  1246. ++it;
  1247. }
  1248. }
  1249. return true;
  1250. }
  1251. void SparseSolver::ConvertToIJV(
  1252. std::vector<int> & row_indices,
  1253. std::vector<int> & column_indices,
  1254. std::vector<taucsType> & vals)
  1255. {
  1256. // Get number of non-zeros
  1257. size_t nnz = 0;
  1258. // loop over columns
  1259. for (int c = 0; c < m_numCols; ++c)
  1260. {
  1261. // add up the number of non-zeros in each column
  1262. nnz += m_colsA[c].size();
  1263. }
  1264. // allocate space in outputs
  1265. vals.resize(nnz);
  1266. row_indices.resize(nnz);
  1267. column_indices.resize(nnz);
  1268. size_t index = 0;
  1269. std::map<int,taucsType>::iterator it;
  1270. // loop over columns
  1271. for (int c = 0; c < m_numCols; ++c)
  1272. {
  1273. // loop over rows
  1274. it = m_colsA[c].begin();
  1275. while (it != m_colsA[c].end())
  1276. {
  1277. row_indices[index] = it->first;
  1278. column_indices[index] = c;
  1279. vals[index] = it->second;
  1280. // increment index
  1281. index++;
  1282. ++it;
  1283. }
  1284. }
  1285. }
  1286. void SparseSolver::ConvertLowerTriangleToIJV(
  1287. std::vector<int> & row_indices,
  1288. std::vector<int> & column_indices,
  1289. std::vector<taucsType> & vals)
  1290. {
  1291. // Get number of ALL non-zeros
  1292. size_t nnz = 0;
  1293. // loop over columns
  1294. for (int c = 0; c < m_numCols; ++c)
  1295. {
  1296. // add up the number of non-zeros in each column
  1297. nnz += m_colsA[c].size();
  1298. }
  1299. // allocate (too much) space in outputs
  1300. vals.resize(nnz);
  1301. row_indices.resize(nnz);
  1302. column_indices.resize(nnz);
  1303. size_t index = 0;
  1304. std::map<int,taucsType>::iterator it;
  1305. // loop over columns
  1306. for (int c = 0; c < m_numCols; ++c)
  1307. {
  1308. // loop over rows
  1309. it = m_colsA[c].begin();
  1310. while (it != m_colsA[c].end())
  1311. {
  1312. // if row is less than or equal to column then we're in the lower
  1313. // triangle
  1314. if(it->first>= c)
  1315. {
  1316. row_indices[index] = it->first;
  1317. column_indices[index] = c;
  1318. vals[index] = it->second;
  1319. // increment index
  1320. index++;
  1321. }
  1322. ++it;
  1323. }
  1324. }
  1325. // resize to actually number of non-zeros in lower triangle
  1326. vals.resize(index);
  1327. row_indices.resize(index);
  1328. column_indices.resize(index);
  1329. }
  1330. void SparseSolver::ConvertToHarwellBoeing(
  1331. int & nnz,
  1332. int & num_rows,
  1333. int & num_cols,
  1334. std::vector<taucsType> & vals,
  1335. std::vector<int> & row_indices,
  1336. std::vector<int> & column_pointers)
  1337. {
  1338. num_rows = m_numRows;
  1339. num_cols = m_numCols;
  1340. nnz = 0;
  1341. // loop over columns
  1342. for (int c = 0; c < m_numCols; ++c)
  1343. {
  1344. // add up the number of non-zeros in each column
  1345. nnz += m_colsA[c].size();
  1346. }
  1347. vals.resize(nnz);
  1348. row_indices.resize(nnz);
  1349. column_pointers.resize(num_cols+1);
  1350. // loop over columns
  1351. int column_pointer = 0;
  1352. int val_index = 0;
  1353. std::map<int,taucsType>::iterator it;
  1354. int c;
  1355. for (c = 0; c < m_numCols; ++c)
  1356. {
  1357. column_pointers[c] = column_pointer;
  1358. column_pointer += m_colsA[c].size();
  1359. // over rows in this column
  1360. it = m_colsA[c].begin();
  1361. while (it != m_colsA[c].end())
  1362. {
  1363. vals[val_index] = it->second;
  1364. row_indices[val_index] = it->first;
  1365. val_index++;
  1366. ++it;
  1367. }
  1368. }
  1369. // by convention column_pointers[num_cols] = nnz
  1370. column_pointers[c] = column_pointer;
  1371. }