Changeset 19bf86 in git
- Timestamp:
- Jun 21, 2010, 1:20:59 PM (13 years ago)
- Branches:
- (u'jengelh-datetime', 'ceac47cbc86fe4a15902392bdbb9bd2ae0ea02c6')(u'spielwiese', 'f875bbaccd0831e36aaed09ff6adeb3eb45aeb94')
- Children:
- e3cc9c88085d8e217de6a163ac2bc7d891c19815
- Parents:
- e558c41b132228287898863201fbd5c35b4231fd
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
Singular/iparith.cc
re558c4 r19bf86 317 317 { "ludecomp", 0, LU_CMD , CMD_1}, 318 318 { "luinverse", 0, LUI_CMD , CMD_M}, 319 { "lusolve", 0, LUS_CMD , CMD_M}, 319 320 { "map", 0, MAP_CMD , RING_DECL}, 320 321 { "matrix", 0, MATRIX_CMD , MATRIX_CMD}, … … 7109 7110 return FALSE; 7110 7111 } 7112 static BOOLEAN jjLU_SOLVE(leftv res, leftv v) 7113 { 7114 /* for solving a linear equation system A * x = b, via the 7115 given LU-decomposition of the matrix A; 7116 There is one valid parametrisation: 7117 1) exactly four arguments P, L, U, b; 7118 P, L, and U realise the L-U-decomposition of A, that is, 7119 P * A = L * U, and P, L, and U satisfy the 7120 properties decribed in method 'jjLU_DECOMP'; 7121 see there; 7122 b is the right-hand side vector of the equation system; 7123 The method will return a list of either 1 entry or three entries: 7124 1) [0] if there is no solution to the system; 7125 2) [1, x, dim] if there is at least one solution; 7126 x is any solution, dim is the dimension of the affine solution 7127 space. 7128 The method produces an error if matrix and vector sizes do not fit. */ 7129 if ((v == NULL) || (v->Typ() != MATRIX_CMD) || 7130 (v->next == NULL) || (v->next->Typ() != MATRIX_CMD) || 7131 (v->next->next == NULL) || (v->next->next->Typ() != MATRIX_CMD) || 7132 (v->next->next->next == NULL) || 7133 (v->next->next->next->Typ() != MATRIX_CMD) || 7134 (v->next->next->next->next != NULL)) 7135 { 7136 Werror("expected exactly three matrices and one vector as input"); 7137 return TRUE; 7138 } 7139 matrix pMat = (matrix)v->Data(); 7140 matrix lMat = (matrix)v->next->Data(); 7141 matrix uMat = (matrix)v->next->next->Data(); 7142 matrix bVec = (matrix)v->next->next->next->Data(); 7143 matrix xVec; int solvable; int dim; 7144 if (pMat->rows() != pMat->cols()) 7145 { 7146 Werror("first matrix (%d x %d) is not quadratic", 7147 pMat->rows(), pMat->cols()); 7148 return TRUE; 7149 } 7150 if (lMat->rows() != lMat->cols()) 7151 { 7152 Werror("second matrix (%d x %d) is not quadratic", 7153 lMat->rows(), lMat->cols()); 7154 return TRUE; 7155 } 7156 if (lMat->rows() != uMat->rows()) 7157 { 7158 Werror("second matrix (%d x %d) and third matrix (%d x %d) do not fit", 7159 lMat->rows(), lMat->cols(), uMat->rows(), uMat->cols()); 7160 return TRUE; 7161 } 7162 if (uMat->rows() != bVec->rows()) 7163 { 7164 Werror("third matrix (%d x %d) and vector (%d x 1) do not fit", 7165 uMat->rows(), uMat->cols(), bVec->rows()); 7166 return TRUE; 7167 } 7168 solvable = luSolveViaLUDecomp(pMat, lMat, uMat, bVec, xVec, &dim); 7169 7170 /* build the return structure; a list with either one or three entries */ 7171 lists ll = (lists)omAllocBin(slists_bin); 7172 if (solvable) 7173 { 7174 ll->Init(3); 7175 ll->m[0].rtyp=INT_CMD; ll->m[0].data=(void *)solvable; 7176 ll->m[1].rtyp=MATRIX_CMD; ll->m[1].data=(void *)xVec; 7177 ll->m[2].rtyp=INT_CMD; ll->m[2].data=(void *)dim; 7178 } 7179 else 7180 { 7181 ll->Init(1); 7182 ll->m[0].rtyp=INT_CMD; ll->m[0].data=(void *)solvable; 7183 } 7184 7185 res->data=(char*)ll; 7186 return FALSE; 7187 } 7111 7188 static BOOLEAN jjINTVEC_PL(leftv res, leftv v) 7112 7189 { … … 7592 7669 ,{jjLIST_PL, LIST_CMD, LIST_CMD, -1 , ALLOW_PLURAL |ALLOW_RING} 7593 7670 ,{jjLU_INVERSE,LUI_CMD, LIST_CMD, -2 , NO_PLURAL |NO_RING} 7671 ,{jjLU_SOLVE, LUS_CMD, LIST_CMD, -2 , NO_PLURAL |NO_RING} 7594 7672 ,{jjWRONG, MINOR_CMD, NONE, 1 , ALLOW_PLURAL |ALLOW_RING} 7595 7673 ,{jjMINOR_M, MINOR_CMD, IDEAL_CMD, -2 , ALLOW_PLURAL |ALLOW_RING} -
Singular/tok.h
re558c4 r19bf86 97 97 LU_CMD, 98 98 LUI_CMD, 99 LUS_CMD, 99 100 MEMORY_CMD, 100 101 MONITOR_CMD, -
kernel/linearAlgebra.cc
re558c4 r19bf86 103 103 for (int r = 1; r <= rr; r++) MATELEM(lMat, r, r) = pOne(); 104 104 105 int bestR; int bestC; int intSwap; poly pSwap; 105 int bestR; int bestC; int intSwap; poly pSwap; int cOffset = 0; 106 106 for (int r = 1; r < rr; r++) 107 107 { 108 if ((r <= cc) && (pivot(uMat, r, rr, r, r, &bestR, &bestC))) 108 if (r > cc) break; 109 while ((r + cOffset <= cc) && 110 (!pivot(uMat, r, rr, r + cOffset, r + cOffset, &bestR, &bestC))) 111 cOffset++; 112 if (r + cOffset <= cc) 109 113 { 110 114 /* swap rows with indices r and bestR in permut */ … … 114 118 115 119 /* swap rows with indices r and bestR in uMat; 116 it is sufficient to do this for columns >= r */117 for (int c = r ; c <= cc; c++)120 it is sufficient to do this for columns >= r + cOffset*/ 121 for (int c = r + cOffset; c <= cc; c++) 118 122 { 119 123 pSwap = MATELEM(uMat, r, c); … … 134 138 row with index r; 135 139 we need to adjust lMat and uMat; 136 we are certain that the matrix entry at [r, r] is non-zero: */ 137 number pivotElement = pGetCoeff(MATELEM(uMat, r, r)); 140 we are certain that the matrix entry at [r, r + cOffset] 141 is non-zero: */ 142 number pivotElement = pGetCoeff(MATELEM(uMat, r, r + cOffset)); 138 143 poly p; number n; 139 144 for (int rGauss = r + 1; rGauss <= rr; rGauss++) 140 145 { 141 p = MATELEM(uMat, rGauss, r );146 p = MATELEM(uMat, rGauss, r + cOffset); 142 147 if (p != NULL) 143 148 { … … 149 154 150 155 /* adjusting uMat: */ 151 MATELEM(uMat, rGauss, r ) = NULL; pDelete(&p);156 MATELEM(uMat, rGauss, r + cOffset) = NULL; pDelete(&p); 152 157 n = nNeg(n); 153 for (int cGauss = r + 1; cGauss <= cc; cGauss++)158 for (int cGauss = r + cOffset + 1; cGauss <= cc; cGauss++) 154 159 MATELEM(uMat, rGauss, cGauss) 155 160 = pAdd(MATELEM(uMat, rGauss, cGauss), … … 316 321 return result; 317 322 } 323 324 bool luSolveViaLUDecomp(const matrix pMat, const matrix lMat, 325 const matrix uMat, const matrix bVec, 326 matrix &xVec, int* dim) 327 { 328 int m = uMat->rows(); int n = uMat->cols(); 329 matrix cVec = mpNew(m, 1); /* for storing pMat * bVec */ 330 matrix yVec = mpNew(m, 1); /* for storing the unique solution of 331 lMat * yVec = cVec */ 332 333 /* compute cVec = pMat * bVec but without actual multiplications */ 334 for (int r = 1; r <= m; r++) 335 { 336 for (int c = 1; c <= m; c++) 337 { 338 if (MATELEM(pMat, r, c) != NULL) 339 { MATELEM(cVec, r, 1) = pCopy(MATELEM(bVec, c, 1)); break; } 340 } 341 } 342 343 /* solve lMat * yVec = cVec; this will always work as lMat is invertible; 344 moreover, no divisions are needed, since lMat[i, i] = 1, for all i */ 345 for (int r = 1; r <= m; r++) 346 { 347 poly p = pNeg(pCopy(MATELEM(cVec, r, 1))); 348 for (int c = 1; c < r; c++) 349 p = pAdd(p, ppMult_qq(MATELEM(lMat, r, c), MATELEM(yVec, c, 1) )); 350 MATELEM(yVec, r, 1) = pNeg(p); 351 } 352 353 /* determine whether uMat * xVec = yVec is solvable */ 354 bool isSolvable = true; 355 bool isZeroRow; int nonZeroRowIndex; 356 for (int r = m; r >= 1; r--) 357 { 358 isZeroRow = true; 359 for (int c = 1; c <= n; c++) 360 if (MATELEM(uMat, r, c) != NULL) { isZeroRow = false; break; } 361 if (isZeroRow) 362 { 363 if (MATELEM(yVec, r, 1) != NULL) { isSolvable = false; break; } 364 } 365 else { nonZeroRowIndex = r; break; } 366 } 367 368 if (isSolvable) 369 { 370 xVec = mpNew(n, 1); *dim = 0; 371 /* solve uMat * xVec = yVec and determine the dimension of the affine 372 solution space */ 373 int nonZeroC; int lastNonZeroC = n + 1; 374 for (int r = nonZeroRowIndex; r >= 1; r--) 375 { 376 for (nonZeroC = 1; nonZeroC <= n; nonZeroC++) 377 if (MATELEM(uMat, r, nonZeroC) != NULL) break; 378 *dim = *dim + lastNonZeroC - nonZeroC - 1; 379 poly p = pNeg(pCopy(MATELEM(yVec, r, 1))); 380 for (int c = nonZeroC + 1; c <= n; c++) 381 if (MATELEM(xVec, c, 1) != NULL) 382 p = pAdd(p, ppMult_qq(MATELEM(uMat, r, c), MATELEM(xVec, c, 1))); 383 poly q = pNSet(nInvers(pGetCoeff(MATELEM(uMat, r, nonZeroC)))); 384 MATELEM(xVec, nonZeroC, 1) = pMult(pNeg(p), q); 385 lastNonZeroC = nonZeroC; 386 } 387 } 388 389 idDelete((ideal*)&cVec); 390 idDelete((ideal*)&yVec); 391 392 return isSolvable; 393 } -
kernel/linearAlgebra.h
re558c4 r19bf86 198 198 matrix &iMat /**< [out] inverse of A if invertible */ 199 199 ); 200 201 /** 202 * Solves the linear system A*x = b, where A is an (n x n)-matrix 203 * which is given by its LU-decomposition. 204 * 205 * The method expects the LU-decomposition of A, that is, 206 * pMat * A = lMat * uMat, where the argument matrices have the 207 * appropriate proteries; see method 208 * 'luDecomp(const matrix aMat, matrix &pMat, matrix &lMat, 209 * matrix &uMat)'.<br> 210 * Instead of trying to invert A and return x = A^(-1)*b, this 211 * method 212 * 1) computes b' = pMat * b, 213 * 2) solves the easy system L * y = b', and then 214 * 3) solves the easy system U * x = y. 215 * Note that steps 1) and 2) will always work, as L is in any case 216 * invertible. Moreover, y is uniquely determined. Step 3) will only 217 * work if and only if y is in the column span of U. In that case, 218 * there may be infinitely many solutions. 219 * Thus, there are three cases:<br> 220 * 1) There is no solution. Then the method returns false, and &xVec 221 as well as &dim remain unchanged.<br> 222 * 2) There is a unique solution. Then the method returns true and 223 * the dimension of the affine solution space is zero.<br> 224 * 3) There are infinitely many solutions. Then the method returns 225 * true and some solution. Furthermore, the dimension of the 226 affine solution space is set accordingly. 227 * 228 * @return true if there is at least one solution, false otherwise 229 **/ 230 bool luSolveViaLUDecomp( 231 const matrix pMat, /**< [in] permutation matrix of an LU- 232 decomposition */ 233 const matrix lMat, /**< [in] lower left matrix of an LU- 234 decomposition */ 235 const matrix uMat, /**< [in] upper right matrix of an LU- 236 decomposition */ 237 const matrix bVec, /**< [in] right-hand side of the linear 238 system to be solved */ 239 matrix &xVec, /**< [out] solution of A*x = b */ 240 int* dim /**< [out] dimension of affine solution 241 space */ 242 ); 200 243 201 244 #endif
Note: See TracChangeset
for help on using the changeset viewer.