1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.math3.linear; 18 19 import java.util.Arrays; 20 21 import org.apache.commons.math3.exception.DimensionMismatchException; 22 import org.apache.commons.math3.util.FastMath; 23 import org.apache.commons.math3.util.IterationEvent; 24 import org.apache.commons.math3.util.IterationListener; 25 import org.junit.Assert; 26 import org.junit.Test; 27 28 public class SymmLQTest { 29 saundersTest(final int n, final boolean goodb, final boolean precon, final double shift, final double pertbn)30 public void saundersTest(final int n, final boolean goodb, 31 final boolean precon, final double shift, 32 final double pertbn) { 33 final RealLinearOperator a = new RealLinearOperator() { 34 35 @Override 36 public RealVector operate(final RealVector x) { 37 if (x.getDimension() != n) { 38 throw new DimensionMismatchException(x.getDimension(), n); 39 } 40 final double[] y = new double[n]; 41 for (int i = 0; i < n; i++) { 42 y[i] = (i + 1) * 1.1 / n * x.getEntry(i); 43 } 44 return new ArrayRealVector(y, false); 45 } 46 47 @Override 48 public int getRowDimension() { 49 return n; 50 } 51 52 @Override 53 public int getColumnDimension() { 54 return n; 55 } 56 }; 57 final double shiftm = shift; 58 final double pertm = FastMath.abs(pertbn); 59 final RealLinearOperator minv; 60 if (precon) { 61 minv = new RealLinearOperator() { 62 @Override 63 public int getRowDimension() { 64 return n; 65 } 66 67 @Override 68 public int getColumnDimension() { 69 return n; 70 } 71 72 @Override 73 public RealVector operate(final RealVector x) { 74 if (x.getDimension() != n) { 75 throw new DimensionMismatchException(x.getDimension(), 76 n); 77 } 78 final double[] y = new double[n]; 79 for (int i = 0; i < n; i++) { 80 double d = (i + 1) * 1.1 / n; 81 d = FastMath.abs(d - shiftm); 82 if (i % 10 == 0) { 83 d += pertm; 84 } 85 y[i] = x.getEntry(i) / d; 86 } 87 return new ArrayRealVector(y, false); 88 } 89 }; 90 } else { 91 minv = null; 92 } 93 final RealVector xtrue = new ArrayRealVector(n); 94 for (int i = 0; i < n; i++) { 95 xtrue.setEntry(i, n - i); 96 } 97 final RealVector b = a.operate(xtrue); 98 b.combineToSelf(1.0, -shift, xtrue); 99 final SymmLQ solver = new SymmLQ(2 * n, 1E-12, true); 100 final RealVector x = solver.solve(a, minv, b, goodb, shift); 101 final RealVector y = a.operate(x); 102 final RealVector r1 = new ArrayRealVector(n); 103 for (int i = 0; i < n; i++) { 104 final double bi = b.getEntry(i); 105 final double yi = y.getEntry(i); 106 final double xi = x.getEntry(i); 107 r1.setEntry(i, bi - yi + shift * xi); 108 } 109 final double enorm = x.subtract(xtrue).getNorm() / xtrue.getNorm(); 110 final double etol = 1E-5; 111 Assert.assertTrue("enorm=" + enorm + ", " + 112 solver.getIterationManager().getIterations(), enorm <= etol); 113 } 114 115 @Test testSolveSaunders1()116 public void testSolveSaunders1() { 117 saundersTest(1, false, false, 0., 0.); 118 } 119 120 @Test testSolveSaunders2()121 public void testSolveSaunders2() { 122 saundersTest(2, false, false, 0., 0.); 123 } 124 125 @Test testSolveSaunders3()126 public void testSolveSaunders3() { 127 saundersTest(1, false, true, 0., 0.); 128 } 129 130 @Test testSolveSaunders4()131 public void testSolveSaunders4() { 132 saundersTest(2, false, true, 0., 0.); 133 } 134 135 @Test testSolveSaunders5()136 public void testSolveSaunders5() { 137 saundersTest(5, false, true, 0., 0.); 138 } 139 140 @Test testSolveSaunders6()141 public void testSolveSaunders6() { 142 saundersTest(5, false, true, 0.25, 0.); 143 } 144 145 @Test testSolveSaunders7()146 public void testSolveSaunders7() { 147 saundersTest(50, false, false, 0., 0.); 148 } 149 150 @Test testSolveSaunders8()151 public void testSolveSaunders8() { 152 saundersTest(50, false, false, 0.25, 0.); 153 } 154 155 @Test testSolveSaunders9()156 public void testSolveSaunders9() { 157 saundersTest(50, false, true, 0., 0.10); 158 } 159 160 @Test testSolveSaunders10()161 public void testSolveSaunders10() { 162 saundersTest(50, false, true, 0.25, 0.10); 163 } 164 165 @Test testSolveSaunders11()166 public void testSolveSaunders11() { 167 saundersTest(1, true, false, 0., 0.); 168 } 169 170 @Test testSolveSaunders12()171 public void testSolveSaunders12() { 172 saundersTest(2, true, false, 0., 0.); 173 } 174 175 @Test testSolveSaunders13()176 public void testSolveSaunders13() { 177 saundersTest(1, true, true, 0., 0.); 178 } 179 180 @Test testSolveSaunders14()181 public void testSolveSaunders14() { 182 saundersTest(2, true, true, 0., 0.); 183 } 184 185 @Test testSolveSaunders15()186 public void testSolveSaunders15() { 187 saundersTest(5, true, true, 0., 0.); 188 } 189 190 @Test testSolveSaunders16()191 public void testSolveSaunders16() { 192 saundersTest(5, true, true, 0.25, 0.); 193 } 194 195 @Test testSolveSaunders17()196 public void testSolveSaunders17() { 197 saundersTest(50, true, false, 0., 0.); 198 } 199 200 @Test testSolveSaunders18()201 public void testSolveSaunders18() { 202 saundersTest(50, true, false, 0.25, 0.); 203 } 204 205 @Test testSolveSaunders19()206 public void testSolveSaunders19() { 207 saundersTest(50, true, true, 0., 0.10); 208 } 209 210 @Test testSolveSaunders20()211 public void testSolveSaunders20() { 212 saundersTest(50, true, true, 0.25, 0.10); 213 } 214 215 @Test(expected = NonSquareOperatorException.class) testNonSquareOperator()216 public void testNonSquareOperator() { 217 final Array2DRowRealMatrix a = new Array2DRowRealMatrix(2, 3); 218 final IterativeLinearSolver solver; 219 solver = new SymmLQ(10, 0., false); 220 final ArrayRealVector b = new ArrayRealVector(a.getRowDimension()); 221 final ArrayRealVector x = new ArrayRealVector(a.getColumnDimension()); 222 solver.solve(a, b, x); 223 } 224 225 @Test(expected = DimensionMismatchException.class) testDimensionMismatchRightHandSide()226 public void testDimensionMismatchRightHandSide() { 227 final Array2DRowRealMatrix a = new Array2DRowRealMatrix(3, 3); 228 final IterativeLinearSolver solver; 229 solver = new SymmLQ(10, 0., false); 230 final ArrayRealVector b = new ArrayRealVector(2); 231 solver.solve(a, b); 232 } 233 234 @Test(expected = DimensionMismatchException.class) testDimensionMismatchSolution()235 public void testDimensionMismatchSolution() { 236 final Array2DRowRealMatrix a = new Array2DRowRealMatrix(3, 3); 237 final IterativeLinearSolver solver; 238 solver = new SymmLQ(10, 0., false); 239 final ArrayRealVector b = new ArrayRealVector(3); 240 final ArrayRealVector x = new ArrayRealVector(2); 241 solver.solve(a, b, x); 242 } 243 244 @Test testUnpreconditionedSolution()245 public void testUnpreconditionedSolution() { 246 final int n = 5; 247 final int maxIterations = 100; 248 final RealLinearOperator a = new HilbertMatrix(n); 249 final InverseHilbertMatrix ainv = new InverseHilbertMatrix(n); 250 final IterativeLinearSolver solver; 251 solver = new SymmLQ(maxIterations, 1E-10, true); 252 final RealVector b = new ArrayRealVector(n); 253 for (int j = 0; j < n; j++) { 254 b.set(0.); 255 b.setEntry(j, 1.); 256 final RealVector x = solver.solve(a, b); 257 for (int i = 0; i < n; i++) { 258 final double actual = x.getEntry(i); 259 final double expected = ainv.getEntry(i, j); 260 final double delta = 1E-6 * FastMath.abs(expected); 261 final String msg = String.format("entry[%d][%d]", i, j); 262 Assert.assertEquals(msg, expected, actual, delta); 263 } 264 } 265 } 266 267 @Test testUnpreconditionedInPlaceSolutionWithInitialGuess()268 public void testUnpreconditionedInPlaceSolutionWithInitialGuess() { 269 final int n = 5; 270 final int maxIterations = 100; 271 final RealLinearOperator a = new HilbertMatrix(n); 272 final InverseHilbertMatrix ainv = new InverseHilbertMatrix(n); 273 final IterativeLinearSolver solver; 274 solver = new SymmLQ(maxIterations, 1E-10, true); 275 final RealVector b = new ArrayRealVector(n); 276 for (int j = 0; j < n; j++) { 277 b.set(0.); 278 b.setEntry(j, 1.); 279 final RealVector x0 = new ArrayRealVector(n); 280 x0.set(1.); 281 final RealVector x = solver.solveInPlace(a, b, x0); 282 Assert.assertSame("x should be a reference to x0", x0, x); 283 for (int i = 0; i < n; i++) { 284 final double actual = x.getEntry(i); 285 final double expected = ainv.getEntry(i, j); 286 final double delta = 1E-6 * FastMath.abs(expected); 287 final String msg = String.format("entry[%d][%d)", i, j); 288 Assert.assertEquals(msg, expected, actual, delta); 289 } 290 } 291 } 292 293 @Test testUnpreconditionedSolutionWithInitialGuess()294 public void testUnpreconditionedSolutionWithInitialGuess() { 295 final int n = 5; 296 final int maxIterations = 100; 297 final RealLinearOperator a = new HilbertMatrix(n); 298 final InverseHilbertMatrix ainv = new InverseHilbertMatrix(n); 299 final IterativeLinearSolver solver; 300 solver = new SymmLQ(maxIterations, 1E-10, true); 301 final RealVector b = new ArrayRealVector(n); 302 for (int j = 0; j < n; j++) { 303 b.set(0.); 304 b.setEntry(j, 1.); 305 final RealVector x0 = new ArrayRealVector(n); 306 x0.set(1.); 307 final RealVector x = solver.solve(a, b, x0); 308 Assert.assertNotSame("x should not be a reference to x0", x0, x); 309 for (int i = 0; i < n; i++) { 310 final double actual = x.getEntry(i); 311 final double expected = ainv.getEntry(i, j); 312 final double delta = 1E-6 * FastMath.abs(expected); 313 final String msg = String.format("entry[%d][%d]", i, j); 314 Assert.assertEquals(msg, expected, actual, delta); 315 Assert.assertEquals(msg, x0.getEntry(i), 1., Math.ulp(1.)); 316 } 317 } 318 } 319 320 @Test(expected = NonSquareOperatorException.class) testNonSquarePreconditioner()321 public void testNonSquarePreconditioner() { 322 final Array2DRowRealMatrix a = new Array2DRowRealMatrix(2, 2); 323 final RealLinearOperator m = new RealLinearOperator() { 324 325 @Override 326 public RealVector operate(final RealVector x) { 327 throw new UnsupportedOperationException(); 328 } 329 330 @Override 331 public int getRowDimension() { 332 return 2; 333 } 334 335 @Override 336 public int getColumnDimension() { 337 return 3; 338 } 339 }; 340 final PreconditionedIterativeLinearSolver solver; 341 solver = new SymmLQ(10, 0., false); 342 final ArrayRealVector b = new ArrayRealVector(a.getRowDimension()); 343 solver.solve(a, m, b); 344 } 345 346 @Test(expected = DimensionMismatchException.class) testMismatchedOperatorDimensions()347 public void testMismatchedOperatorDimensions() { 348 final Array2DRowRealMatrix a = new Array2DRowRealMatrix(2, 2); 349 final RealLinearOperator m = new RealLinearOperator() { 350 351 @Override 352 public RealVector operate(final RealVector x) { 353 throw new UnsupportedOperationException(); 354 } 355 356 @Override 357 public int getRowDimension() { 358 return 3; 359 } 360 361 @Override 362 public int getColumnDimension() { 363 return 3; 364 } 365 }; 366 final PreconditionedIterativeLinearSolver solver; 367 solver = new SymmLQ(10, 0d, false); 368 final ArrayRealVector b = new ArrayRealVector(a.getRowDimension()); 369 solver.solve(a, m, b); 370 } 371 372 @Test(expected = NonPositiveDefiniteOperatorException.class) testNonPositiveDefinitePreconditioner()373 public void testNonPositiveDefinitePreconditioner() { 374 final Array2DRowRealMatrix a = new Array2DRowRealMatrix(2, 2); 375 a.setEntry(0, 0, 1d); 376 a.setEntry(0, 1, 2d); 377 a.setEntry(1, 0, 3d); 378 a.setEntry(1, 1, 4d); 379 final RealLinearOperator m = new RealLinearOperator() { 380 381 @Override 382 public RealVector operate(final RealVector x) { 383 final ArrayRealVector y = new ArrayRealVector(2); 384 y.setEntry(0, -x.getEntry(0)); 385 y.setEntry(1, -x.getEntry(1)); 386 return y; 387 } 388 389 @Override 390 public int getRowDimension() { 391 return 2; 392 } 393 394 @Override 395 public int getColumnDimension() { 396 return 2; 397 } 398 }; 399 final PreconditionedIterativeLinearSolver solver; 400 solver = new SymmLQ(10, 0d, true); 401 final ArrayRealVector b = new ArrayRealVector(2); 402 b.setEntry(0, -1d); 403 b.setEntry(1, -1d); 404 solver.solve(a, m, b); 405 } 406 407 @Test testPreconditionedSolution()408 public void testPreconditionedSolution() { 409 final int n = 8; 410 final int maxIterations = 100; 411 final RealLinearOperator a = new HilbertMatrix(n); 412 final InverseHilbertMatrix ainv = new InverseHilbertMatrix(n); 413 final RealLinearOperator m = JacobiPreconditioner.create(a); 414 final PreconditionedIterativeLinearSolver solver; 415 solver = new SymmLQ(maxIterations, 1E-15, true); 416 final RealVector b = new ArrayRealVector(n); 417 for (int j = 0; j < n; j++) { 418 b.set(0.); 419 b.setEntry(j, 1.); 420 final RealVector x = solver.solve(a, m, b); 421 for (int i = 0; i < n; i++) { 422 final double actual = x.getEntry(i); 423 final double expected = ainv.getEntry(i, j); 424 final double delta = 1E-6 * FastMath.abs(expected); 425 final String msg = String.format("coefficient (%d, %d)", i, j); 426 Assert.assertEquals(msg, expected, actual, delta); 427 } 428 } 429 } 430 431 @Test testPreconditionedSolution2()432 public void testPreconditionedSolution2() { 433 final int n = 100; 434 final int maxIterations = 100000; 435 final Array2DRowRealMatrix a = new Array2DRowRealMatrix(n, n); 436 double daux = 1.; 437 for (int i = 0; i < n; i++) { 438 a.setEntry(i, i, daux); 439 daux *= 1.2; 440 for (int j = i + 1; j < n; j++) { 441 if (i == j) { 442 } else { 443 final double value = 1.0; 444 a.setEntry(i, j, value); 445 a.setEntry(j, i, value); 446 } 447 } 448 } 449 final RealLinearOperator m = JacobiPreconditioner.create(a); 450 final PreconditionedIterativeLinearSolver prec; 451 final IterativeLinearSolver unprec; 452 prec = new SymmLQ(maxIterations, 1E-15, true); 453 unprec = new SymmLQ(maxIterations, 1E-15, true); 454 final RealVector b = new ArrayRealVector(n); 455 final String pattern = "preconditioned SymmLQ (%d iterations) should" 456 + " have been faster than unpreconditioned (%d iterations)"; 457 String msg; 458 for (int j = 0; j < 1; j++) { 459 b.set(0.); 460 b.setEntry(j, 1.); 461 final RealVector px = prec.solve(a, m, b); 462 final RealVector x = unprec.solve(a, b); 463 final int np = prec.getIterationManager().getIterations(); 464 final int nup = unprec.getIterationManager().getIterations(); 465 msg = String.format(pattern, np, nup); 466 for (int i = 0; i < n; i++) { 467 msg = String.format("row %d, column %d", i, j); 468 final double expected = x.getEntry(i); 469 final double actual = px.getEntry(i); 470 final double delta = 5E-5 * FastMath.abs(expected); 471 Assert.assertEquals(msg, expected, actual, delta); 472 } 473 } 474 } 475 476 @Test testEventManagement()477 public void testEventManagement() { 478 final int n = 5; 479 final int maxIterations = 100; 480 final RealLinearOperator a = new HilbertMatrix(n); 481 final IterativeLinearSolver solver; 482 /* 483 * count[0] = number of calls to initializationPerformed 484 * count[1] = number of calls to iterationStarted 485 * count[2] = number of calls to iterationPerformed 486 * count[3] = number of calls to terminationPerformed 487 */ 488 final int[] count = new int[] {0, 0, 0, 0}; 489 final RealVector xFromListener = new ArrayRealVector(n); 490 final IterationListener listener = new IterationListener() { 491 492 public void initializationPerformed(final IterationEvent e) { 493 ++count[0]; 494 } 495 496 public void iterationPerformed(final IterationEvent e) { 497 ++count[2]; 498 Assert.assertEquals("iteration performed", 499 count[2], 500 e.getIterations() - 1); 501 } 502 503 public void iterationStarted(final IterationEvent e) { 504 ++count[1]; 505 Assert.assertEquals("iteration started", 506 count[1], 507 e.getIterations() - 1); 508 } 509 510 public void terminationPerformed(final IterationEvent e) { 511 ++count[3]; 512 final IterativeLinearSolverEvent ilse; 513 ilse = (IterativeLinearSolverEvent) e; 514 xFromListener.setSubVector(0, ilse.getSolution()); 515 } 516 }; 517 solver = new SymmLQ(maxIterations, 1E-10, true); 518 solver.getIterationManager().addIterationListener(listener); 519 final RealVector b = new ArrayRealVector(n); 520 for (int j = 0; j < n; j++) { 521 Arrays.fill(count, 0); 522 b.set(0.); 523 b.setEntry(j, 1.); 524 final RealVector xFromSolver = solver.solve(a, b); 525 String msg = String.format("column %d (initialization)", j); 526 Assert.assertEquals(msg, 1, count[0]); 527 msg = String.format("column %d (finalization)", j); 528 Assert.assertEquals(msg, 1, count[3]); 529 /* 530 * Check that solution is not "over-refined". When the last 531 * iteration has occurred, no further refinement should be 532 * performed. 533 */ 534 for (int i = 0; i < n; i++){ 535 msg = String.format("row %d, column %d", i, j); 536 final double expected = xFromSolver.getEntry(i); 537 final double actual = xFromListener.getEntry(i); 538 Assert.assertEquals(msg, expected, actual, 0.0); 539 } 540 } 541 } 542 543 @Test(expected = NonSelfAdjointOperatorException.class) testNonSelfAdjointOperator()544 public void testNonSelfAdjointOperator() { 545 final RealLinearOperator a; 546 a = new Array2DRowRealMatrix(new double[][] { 547 {1., 2., 3.}, 548 {2., 4., 5.}, 549 {2.999, 5., 6.} 550 }); 551 final RealVector b; 552 b = new ArrayRealVector(new double[] {1., 1., 1.}); 553 new SymmLQ(100, 1., true).solve(a, b); 554 } 555 556 @Test(expected = NonSelfAdjointOperatorException.class) testNonSelfAdjointPreconditioner()557 public void testNonSelfAdjointPreconditioner() { 558 final RealLinearOperator a = new Array2DRowRealMatrix(new double[][] { 559 {1., 2., 3.}, 560 {2., 4., 5.}, 561 {3., 5., 6.} 562 }); 563 final Array2DRowRealMatrix mMat; 564 mMat = new Array2DRowRealMatrix(new double[][] { 565 {1., 0., 1.}, 566 {0., 1., 0.}, 567 {0., 0., 1.} 568 }); 569 final DecompositionSolver mSolver; 570 mSolver = new LUDecomposition(mMat).getSolver(); 571 final RealLinearOperator minv = new RealLinearOperator() { 572 573 @Override 574 public RealVector operate(final RealVector x) { 575 return mSolver.solve(x); 576 } 577 578 @Override 579 public int getRowDimension() { 580 return mMat.getRowDimension(); 581 } 582 583 @Override 584 public int getColumnDimension() { 585 return mMat.getColumnDimension(); 586 } 587 }; 588 final RealVector b = new ArrayRealVector(new double[] { 589 1., 1., 1. 590 }); 591 new SymmLQ(100, 1., true).solve(a, minv, b); 592 } 593 594 @Test testUnpreconditionedNormOfResidual()595 public void testUnpreconditionedNormOfResidual() { 596 final int n = 5; 597 final int maxIterations = 100; 598 final RealLinearOperator a = new HilbertMatrix(n); 599 final IterativeLinearSolver solver; 600 final IterationListener listener = new IterationListener() { 601 602 private void doTestNormOfResidual(final IterationEvent e) { 603 final IterativeLinearSolverEvent evt; 604 evt = (IterativeLinearSolverEvent) e; 605 final RealVector x = evt.getSolution(); 606 final RealVector b = evt.getRightHandSideVector(); 607 final RealVector r = b.subtract(a.operate(x)); 608 final double rnorm = r.getNorm(); 609 Assert.assertEquals("iteration performed (residual)", 610 rnorm, evt.getNormOfResidual(), 611 FastMath.max(1E-5 * rnorm, 1E-10)); 612 } 613 614 public void initializationPerformed(final IterationEvent e) { 615 doTestNormOfResidual(e); 616 } 617 618 public void iterationPerformed(final IterationEvent e) { 619 doTestNormOfResidual(e); 620 } 621 622 public void iterationStarted(final IterationEvent e) { 623 doTestNormOfResidual(e); 624 } 625 626 public void terminationPerformed(final IterationEvent e) { 627 doTestNormOfResidual(e); 628 } 629 }; 630 solver = new SymmLQ(maxIterations, 1E-10, true); 631 solver.getIterationManager().addIterationListener(listener); 632 final RealVector b = new ArrayRealVector(n); 633 for (int j = 0; j < n; j++) { 634 b.set(0.); 635 b.setEntry(j, 1.); 636 solver.solve(a, b); 637 } 638 } 639 640 @Test testPreconditionedNormOfResidual()641 public void testPreconditionedNormOfResidual() { 642 final int n = 5; 643 final int maxIterations = 100; 644 final RealLinearOperator a = new HilbertMatrix(n); 645 final JacobiPreconditioner m = JacobiPreconditioner.create(a); 646 final RealLinearOperator p = m.sqrt(); 647 final PreconditionedIterativeLinearSolver solver; 648 final IterationListener listener = new IterationListener() { 649 650 private void doTestNormOfResidual(final IterationEvent e) { 651 final IterativeLinearSolverEvent evt; 652 evt = (IterativeLinearSolverEvent) e; 653 final RealVector x = evt.getSolution(); 654 final RealVector b = evt.getRightHandSideVector(); 655 final RealVector r = b.subtract(a.operate(x)); 656 final double rnorm = p.operate(r).getNorm(); 657 Assert.assertEquals("iteration performed (residual)", 658 rnorm, evt.getNormOfResidual(), 659 FastMath.max(1E-5 * rnorm, 1E-10)); 660 } 661 662 public void initializationPerformed(final IterationEvent e) { 663 doTestNormOfResidual(e); 664 } 665 666 public void iterationPerformed(final IterationEvent e) { 667 doTestNormOfResidual(e); 668 } 669 670 public void iterationStarted(final IterationEvent e) { 671 doTestNormOfResidual(e); 672 } 673 674 public void terminationPerformed(final IterationEvent e) { 675 doTestNormOfResidual(e); 676 } 677 }; 678 solver = new SymmLQ(maxIterations, 1E-10, true); 679 solver.getIterationManager().addIterationListener(listener); 680 final RealVector b = new ArrayRealVector(n); 681 for (int j = 0; j < n; j++) { 682 b.set(0.); 683 b.setEntry(j, 1.); 684 solver.solve(a, m, b); 685 } 686 } 687 } 688 689