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