12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601 |
- #define NO_TAUCS
- #ifdef NO_TAUCS
- typedef double taucsType;
- # include <vector>
- # include <map>
- #else
- # include "taucsaddon.h"
- #endif
- class SparseSolver {
- protected:
- // is set to true iff m_A is symmetric positive definite
- bool m_SPD;
-
- #ifndef NO_TAUCS
- taucs_ccs_matrix * m_A;
- taucs_ccs_matrix * m_AT;
- taucs_ccs_matrix * m_ATA;
- #endif
- #ifndef NO_TAUCS
- void * m_factorATA;
- void * m_factorA;
- void * m_etree; // for the factor update
- #endif
-
- // placeholder, so that we don't need to allocate space every time
- // the space is allocated when a factor for ATA is created
- std::vector<taucsType> m_ATb;
- // helper map to create A
- std::vector< std::map<int,taucsType> > m_colsA;
- // the dimensions of the A matrix
- int m_numRows;
- int m_numCols;
- public:
- SparseSolver(const int numRows = 0, const int numCols = 0, const bool isSPD = false)
- :
- m_SPD(isSPD)
- ,
- #ifndef NO_TAUCS
- m_A(NULL)
- , m_AT(NULL)
- , m_ATA(NULL)
- , m_factorATA(NULL)
- , m_factorA(NULL)
- , m_etree(NULL)
- , m_ATb(NULL)
- ,
- #endif
- m_colsA(numCols)
- , m_numRows(numRows)
- , m_numCols(numCols)
- {};
- ~SparseSolver() { ClearObject();}
- //Operators
- public:
- /** Copies the matrix.
- However, factorizations are not copied.
- This is because the factorizations are actually owned by taucs
- and we have to call taucs to release them.
- If we would release them from two different objects,
- we would run into trouble.
- */
- SparseSolver& operator=(const SparseSolver& other)
- {
- //Reset ourselves
- Reset(other.GetNumRows(), other.GetNumColumns());
- //Copy the sparse matrix
- m_colsA = other.m_colsA;
- m_SPD = other.m_SPD;
- m_numRows = other.m_numRows;
- m_numCols = other.m_numCols;
- return *this;
- }
- //Methods
- public:
- ///Resets all internal data structures and sets the new size of this matrix
- void Reset(const int numRows, const int numCols);
- ///Returns the number of rows of the \c A matrix.
- inline int GetNumRows() const {return m_numRows;}
- ///Returns the number of columns of the \c A matrix.
- inline int GetNumColumns() const {return m_numCols;}
- ///Returns the dimensions of the \c A matrix.
- inline void GetAMatrixSize(int & numRows, int & numCols) const
- {
- numRows = m_numRows;
- numCols = m_numCols;
- }
- ///Returns true if no rows or columns are in the matrix.
- inline bool IsEmpty() const {return m_numRows == 0 || m_numCols == 0;}
- ///Clears all data structures.
- void ClearObject();
- // adds a new entry to the sparse matrix A
- // i and j are 0-based
- // if the A^T A matrix had been factored, this will destroy the factor
- void AddIJV(const int i, const int j, const taucsType v);
- // updates the entry in A by adding the value v to the current value
- // i and j are 0-based
- // if the A^T A matrix had been factored, this will destroy the factor
- void AddToIJV(const int i, const int j, const taucsType v);
- // updates the entries in A by adding the values v in B to the current
- // Value
- // if the A^T A matrix had been factored, this will destroy the factor
- void AddMatrix(SparseSolver & B);
- // updates the entries in A by adding the values v in B to the current
- // Value in A offset by (i,j)
- // like matlab's A[i:m,j:n] = B, where [m,n] = size(B);
- // i and j are 0-based
- // if the A^T A matrix had been factored, this will destroy the factor
- void AddMatrix(const int i, const int j, SparseSolver & B);
- ///Removes all entries from the given row.
- ///If the A^T A matrix had been factored, this will destroy the factor.
- inline bool ClearRow(const int iRow)
- {
- if (iRow >= 0 && iRow < m_numRows)
- {
- #ifndef NO_TAUCS
- ClearFactorATA();
- ClearFactorA();
- ClearMatricesATA();
- ClearMatricesA();
- #endif
- //Go over all columns, try to find the respective row and delete it
- for(std::vector< std::map<int,taucsType> >::iterator itCol=m_colsA.begin();itCol!=m_colsA.end();itCol++)
- {
- //Find the row
- std::map<int,taucsType>::iterator itRow = itCol->find(iRow);
- if (itRow != itCol->end())
- {
- itCol->erase(itRow);
- }
- }
- return true;
- }
- return false;
- }
- ///Removes all entries from the given column.
- ///If the A^T A matrix had been factored, this will destroy the factor.
- inline bool ClearColumn(const int iColumn)
- {
- if (iColumn >= 0 && iColumn < m_numCols)
- {
- #ifndef NO_TAUCS
- ClearFactorATA();
- ClearFactorA();
- ClearMatricesATA();
- ClearMatricesA();
- #endif
- m_colsA[iColumn].clear();
- return true;
- }
- return false;
- }
- // Sets the status of a matrix - whether SPD or not
- void SetSPD(bool isSPD) {m_SPD = isSPD;}
- // Return true only if symmetric, automatically true if isSPD flag is
- // set to true, otherwise actually determine if matrix is symmetric
- bool IsSymmetric();
- #ifndef NO_TAUCS
- // allows to add an anchored vertex without destroying the factor, if there was one
- // i is the anchor's number (i.e. the index of the mesh vertex that is anchored is i)
- // w is the weight of the anchor in the original Ax=b system. HAS TO BE POSITIVE!!
- // if there was no factor for A^T A, this will simply add an anchor row to the Ax=b system
- // if there was a factor, the factor will be updated, approximately at the cost of
- // a single solve.
- void AddAnchor(const int i, const taucsType w);
- // Will create A^T A and its factorization, as well as store A^T
- // returns true on success, false otherwise
- bool FactorATA();
- // Will create A and its factorization. If A is spd then Cholesky factor, otherwise LU
- // returns true on success, false otherwise
- // Assumes A is square and invertible
- bool FactorA();
- // Will create *symbolic* factorization of ATA and return it; returns NULL on failure
- void * SymbolicFactorATA();
- taucs_ccs_matrix * GetATA_Copy();
- // Will create the actual numerical factorization of the present ATA matrix
- // with the same non-zero pattern as created by SymbolicFactorATA()
- bool FactorATA_UseSymbolic(void * symbFactor,
- taucs_ccs_matrix ** PAP,
- int * perm,
- int * invperm);
- // Solves the normal equations for Ax = b, namely A^T A x = A^T b
- // it is assumed that enough space is allocated in x
- // Uses the factorization provided in factor
- // numRhs should be the the number of right-hand sides stored in b (and respectively,
- // there should be enough space allocated in the solution vector x)
- // returns true on success, false otherwise
- bool SolveATA_UseFactor(void * factor,
- taucs_ccs_matrix * PAP,
- int * perm,
- int * invperm,
- const taucsType * b, taucsType * x, const int numRhs);
- // Solves the normal equations for Ax = b, namely A^T A x = A^T b
- // it is assumed that enough space is allocated in x
- // If a factorization of A^T A exists, it will be used, otherwise it will be created
- // numRhs should be the the number of right-hand sides stored in b (and respectively,
- // there should be enough space allocated in the solution vector x)
- // returns true on success, false otherwise
- bool SolveATA(const taucsType * b, taucsType * x, const int numRhs);
- // Same as SolveATA only that this solves the actual system Ax = b
- // It is assumed that A is rectangular and invertible
- bool SolveA(const taucsType * b, taucsType * x, const int numRhs);
- // The version of SolveATA with 3 right-hand sides
- // returns true on success, false otherwise
- bool SolveATA3(const taucsType * bx, const taucsType * by, const taucsType * bz,
- taucsType * x, taucsType * y, taucsType * z);
- // The version of SolveATA with 2 right-hand sides
- // returns true on success, false otherwise
- bool SolveATA2(const taucsType * bx, const taucsType * by,
- taucsType * x, taucsType * y);
- #endif
- // Matrix utility routines
- // Stores the result of Matrix*v in result.
- // v can have numCols columns; then the result is stored column-wise as well
- // It is assumed space is allocaed in result!
- // v cannot be the same pointer as result
- void MultiplyMatrixVector(const taucsType * v, taucsType * result, const int numCols) const;
- // Multiplies the matrix by diagonal matrix D from the left, stores the result
- // in the columns of res
- void MultiplyDiagMatrixMatrix(const taucsType * D, SparseSolver & res) const;
- // Multiplies the matrix by the given matrix B from the right
- // and stores the result in the columns of res
- // isSPD tells us whether the result should be SPD or not
- // retuns false if the dimensions didn't match (in such case res is unaltered), otherwise true
- bool MultiplyMatrixRight(const SparseSolver & B, SparseSolver & res,const bool isSPD) const;
- // Transposes the matrix
- // and stores the result in the columns of res
- bool Transpose(SparseSolver & res) const;
- // will remove the rows startInd-endInd (including ends, zero-based) from the matrix
- // will discard any factors
- bool DeleteRowRange(const int startInd, const int endInd);
- // will remove the columns startInd-endInd (including ends, zero-based) from the matrix
- // will discard any factors
- bool DeleteColumnRange(const int startInd, const int endInd);
- // copies columns startInd through endInd (including, zero-based) from the matrix to res matrix
- // previous data in res, including factors, is erased.
- bool CopyColumnRange(const int startInd, const int endInd, SparseSolver & res) const;
- // copies rows startInd through endInd (including, zero-based) from the matrix to res matrix
- // previous data in res, including factors, is erased.
- bool CopyRowRange(const int startInd, const int endInd, SparseSolver & res) const;
- ///Multiplies the given range of rows (zero-based, including startInd and endInd) with the given scalar.
- bool MultiplyRows(const int startInd, const int endInd, const taucsType val);
- ///Multiplies all entries of the matrix with the given scalar. Will discard any factors.
- void MultiplyMatrixScalar(const taucsType val);
- /** Computes IdentityMatrix minus this matrix in-place. Will discard any factors.
- If an entry on the diagonal is missing, it will be created.
- */
- void IdentityMinusMatrix();
- /** Computes IdentityMatrix plus this matrix in-place. Will discard any factors.
- If an entry on the diagonal is missing, it will be created.
- */
- void IdentityPlusMatrix();
- // Alec:
- // Note on splice methods:
- // The following splice methods act like matlabs splicing and
- // reordering via index lists and the operator()
- // Both SpliceColumns and SpliceRows are ignorant of SPD, meaning that
- // they will not give "correct" splices for SPD matrices: splices of
- // This only matters if you are not setting all
- // SPD matrices are just splices of the lower triangle
- //
- // This only matters if you are not setting the upper half of the
- // matrix. To get correct splices you need to set both upper and lower
- // triangles before splicing.
- // Alec:
- // Copies certain cols in any order to a new matrix res
- // Like in Matlab B = A(:,column_indices)
- // Previous data in res is erased.
- // Returns false on error. As in column_indices are invalid
- // Result is always NOT SPD
- //
- // WARNING: If your matrix is only the lower half of an SPD matrix
- // then the result will only be a copy of the lower half of the
- // spliced columns. See note above (Note on splice methods)
- bool SpliceColumns(
- const std::vector<size_t> column_indices,
- SparseSolver & res) const;
- // Alec:
- // Copies certain rows in any order to a new matrix res
- // Like in Matlab B = A(:,row_indices)
- // Previous data in res is erased.
- // Returns false on error. As in row_indices are invalid
- // Result is always NOT SPD
- //
- // WARNING: If your matrix is only the lower half of an SPD matrix
- // then the result will only be a copy of the lower half of the
- // spliced rows. See note above (Note on splice methods)
- bool SpliceRows(
- const std::vector<size_t> row_indices,
- SparseSolver & res) const;
- // Wrapper than calls
- // SpliceColumns(column_indices, temp)
- // then
- // temp.SpliceRows(row_indices, res);
- bool SpliceColumnsThenRows(
- const std::vector<size_t> column_indices,
- const std::vector<size_t> row_indices,
- SparseSolver & res) const;
- // Vertical concatenation, works like matlab:
- // C = [A ; B];
- // If this matrix is A in the above the result is the concatenation of
- // this matrix on top of the supplied other matrix into the result
- // number of columns in A must equal number of columns in B
- //
- bool VerticalConcatenation(
- SparseSolver & other,
- SparseSolver & res);
- // Convert the matrix to IJV aka Coordinate format,
- // Outputs:
- // vals non-zero values, in no particular order
- // row_indices row indices corresponding to vals
- // column_indices column indices corresponding to vals
- //
- // All indices are 0-based
- void ConvertToIJV(
- std::vector<int> & row_indices,
- std::vector<int> & column_indices,
- std::vector<taucsType> & vals);
- // Convert lower triangle (including diagonal) of the matrix to IJV aka
- // Coordinate format,
- // Outputs:
- // vals non-zero values, in no particular order
- // row_indices row indices corresponding to vals
- // column_indices column indices corresponding to vals
- //
- // All indices are 0-based
- void ConvertLowerTriangleToIJV(
- std::vector<int> & row_indices,
- std::vector<int> & column_indices,
- std::vector<taucsType> & vals);
- // Convert the matrix to Compressed sparse column (CSC or CCS) format,
- // also known as Harwell Boeing format. As described:
- // http://netlib.org/linalg/html_templates/node92.html
- // or
- // http://en.wikipedia.org/wiki/Sparse_matrix
- // #Compressed_sparse_column_.28CSC_or_CCS.29
- // Outputs:
- // nnz number of non zero entries
- // num_rows number of rows
- // num_cols number of cols
- // vals non-zero values, row indices running fastest,
- // size(vals) = nnz
- // row_indices row indices corresponding to vals,
- // size(row_indices) = nnz
- // column_pointers index in vals of first entry in each column,
- // size(column_pointers) = num_cols+1
- //
- // All indices and pointers are 0-based
- void ConvertToHarwellBoeing(
- int & nnz,
- int & num_rows,
- int & num_cols,
- std::vector<taucsType> & vals,
- std::vector<int> & row_indices,
- std::vector<int> & column_pointers);
- #ifdef PRINTMODE
- // Print the matrix in IJV form
- void PrintIJV();
- #endif
- protected:
- #ifndef NO_TAUCS
- // Will create ATA matrix and AT matrix (in ccs format).
- void CreateATA();
- // Will create A matrix (in ccs format)
- void CreateA();
- void ClearFactorATA();
- void ClearFactorA();
- void ClearMatricesATA(); // clears m_A, m_ATA, m_AT
- void ClearMatricesA(); // clears the m_A matrix
- #endif
- };
- #ifdef PRINTMODE
- #include <cstdio>
- inline void SparseSolver::PrintIJV(){
- std::map<int,taucsType>::iterator it;
- for (int c = 0; c < m_numCols; ++c)
- {
- it = m_colsA[c].begin();
- while (it != m_colsA[c].end())
- {
- printf("%d %d %g\n",it->first,c, it->second);
- ++it;
- }
- }
- }
- #endif
- inline void SparseSolver::ClearObject() {
- #ifndef NO_TAUCS
- ClearFactorATA();
- ClearFactorA();
- ClearMatricesATA();
- ClearMatricesA();
- m_ATb.clear();
- m_etree = NULL;
- #endif
- m_numCols = 0;
- m_numRows = 0;
- m_colsA.clear();
- }
- // adds a new entry to the sparse matrix A
- // i and j are 0-based
- // if the A^T A matrix had been factored, this will destroy the factor
- inline void SparseSolver::AddIJV(const int i, const int j, const taucsType v) {
- #ifndef NO_TAUCS
- ClearFactorATA();
- ClearFactorA();
- ClearMatricesATA();
- ClearMatricesA();
- #endif
- m_colsA[j][i] = v;
- // update number of rows
- if ((i+1) > m_numRows)
- m_numRows = i+1;
- }
- // updates the entry in A by adding the value v to the current value
- // i and j are 0-based
- // if the A^T A matrix had been factored, this will destroy the factor
- inline void SparseSolver::AddToIJV(const int i, const int j, const taucsType v) {
- #ifndef NO_TAUCS
- ClearFactorATA();
- ClearFactorA();
- ClearMatricesATA();
- ClearMatricesA();
- #endif
- // if no such entry existed
- if (m_colsA[j].find(i) == m_colsA[j].end())
- m_colsA[j][i] = 0;
- m_colsA[j][i] += v;
- // update number of rows
- if ((i+1) > m_numRows)
- m_numRows = i+1;
- }
- #ifndef NO_TAUCS
- inline taucs_ccs_matrix * SparseSolver::GetATA_Copy() {
- if (! m_ATA) {
- CreateATA();
- }
- return MatrixCopy(m_ATA);
- }
- #endif
- // Implementation
- #define PRINTMODE
- #ifndef NO_TAUCS
- extern "C" {
- void chol_update(void *vF, int index, double val,void**vetree);
- }
- #endif
- void SparseSolver::Reset(const int numRows, const int numCols)
- {
- ClearObject();
- m_numRows = numRows;
- m_numCols = numCols;
- m_colsA.resize(m_numCols);
- }
- #ifndef NO_TAUCS
- // Will create A^T A and its factorization, as well as store A^T
- // returns true on success, false otherwise
- bool SparseSolver::FactorATA() {
- if (m_SPD)
- return FactorA();
- ClearFactorATA();
- if (m_ATA == NULL)
- CreateATA();
- // factorization
- int rc = taucs_linsolve(m_ATA, &m_factorATA,0,NULL,NULL,SIVANfactor,SIVANopt_arg);
- if (rc != TAUCS_SUCCESS)
- return false;
- return true;
- }
- // Will create ATA matrix and AT matrix.
- // returns true on success, false otherwise
- void SparseSolver::CreateATA() {
- if (m_A == NULL)
- CreateA();
- ClearMatricesATA();
- if (m_SPD) {
- // don't need to multiply because m_A is invertible and symmetric
- return;
- }
- else {
- m_AT = MatrixTranspose(m_A);
- // Multiply to get ATA:
- m_ATA = Mul2NonSymmMatSymmResult(m_AT, m_A);
- }
- }
- // Will create A matrix (in ccs format)
- void SparseSolver::CreateA() {
- ClearMatricesA();
- if (m_SPD)
- m_A = CreateTaucsMatrixFromColumns(m_colsA, m_numRows, TAUCS_DOUBLE|TAUCS_SYMMETRIC|TAUCS_LOWER);
- else
- m_A = CreateTaucsMatrixFromColumns(m_colsA, m_numRows, TAUCS_DOUBLE);
- }
- // Will create *symbolic* factorization of ATA and return it; returns NULL on failure
- void * SparseSolver::SymbolicFactorATA() {
- if (m_SPD) {
- if (m_A == NULL)
- CreateA();
- return taucs_ccs_factor_llt_symbolic(m_A);
- }
- else {
- if (m_ATA == NULL)
- CreateATA();
- return taucs_ccs_factor_llt_symbolic(m_ATA);
- }
- }
- // Will create the actual numerical factorization of the present ATA matrix
- // with the same non-zero pattern as created by SymbolicFactorATA()
- bool SparseSolver::FactorATA_UseSymbolic(void * symbFactor,
- taucs_ccs_matrix ** PAP,
- int * perm,
- int * invperm)
- {
- if (m_SPD) {
- if (m_A == NULL)
- CreateA();
- *PAP = taucs_ccs_permute_symmetrically(m_A, perm, invperm);
- }
- else {
- if (m_ATA == NULL)
- CreateATA();
- *PAP = taucs_ccs_permute_symmetrically(m_ATA, perm, invperm);
- }
- // compute numerical factorization
- if (taucs_ccs_factor_llt_numeric(*PAP, symbFactor) != 0) {
- return false;
- }
- else {
- return true;
- }
- }
- // Will create A and its factorization. If A is spd Cholesky factor, otherwise LU
- // returns true on success, false otherwise
- // Assumes A is square and invertible
- bool SparseSolver::FactorA() {
- ClearFactorA();
- if (m_A == NULL)
- CreateA();
- // factorization
- int rc;
- if (m_SPD)
- rc = taucs_linsolve(m_A, &m_factorA,0,NULL,NULL,SIVANfactor,SIVANopt_arg);
- else
- rc = taucs_linsolve(m_A, &m_factorA,0,NULL,NULL,SIVANfactorLU,SIVANopt_arg);
- if (rc != TAUCS_SUCCESS)
- return false;
- return true;
- }
- // Solves the normal equations for Ax = b, namely A^T A x = A^T b
- // it is assumed that enough space is allocated in x
- // Uses the factorization provided in factor
- // numRhs should be the the number of right-hand sides stored in b (and respectively,
- // there should be enough space allocated in the solution vector x)
- // returns true on success, false otherwise
- bool SparseSolver::SolveATA_UseFactor(void * factor,
- taucs_ccs_matrix * PAP,
- int * perm,
- int * invperm,
- const taucsType * b, taucsType * x, const int numRhs) {
- if (factor == NULL) {
- return false;
- }
- if (! m_SPD) {
- // prepare right-hand side
- if ((int)m_ATb.size() != m_numCols*numRhs)
- m_ATb.resize(m_numCols*numRhs);
- // multiply right-hand side
- for (int i = 0; i < numRhs; ++i) {
- MulMatrixVector(m_AT, b + i*m_numRows, (taucsType *)&(m_ATb.front()) + i*m_numCols);
- }
- }
- // solve the system:
- std::vector<taucsType> PB(m_numCols*numRhs), PX(m_numCols*numRhs);
- // permute rhs
- for (int c = 0; c < numRhs; ++c) {
- taucsType * curPB = &PB[0] + c*m_numCols;
- const taucsType * curB = (m_SPD)? (b + c*m_numCols) : (&(m_ATb.front()) + c*m_numCols);
- for (int i=0; i<m_numCols; ++i)
- curPB[i] = curB[perm[i]];
- }
- // solve by back-substitution
- int rc;
- for (int c = 0; c < numRhs; ++c) {
- rc = taucs_supernodal_solve_llt(factor, &PX[0] + c*m_numCols, &PB[0] + c*m_numCols);
- if (rc != TAUCS_SUCCESS) {
- return false;
- }
- }
- // re-permute x
- for (int c = 0; c < numRhs; ++c) {
- taucsType * curX = x + c*m_numCols;
- taucsType * curPX = &PX[0] + c*m_numCols;
- for (int i=0; i<m_numCols; ++i)
- curX[i] = curPX[invperm[i]];
- }
- return true;
- }
- // Solves the normal equations for Ax = b, namely A^T A x = A^T b
- // it is assumed that enough space is allocated in x
- // If a factorization of A^T A exists, it will be used, otherwise it will be created
- // numRhs should be the the number of right-hand sides stored in b (and respectively,
- // there should be enough space allocated in the solution vector x)
- // returns true on success, false otherwise
- bool SparseSolver::SolveATA(const taucsType * b, taucsType * x, const int numRhs) {
- if (m_SPD) {
- return SolveA(b, x, numRhs);
- }
- else {
- if (m_factorATA == NULL) {
- bool rc = FactorATA();
- if (!rc)
- return false;
- }
- }
- // prepare right-hand side
- if ((int)m_ATb.size() != m_numCols*numRhs)
- m_ATb.resize(m_numCols*numRhs);
- // multiply right-hand side
- for (int i = 0; i < numRhs; ++i) {
- MulMatrixVector(m_AT, b + i*m_numRows, (taucsType *)&(m_ATb.front()) + i*m_numCols);
- }
- int rc;
- // solve the system
- rc = taucs_linsolve(m_ATA,
- &m_factorATA,
- numRhs,
- x,
- (taucsType *)&(m_ATb.front()),
- SIVANsolve,
- SIVANopt_arg);
- return (rc == TAUCS_SUCCESS);
- }
- // Same as SolveATA only that this solves the actual system Ax = b
- // It is assumed that A is rectangular and invertible
- bool SparseSolver::SolveA(const taucsType * b, taucsType * x, const int numRhs) {
- if (m_factorA == NULL)
- if (!FactorA())
- return false;
- // solve the system
- int rc = taucs_linsolve(m_A,
- &m_factorA,
- numRhs,
- x,
- (void *)b,
- SIVANsolve,
- SIVANopt_arg);
- return (rc == TAUCS_SUCCESS);
- }
- // The version of SolveATA with 3 right-hand sides
- // returns true on success, false otherwise
- bool SparseSolver::SolveATA3(const taucsType * bx, const taucsType * by, const taucsType * bz,
- taucsType * x, taucsType * y, taucsType * z)
- {
- if (m_factorATA == NULL) {
- bool rc = FactorATA();
- if (!rc)
- return false;
- }
- // prepare right-hand side
- if ((int)m_ATb.size() != m_numCols*3)
- m_ATb.resize(m_numCols*3);
- // multiply right-hand side
- MulMatrixVector(m_AT, bx, (taucsType *)&(m_ATb.front()));
- MulMatrixVector(m_AT, by, (taucsType *)&(m_ATb.front()) + m_numCols);
- MulMatrixVector(m_AT, bz, (taucsType *)&(m_ATb.front()) + 2*m_numCols);
-
- // solve the system
- int rc = taucs_linsolve(m_ATA,
- &m_factorATA,
- 1,
- x,
- (taucsType *)&(m_ATb.front()),
- SIVANsolve,
- SIVANopt_arg);
- if (rc != TAUCS_SUCCESS)
- return false;
- rc = taucs_linsolve(m_ATA,
- &m_factorATA,
- 1,
- y,
- (taucsType *)&(m_ATb.front()) + m_numCols,
- SIVANsolve,
- SIVANopt_arg);
- if (rc != TAUCS_SUCCESS)
- return false;
- rc = taucs_linsolve(m_ATA,
- &m_factorATA,
- 1,
- z,
- (taucsType *)&(m_ATb.front()) + 2*m_numCols,
- SIVANsolve,
- SIVANopt_arg);
- return (rc == TAUCS_SUCCESS);
- }
- // The version of SolveATA with 2 right-hand sides
- // returns true on success, false otherwise
- bool SparseSolver::SolveATA2(const taucsType * bx, const taucsType * by,
- taucsType * x, taucsType * y)
- {
- if (m_factorATA == NULL) {
- bool rc = FactorATA();
- if (!rc)
- return false;
- }
- // prepare right-hand side
- if ((int)m_ATb.size() != m_numCols*2)
- m_ATb.resize(m_numCols*2);
- // multiply right-hand side
- MulMatrixVector(m_AT, bx, (taucsType *)&(m_ATb.front()));
- MulMatrixVector(m_AT, by, (taucsType *)&(m_ATb.front()) + m_numCols);
-
- // solve the system
- int rc = taucs_linsolve(m_ATA,
- &m_factorATA,
- 1,
- x,
- (taucsType *)&(m_ATb.front()),
- SIVANsolve,
- SIVANopt_arg);
- if (rc != TAUCS_SUCCESS)
- return false;
- rc = taucs_linsolve(m_ATA,
- &m_factorATA,
- 1,
- y,
- (taucsType *)&(m_ATb.front()) + m_numCols,
- SIVANsolve,
- SIVANopt_arg);
- return (rc == TAUCS_SUCCESS);
- }
- void SparseSolver::ClearFactorATA() {
- // release the factor
- taucs_linsolve(NULL,&m_factorATA,0, NULL,NULL,SIVANfactor,SIVANopt_arg);
- m_factorATA = NULL;
- m_etree = NULL;
- }
- void SparseSolver::ClearFactorA() {
- // release the factor
- if (m_SPD)
- taucs_linsolve(NULL,&m_factorA,0, NULL,NULL,SIVANfactor,SIVANopt_arg);
- else
- taucs_linsolve(NULL,&m_factorA,0, NULL,NULL,SIVANfactorLU,SIVANopt_arg);
- m_factorA = NULL;
- }
- void SparseSolver::ClearMatricesATA() {
- // free the matrices
- taucs_free(m_AT);
- m_AT = NULL;
- taucs_free(m_ATA);
- m_ATA = NULL;
- }
- void SparseSolver::ClearMatricesA() {
- // free the matrices
- taucs_free(m_A);
- m_A = NULL;
- }
- #endif
- void SparseSolver::AddMatrix(SparseSolver & B)
- {
- AddMatrix(0,0,B);
- }
- void SparseSolver::AddMatrix(const int i, const int j, SparseSolver & B)
- {
- std::map<int,taucsType>::iterator it;
- for (int c = 0; c < B.m_numCols; ++c)
- {
- it = B.m_colsA[c].begin();
- while (it != B.m_colsA[c].end())
- {
- // because AddToIJV is not O(1), this algorithm is O(Bnnz * Amaxrows),
- // ideally it would be O(Bnnz)
- AddToIJV(i+it->first,j+c,it->second);
- ++it;
- }
- }
- }
- bool SparseSolver::IsSymmetric()
- {
- if(m_SPD)
- {
- return true;
- }
- if(GetNumColumns() != GetNumRows())
- {
- return false;
- }
- // Cheapskate way to test if symmetric
- SparseSolver AT;
- if(!Transpose(AT))
- {
- return false;
- }
- // loop over columns
- std::map<int,taucsType>::iterator it;
- std::map<int,taucsType>::iterator ATit;
- for (int c = 0; c < m_numCols; ++c)
- {
- it = m_colsA[c].begin();
- ATit = AT.m_colsA[c].begin();
- while (it != m_colsA[c].end() && ATit !=AT.m_colsA[c].end())
- {
- if( it->first != ATit->first || it->second != ATit->second)
- {
- return false;
- }
- ++it;
- ++ATit;
- }
- }
- return true;
- }
- #ifndef NO_TAUCS
- // allows to add an anchored vertex without destroying the factor, if there was one
- // i is the anchor's number (i.e. the index of the mesh vertex that is anchored is i)
- // w is the weight of the anchor in the original Ax=b system. HAS TO BE POSITIVE!!
- // if there was no factor for A^T A, this will simply add an anchor row to the Ax=b system
- // if there was a factor, the factor will be updated, approximately at the cost of
- // a single solve.
- void SparseSolver::AddAnchor(const int i, const taucsType w) {
- if (m_SPD) {
- // update the columns
- if (m_colsA[i].find(i) == m_colsA[i].end())
- m_colsA[i][i] = w*w;
- else
- m_colsA[i][i] += w*w;
- if (m_factorA != NULL) {
- // the matrix is SPD so we update the factor of A
- chol_update(m_factorA, i, w, &m_etree);
- // update the matrix
- m_A->taucs_values[ m_A->colptr[i] ] += w*w;
- }
- }
- else {
- m_colsA[i][m_numRows] = w;
- m_numRows++;
- if (m_factorATA != NULL) {
- // update the ATA factor
- chol_update(m_factorATA, i, w, &m_etree);
- // update ATA
- m_ATA->taucs_values[ m_ATA->colptr[i] ] += w*w;
- // update A and AT (for multiplying rhs)
- CreateA();
- taucs_free(m_AT);
- m_AT = MatrixTranspose(m_A);
- }
- }
- }
- #endif
- void SparseSolver::MultiplyMatrixVector(const taucsType * v, taucsType * result, const int numCols) const {
- // make result all zero
- memset(result, 0, m_numRows * numCols * sizeof(taucsType));
- std::map<int,taucsType>::const_iterator iter;
- int offset_v;
- int offset_r;
- if (m_SPD) { // the matrix is symmetric
- for (int c = 0; c < numCols; ++c) {
- offset_v = m_numCols*c;
- for (int col = 0; col < m_numCols; ++col) {
- // going over column col of the matrix, multiplying
- // it by v[col] and setting the appropriate values
- // of vector result; also mirroring the other triangle
- for (iter = m_colsA[col].begin(); iter->first < col; ++iter) {
- result[iter->first + offset_v] += v[col + offset_v]*(iter->second);
- // mirroring
- result[col + offset_v] += v[iter->first + offset_v]*(iter->second);
- }
- if (iter->first == col)
- result[iter->first + offset_v] += v[col + offset_v]*(iter->second);
- }
- }
- }
- else {
- for (int c = 0; c < numCols; ++c) {
- offset_v = m_numCols*c;
- offset_r = m_numRows*c;
- for (int col = 0; col < m_numCols; ++col) {
- // going over column col of the matrix, multiplying
- // it by v[col] and setting the appropriate values
- // of vector result
- for (iter = m_colsA[col].begin(); iter != m_colsA[col].end(); ++iter) {
- result[iter->first + offset_r] += v[col + offset_v]*(iter->second);
- }
- }
- }
- }
- }
- // Multiplies the matrix by diagonal matrix D from the left, stores the result
- // in the columns of res
- void SparseSolver::MultiplyDiagMatrixMatrix(const taucsType * D, SparseSolver & res) const {
- res = SparseSolver(m_numRows, m_numCols, false);
- std::map<int,taucsType>::const_iterator iterA;
- std::map<int,taucsType>::iterator iterRes;
- res.m_colsA = m_colsA;
- if (m_SPD) {
- for (int col = 0; col < m_numCols; ++col) {
- iterA = m_colsA[col].begin();
- iterRes = res.m_colsA[col].begin();
- for ( ; iterA != m_colsA[col].end() && iterA->first <= col; ++iterA, ++iterRes) {
- iterRes->second = (iterA->second) * D[iterA->first];
- // mirroring
- res.m_colsA[iterA->first][col] = (iterA->second) * D[col];
- }
- }
- }
- else {
- for (int col = 0; col < m_numCols; ++col) {
- iterA = m_colsA[col].begin();
- iterRes = res.m_colsA[col].begin();
- for ( ; iterA != m_colsA[col].end(); ++iterA, ++iterRes) {
- iterRes->second = (iterA->second) * D[iterA->first];
- }
- }
- }
- }
- // Multiplies the matrix by the given matrix B from the right
- // and stores the result in the columns of res
- // isSPD tells us whether the result should be SPD or not
- // retuns false if the dimensions didn't match (in such case res is unaltered), otherwise true
- bool SparseSolver::MultiplyMatrixRight(const SparseSolver & B, SparseSolver & res,const bool isSPD) const {
- // for now ignore the option that one of the involved matrices is symmetric and doesn't have
- // stored under-diagonal values in m_colsA
- // we assume both matrices have all the values in m_colsA
- // (m x n) * (n x k)
- int m = m_numRows;
- int n = m_numCols;
- int k = B.m_numCols;
- if (B.m_numRows != n)
- return false;
- std::map<int,taucsType>::const_iterator iterBi, iterA;
- std::map<int,taucsType>::iterator iterRes;
- int rowInd;
- taucsType BiVal;
- res = SparseSolver(m, k, isSPD);
- for (int i = 0; i < k; ++i) { // go over the columns of res; res(i) = A*B(i)
- for (iterBi = B.m_colsA[i].begin(); iterBi != B.m_colsA[i].end(); ++iterBi) { // go over column B(i)
- // iterBi->second multiplies column A(iterBi->first)
- BiVal = iterBi->second;
- rowInd = iterBi->first;
- for (iterA = m_colsA[rowInd].begin(); iterA != m_colsA[rowInd].end(); ++iterA) { // go over column of A
- iterRes = res.m_colsA[i].find(iterA->first);
- if (iterRes == res.m_colsA[i].end()) // first occurence of this row number
- res.m_colsA[i][iterA->first] = (iterA->second)*BiVal;
- else
- iterRes->second += (iterA->second)*BiVal;
- }
- }
- }
- return true;
- }
- // Transposes the matrix
- // and stores the result in the columns of res
- bool SparseSolver::Transpose(SparseSolver & res) const {
- res = SparseSolver(m_numCols, m_numRows, m_SPD);
- // if the matrix was symmetric to begin with, just copy the columns
- if (m_SPD) {
- res.m_colsA = m_colsA;
- return true;
- }
- // else need to transpose
- std::map<int,taucsType>::const_iterator iterA;
- for (int i=0; i < m_numCols; ++i) {
- for (iterA = m_colsA[i].begin(); iterA != m_colsA[i].end(); ++iterA) {
- res.m_colsA[iterA->first][i] = iterA->second;
- }
- }
- return true;
- }
- // will remove the rows startInd-endInd (including ends, zero-based) from the matrix
- // will discard any factors
- bool SparseSolver::DeleteRowRange(const int startInd, const int endInd) {
- if (startInd < 0 || endInd >= m_numRows || startInd > endInd)
- return false;
- #ifndef NO_TAUCS
- ClearFactorATA();
- ClearFactorA();
- ClearMatricesATA();
- ClearMatricesA();
- #endif
- std::map<int,taucsType>::iterator it;
- std::map<int,taucsType>::iterator tempIt;
- int diff = endInd - startInd + 1;
- for (int c = 0; c < m_numCols; ++c) {
- it = m_colsA[c].begin();
- while (it != m_colsA[c].end()) {
- if (it->first >= startInd && it->first <= endInd) { // row that should be erased
- m_colsA[c].erase(it++);
- } else {
- if (it->first > endInd) {// row number must be updated
- m_colsA[c][it->first - diff] = it->second;
- m_colsA[c].erase(it++);
- }
- else
- ++it;
- }
- }
- }
- m_numRows -= diff;
- m_SPD = false;
-
- return true;
- }
- bool SparseSolver::MultiplyRows(const int startInd, const int endInd, const taucsType val)
- {
- if (startInd < 0 || endInd >= m_numRows || startInd > endInd) return false;
- #ifndef NO_TAUCS
- ClearFactorATA();
- ClearFactorA();
- ClearMatricesATA();
- ClearMatricesA();
- #endif
- std::map<int,taucsType>::iterator it;
- for (int c = 0; c < m_numCols; ++c)
- {
- it = m_colsA[c].begin();
- while (it != m_colsA[c].end())
- {
- if (it->first >= startInd && it->first <= endInd) // row that should be multiplied
- {
- it->second *= val;
- }
- it++;
- }
- }
- return true;
- }
- // will remove the columns startInd-endInd (including ends, zero-based) from the matrix
- // will discard any factors
- bool SparseSolver::DeleteColumnRange(const int startInd, const int endInd) {
- if (startInd < 0 || endInd >= m_numCols || startInd > endInd)
- return false;
- #ifndef NO_TAUCS
- ClearFactorATA();
- ClearFactorA();
- ClearMatricesATA();
- ClearMatricesA();
- #endif
- m_colsA.erase(m_colsA.begin() + startInd, m_colsA.begin() + (endInd+1));
- m_numCols -= (endInd - startInd + 1);
- return true;
- }
- // copies columns startInd through endInd (including, zero-based) from the matrix to res matrix
- // previous data in res, including factors, is erased.
- bool SparseSolver::CopyColumnRange(const int startInd, const int endInd, SparseSolver & res) const {
- if (startInd < 0 || endInd >= m_numCols || startInd > endInd)
- return false;
- int k = endInd - startInd + 1;
- res = SparseSolver(m_numRows, k, false);
- for (int c = startInd; c <= endInd; ++c)
- res.m_colsA[c - startInd] = m_colsA[c];
- return true;
- }
- // copies rows startInd through endInd (including, zero-based) from the matrix to res matrix
- // previous data in res, including factors, is erased.
- bool SparseSolver::CopyRowRange(const int startInd, const int endInd, SparseSolver & res) const {
- if (startInd < 0 || endInd >= m_numRows || startInd > endInd)
- return false;
- res.m_colsA = m_colsA;
- for (int c = 0; c < m_numCols; ++c) {
- std::map<int,taucsType>::iterator it = res.m_colsA[c].begin();
- std::map<int,taucsType>::iterator tempIt;
- for ( ; it != res.m_colsA[c].end(); ++it) {
- if (it->first < startInd || it->first > endInd) {
- tempIt = it;
- it++;
- res.m_colsA[c].erase(tempIt);
- continue;
- }
- }
- }
- return true;
- }
- void SparseSolver::MultiplyMatrixScalar(const taucsType val)
- {
- #ifndef NO_TAUCS
- ClearFactorATA();
- ClearFactorA();
- ClearMatricesATA();
- ClearMatricesA();
- #endif
- //Over all entries
- for (int c=0;c<m_numCols;c++)
- {
- for(std::map< int, taucsType >::iterator it=m_colsA[c].begin();it!=m_colsA[c].end();it++)
- {
- it->second *= val; //Multiply
- }
- }
- }
- void SparseSolver::IdentityMinusMatrix()
- {
- #ifndef NO_TAUCS
- ClearFactorATA();
- ClearFactorA();
- ClearMatricesATA();
- ClearMatricesA();
- #endif
- //Over the diagonal
- for (int c=0;c<m_numCols;c++)
- {
- std::map< int, taucsType >::iterator it = m_colsA[c].find(c);
- if (it != m_colsA[c].end())
- {
- it->second = 1.0 - it->second;
- }
- else
- {
- AddIJV(c, c, 1.0);
- }
- }
- }
- void SparseSolver::IdentityPlusMatrix()
- {
- #ifndef NO_TAUCS
- ClearFactorATA();
- ClearFactorA();
- ClearMatricesATA();
- ClearMatricesA();
- #endif
- //Over the diagonal
- for (int c=0;c<m_numCols;c++)
- {
- std::map< int, taucsType >::iterator it = m_colsA[c].find(c);
- if (it != m_colsA[c].end())
- {
- it->second += 1.0;
- }
- else
- {
- AddIJV(c, c, 1.0);
- }
- }
- }
- //
- // Memory: 1*spliced = 1*O(column_indices.size * numRows)
- // Runtime: O(size of spliced) = O(column_indices.size * numRows)
- bool SparseSolver::SpliceColumns(
- const std::vector<size_t> column_indices,
- SparseSolver & res) const
- {
- // Check that all indices in column_indices are valid
- for(
- std::vector<size_t>::const_iterator old_index = column_indices.begin();
- old_index != column_indices.end();
- old_index++)
- {
- if((*old_index) >= (size_t)m_numCols)
- {
- return false;
- }
- }
- // create result
- res = SparseSolver(m_numRows,column_indices.size(),false);
- // splice (and reorder) columns
- size_t new_index = 0;
- for(
- std::vector<size_t>::const_iterator old_index = column_indices.begin();
- old_index != column_indices.end();
- old_index++,new_index++)
- {
- res.m_colsA[new_index] = m_colsA[(*old_index)];
- }
- return true;
- }
- // Cheating way of handling SpliceRows.
- // SpliceRows = Transpose -> SpliceColumns -> Transpose
- //
- // Sparse (not dense), but not perfect implementation:
- // Memory: 1*original + 2*spliced
- // Runtime: O(
- // transpose of original +
- // splicecolumns of original +
- // transpose of spliced)
- // = O(
- // size of original +
- // size of spliced
- // size of spliced)
- // = O( size of original )
- //
- // A good implementation should be:
- // Memory: 1*spliced = 1*O(row_indices.size * numCols)
- // Runtime: O(size of spliced) = O(row_indices.size * numCols)
- bool SparseSolver::SpliceRows(
- const std::vector<size_t> row_indices,
- SparseSolver & res) const
- {
- // Check that all indices in row_indices are valid
- for(
- std::vector<size_t>::const_iterator old_index = row_indices.begin();
- old_index != row_indices.end();
- old_index++)
- {
- if((*old_index) >= (size_t)m_numRows)
- {
- return false;
- }
- }
- // transpose (now columns are rows, rows are columns)
- SparseSolver transpose;
- if(!Transpose(transpose))
- {
- return false;
- }
- // Splice columns of transpose
- SparseSolver spliced_transpose;
- if(!transpose.SpliceColumns(row_indices, spliced_transpose))
- {
- return false;
- }
- // Transpose again (rows back to rows, columns back to columns)
- if(!spliced_transpose.Transpose(res))
- {
- return false;
- }
- return true;
- }
- bool SparseSolver::SpliceColumnsThenRows(
- const std::vector<size_t> column_indices,
- const std::vector<size_t> row_indices,
- SparseSolver & res) const
- {
- SparseSolver temp;
- if(!SpliceColumns(column_indices,temp))
- {
- return false;
- }
- if(!temp.SpliceRows(row_indices,res))
- {
- return false;
- }
- return true;
- }
-
- bool SparseSolver::VerticalConcatenation(
- SparseSolver & other,
- SparseSolver & res)
- {
- // if other if skinnier than we'll padd with zeros
- if(other.GetNumColumns() > m_numCols)
- {
- return false;
- }
- res = SparseSolver(m_numRows+other.GetNumRows(), m_numCols,false);
- // copy all columns from this matrix to result
- res.m_colsA = m_colsA;
- // copy all entries in other to result with rows offset by "m_numRows"
- std::map<int,taucsType>::iterator it;
- for (int c = 0; c < other.m_numCols; ++c)
- {
- it = other.m_colsA[c].begin();
- while (it != other.m_colsA[c].end())
- {
- res.AddIJV(it->first+m_numRows,c,it->second);
- ++it;
- }
- }
- return true;
- }
- void SparseSolver::ConvertToIJV(
- std::vector<int> & row_indices,
- std::vector<int> & column_indices,
- std::vector<taucsType> & vals)
- {
- // Get number of non-zeros
- size_t nnz = 0;
- // loop over columns
- for (int c = 0; c < m_numCols; ++c)
- {
- // add up the number of non-zeros in each column
- nnz += m_colsA[c].size();
- }
- // allocate space in outputs
- vals.resize(nnz);
- row_indices.resize(nnz);
- column_indices.resize(nnz);
- size_t index = 0;
-
- std::map<int,taucsType>::iterator it;
- // loop over columns
- for (int c = 0; c < m_numCols; ++c)
- {
- // loop over rows
- it = m_colsA[c].begin();
- while (it != m_colsA[c].end())
- {
- row_indices[index] = it->first;
- column_indices[index] = c;
- vals[index] = it->second;
- // increment index
- index++;
-
- ++it;
- }
- }
- }
- void SparseSolver::ConvertLowerTriangleToIJV(
- std::vector<int> & row_indices,
- std::vector<int> & column_indices,
- std::vector<taucsType> & vals)
- {
- // Get number of ALL non-zeros
- size_t nnz = 0;
- // loop over columns
- for (int c = 0; c < m_numCols; ++c)
- {
- // add up the number of non-zeros in each column
- nnz += m_colsA[c].size();
- }
- // allocate (too much) space in outputs
- vals.resize(nnz);
- row_indices.resize(nnz);
- column_indices.resize(nnz);
- size_t index = 0;
-
- std::map<int,taucsType>::iterator it;
- // loop over columns
- for (int c = 0; c < m_numCols; ++c)
- {
- // loop over rows
- it = m_colsA[c].begin();
- while (it != m_colsA[c].end())
- {
- // if row is less than or equal to column then we're in the lower
- // triangle
- if(it->first>= c)
- {
- row_indices[index] = it->first;
- column_indices[index] = c;
- vals[index] = it->second;
- // increment index
- index++;
- }
-
- ++it;
- }
- }
- // resize to actually number of non-zeros in lower triangle
- vals.resize(index);
- row_indices.resize(index);
- column_indices.resize(index);
- }
- void SparseSolver::ConvertToHarwellBoeing(
- int & nnz,
- int & num_rows,
- int & num_cols,
- std::vector<taucsType> & vals,
- std::vector<int> & row_indices,
- std::vector<int> & column_pointers)
- {
- num_rows = m_numRows;
- num_cols = m_numCols;
- nnz = 0;
- // loop over columns
- for (int c = 0; c < m_numCols; ++c)
- {
- // add up the number of non-zeros in each column
- nnz += m_colsA[c].size();
- }
- vals.resize(nnz);
- row_indices.resize(nnz);
- column_pointers.resize(num_cols+1);
- // loop over columns
- int column_pointer = 0;
- int val_index = 0;
- std::map<int,taucsType>::iterator it;
- int c;
- for (c = 0; c < m_numCols; ++c)
- {
- column_pointers[c] = column_pointer;
- column_pointer += m_colsA[c].size();
- // over rows in this column
- it = m_colsA[c].begin();
- while (it != m_colsA[c].end())
- {
- vals[val_index] = it->second;
- row_indices[val_index] = it->first;
- val_index++;
- ++it;
- }
- }
- // by convention column_pointers[num_cols] = nnz
- column_pointers[c] = column_pointer;
- }
|