You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ce...@apache.org on 2012/02/01 03:22:00 UTC

svn commit: r1238905 - in /commons/proper/math/trunk/src: main/java/org/apache/commons/math/linear/ test/java/org/apache/commons/math/linear/

Author: celestin
Date: Wed Feb  1 02:22:00 2012
New Revision: 1238905

URL: http://svn.apache.org/viewvc?rev=1238905&view=rev
Log:
In o.a.c.m.linear
- Removed tagging interface ProvidesResidual
- added double IterativeLinearSolverEvent.getNormOfResidual()
- added RealVector IterativeLinearSolverEvent.getResidual() (optional operation)
- added boolean IterativeLinearSolverEvent.providesResidual()
- added default implementation DefaultIterativeLinearSolverEvent
see MATH-735.

Added:
    commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/DefaultIterativeLinearSolverEvent.java   (with props)
Removed:
    commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/ProvidesResidual.java
Modified:
    commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/ConjugateGradient.java
    commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/IterativeLinearSolverEvent.java
    commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/ConjugateGradientTest.java

Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/ConjugateGradient.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/ConjugateGradient.java?rev=1238905&r1=1238904&r2=1238905&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/ConjugateGradient.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/ConjugateGradient.java Wed Feb  1 02:22:00 2012
@@ -79,78 +79,6 @@ import org.apache.commons.math.util.Iter
 public class ConjugateGradient
     extends PreconditionedIterativeLinearSolver {
 
-    /**
-     * The type of all events fired by this implementation of the Conjugate
-     * Gradient method.
-     *
-     * @version $Id: ConjugateGradient.java 1175404 2011-09-25 14:48:18Z
-     * celestin $
-     */
-    public static class ConjugateGradientEvent
-        extends IterativeLinearSolverEvent
-        implements ProvidesResidual {
-
-        /** */
-        private static final long serialVersionUID = 20120128L;
-
-        /** The right-hand side vector. */
-        private final RealVector b;
-
-        /** The current estimate of the residual. */
-        private final RealVector r;
-
-        /** The current estimate of the norm of the residual. */
-        private final double rnorm;
-
-        /** The current estimate of the solution. */
-        private final RealVector x;
-
-        /**
-         * Creates a new instance of this class.
-         *
-         * @param source the iterative algorithm on which the event initially
-         * occurred
-         * @param iterations the number of iterations performed at the time
-         * {@code this} event is created
-         * @param x the current estimate of the solution
-         * @param b the right-hand side vector
-         * @param r the current estimate of the residual
-         * @param rnorm the norm of the current estimate of the residual
-         */
-        public ConjugateGradientEvent(final Object source, final int iterations,
-            final RealVector x, final RealVector b, final RealVector r,
-            final double rnorm) {
-            super(source, iterations);
-            this.x = RealVector.unmodifiableRealVector(x);
-            this.b = RealVector.unmodifiableRealVector(b);
-            this.r = RealVector.unmodifiableRealVector(r);
-            this.rnorm = rnorm;
-        }
-
-        /** {@inheritDoc} */
-        @Override
-        public double getNormOfResidual() {
-            return rnorm;
-        }
-
-        /** {@inheritDoc} */
-        public RealVector getResidual() {
-            return r;
-        }
-
-        /** {@inheritDoc} */
-        @Override
-        public RealVector getRightHandSideVector() {
-            return b;
-        }
-
-        /** {@inheritDoc} */
-        @Override
-        public RealVector getSolution() {
-            return x;
-        }
-    }
-
     /** Key for the <a href="#context">exception context</a>. */
     public static final String OPERATOR = "operator";
 
@@ -219,6 +147,7 @@ public class ConjugateGradient
         // Initialization of default stopping criterion
         manager.resetIterationCount();
         final double rmax = delta * b.getNorm();
+        final RealVector bro = RealVector.unmodifiableRealVector(b);
 
         // Initialization phase counts as one iteration.
         manager.incrementIterationCount();
@@ -226,10 +155,12 @@ public class ConjugateGradient
         // of x is optimized for the calculation of the matrix-vector product
         // A.x.
         final RealVector x = x0;
+        final RealVector xro = RealVector.unmodifiableRealVector(x);
         final RealVector p = x.copy();
         RealVector q = a.operate(p);
 
         final RealVector r = b.combine(1, -1, q);
+        final RealVector rro = RealVector.unmodifiableRealVector(r);
         double rnorm = r.getNorm();
         RealVector z;
         if (minv == null) {
@@ -238,7 +169,8 @@ public class ConjugateGradient
             z = null;
         }
         IterativeLinearSolverEvent evt;
-        evt = new ConjugateGradientEvent(this, manager.getIterations(), x, b, r, rnorm);
+        evt = new DefaultIterativeLinearSolverEvent(this,
+            manager.getIterations(), xro, bro, rro, rnorm);
         manager.fireInitializationEvent(evt);
         if (rnorm <= rmax) {
             manager.fireTerminationEvent(evt);
@@ -247,7 +179,8 @@ public class ConjugateGradient
         double rhoPrev = 0.;
         while (true) {
             manager.incrementIterationCount();
-            evt = new ConjugateGradientEvent(this, manager.getIterations(), x, b, r, rnorm);
+            evt = new DefaultIterativeLinearSolverEvent(this,
+                manager.getIterations(), xro, bro, rro, rnorm);
             manager.fireIterationStartedEvent(evt);
             if (minv != null) {
                 z = minv.operate(r);
@@ -281,7 +214,8 @@ public class ConjugateGradient
             r.combineToSelf(1., -alpha, q);
             rhoPrev = rhoNext;
             rnorm = r.getNorm();
-            evt = new ConjugateGradientEvent(this, manager.getIterations(), x, b, r, rnorm);
+            evt = new DefaultIterativeLinearSolverEvent(this,
+                manager.getIterations(), xro, bro, rro, rnorm);
             manager.fireIterationPerformedEvent(evt);
             if (rnorm <= rmax) {
                 manager.fireTerminationEvent(evt);

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/DefaultIterativeLinearSolverEvent.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/DefaultIterativeLinearSolverEvent.java?rev=1238905&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/DefaultIterativeLinearSolverEvent.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/DefaultIterativeLinearSolverEvent.java Wed Feb  1 02:22:00 2012
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math.linear;
+
+import org.apache.commons.math.exception.MathUnsupportedOperationException;
+
+/**
+ * A default concrete implementation of the abstract class
+ * {@link IterativeLinearSolverEvent}.
+ *
+ * @version $Id$
+ */
+public class DefaultIterativeLinearSolverEvent extends IterativeLinearSolverEvent {
+
+    /** */
+    private static final long serialVersionUID = 20120129L;
+
+    /** The right-hand side vector. */
+    private final RealVector b;
+
+    /** The current estimate of the residual. */
+    private final RealVector r;
+
+    /** The current estimate of the norm of the residual. */
+    private final double rnorm;
+
+    /** The current estimate of the solution. */
+    private final RealVector x;
+
+    /**
+     * Creates a new instance of this class. This implementation does
+     * <em>not</em> deep copy the specified vectors {@code x}, {@code b},
+     * {@code r}. Therefore the user must make sure that these vectors are
+     * either unmodifiable views or deep copies of the same vectors actually
+     * used by the {@code source}. Failure to do so may compromise subsequent
+     * iterations of the {@code source}. If the residual vector {@code r} is
+     * {@code null}, then {@link #getResidual()} throws a
+     * {@link MathUnsupportedOperationException}, and
+     * {@link #providesResidual()} returns {@code false}.
+     *
+     * @param source the iterative solver which fired this event
+     * @param iterations the number of iterations performed at the time
+     * {@code this} event is created
+     * @param x the current estimate of the solution
+     * @param b the right-hand side vector
+     * @param r the current estimate of the residual (can be {@code null})
+     * @param rnorm the norm of the current estimate of the residual
+     */
+    public DefaultIterativeLinearSolverEvent(final Object source, final int iterations,
+        final RealVector x, final RealVector b, final RealVector r,
+        final double rnorm) {
+        super(source, iterations);
+        this.x = x;
+        this.b = b;
+        this.r = r;
+        this.rnorm = rnorm;
+    }
+
+    /**
+     * Creates a new instance of this class. This implementation does
+     * <em>not</em> deep copy the specified vectors {@code x}, {@code b}.
+     * Therefore the user must make sure that these vectors are either
+     * unmodifiable views or deep copies of the same vectors actually used by
+     * the {@code source}. Failure to do so may compromise subsequent iterations
+     * of the {@code source}. Callling {@link #getResidual()} on instances
+     * returned by this constructor throws a
+     * {@link MathUnsupportedOperationException}, while
+     * {@link #providesResidual()} returns {@code false}.
+     *
+     * @param source the iterative solver which fired this event
+     * @param iterations the number of iterations performed at the time
+     * {@code this} event is created
+     * @param x the current estimate of the solution
+     * @param b the right-hand side vector
+     * @param rnorm the norm of the current estimate of the residual
+     */
+    public DefaultIterativeLinearSolverEvent(final Object source, final int iterations,
+        final RealVector x, final RealVector b, final double rnorm) {
+        super(source, iterations);
+        this.x = x;
+        this.b = b;
+        this.r = null;
+        this.rnorm = rnorm;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public double getNormOfResidual() {
+        return rnorm;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * This implementation throws an {@link MathUnsupportedOperationException}
+     * if no residual vector {@code r} was provided at construction time.
+     */
+    public RealVector getResidual() {
+        if (r != null) {
+            return r;
+        }
+        throw new MathUnsupportedOperationException();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public RealVector getRightHandSideVector() {
+        return b;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public RealVector getSolution() {
+        return x;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * This implementation returns {@code true} if a non-{@code null} value was
+     * specified for the residual vector {@code r} at construction time.
+     *
+     * @return {@code true} if {@code r != null}
+     */
+    @Override
+    public boolean providesResidual() {
+        return r != null;
+    }
+}

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/DefaultIterativeLinearSolverEvent.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/DefaultIterativeLinearSolverEvent.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/IterativeLinearSolverEvent.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/IterativeLinearSolverEvent.java?rev=1238905&r1=1238904&r2=1238905&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/IterativeLinearSolverEvent.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/IterativeLinearSolverEvent.java Wed Feb  1 02:22:00 2012
@@ -29,7 +29,7 @@ public abstract class IterativeLinearSol
     extends IterationEvent {
 
     /** */
-    private static final long serialVersionUID = 20120128L;
+    private static final long serialVersionUID = 20120129L;
 
     /**
      * Creates a new instance of this class.
@@ -71,6 +71,29 @@ public abstract class IterativeLinearSol
     public abstract double getNormOfResidual();
 
     /**
+     * <p>
+     * Returns the residual. This is an optional operation, as all iterative
+     * linear solvers do not provide cheap estimate of the updated residual
+     * vector, in which case
+     * </p>
+     * <ul>
+     * <li>this method should throw a
+     * {@link MathUnsupportedOperationException},</li>
+     * <li>{@link #providesResidual()} returns {@code false}.</li>
+     * </ul>
+     * <p>
+     * The default implementation throws a
+     * {@link MathUnsupportedOperationException}. If this method is overriden,
+     * then {@link #providesResidual()} should be overriden as well.
+     * </p>
+     *
+     * @return the updated residual, r
+     */
+    public RealVector getResidual() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
      * Returns the current estimate of the solution to the linear system to be
      * solved. This method should return an unmodifiable view, or a deep copy of
      * the actual current solution, in order not to compromise subsequent
@@ -79,4 +102,15 @@ public abstract class IterativeLinearSol
      * @return the solution, x
      */
     public abstract RealVector getSolution();
+
+    /**
+     * Returns {@code true} if {@link #getResidual()} is supported. The default
+     * implementation returns {@code false}.
+     *
+     * @return {@code false} if {@link #getResidual()} throws a
+     * {@link MathUnsupportedOperationException}
+     */
+    public boolean providesResidual() {
+        return false;
+    }
 }

Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/ConjugateGradientTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/ConjugateGradientTest.java?rev=1238905&r1=1238904&r2=1238905&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/ConjugateGradientTest.java (original)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/ConjugateGradientTest.java Wed Feb  1 02:22:00 2012
@@ -19,6 +19,7 @@ package org.apache.commons.math.linear;
 import java.util.Arrays;
 
 import org.apache.commons.math.exception.DimensionMismatchException;
+import org.apache.commons.math.exception.MathUnsupportedOperationException;
 import org.apache.commons.math.exception.MaxCountExceededException;
 import org.apache.commons.math.util.FastMath;
 import org.apache.commons.math.util.IterationEvent;
@@ -176,9 +177,11 @@ public class ConjugateGradientTest {
             }
 
             public void iterationPerformed(final IterationEvent e) {
-                RealVector v = ((ProvidesResidual) e).getResidual();
+                final IterativeLinearSolverEvent evt;
+                evt = (IterativeLinearSolverEvent) e;
+                RealVector v = evt.getResidual();
                 r.setSubVector(0, v);
-                v = ((IterativeLinearSolverEvent) e).getSolution();
+                v = evt.getSolution();
                 x.setSubVector(0, v);
             }
 
@@ -345,9 +348,11 @@ public class ConjugateGradientTest {
             }
 
             public void iterationPerformed(final IterationEvent e) {
-                RealVector v = ((ProvidesResidual)e).getResidual();
+                final IterativeLinearSolverEvent evt;
+                evt = (IterativeLinearSolverEvent) e;
+                RealVector v = evt.getResidual();
                 r.setSubVector(0, v);
-                v = ((IterativeLinearSolverEvent) e).getSolution();
+                v = evt.getSolution();
                 x.setSubVector(0, v);
             }
 
@@ -443,24 +448,51 @@ public class ConjugateGradientTest {
          */
         final int[] count = new int[] {0, 0, 0, 0};
         final IterationListener listener = new IterationListener() {
+            private void doTestVectorsAreUnmodifiable(final IterationEvent e) {
+                final IterativeLinearSolverEvent evt;
+                evt = (IterativeLinearSolverEvent) e;
+                try {
+                    evt.getResidual().set(0.0);
+                    Assert.fail("r is modifiable");
+                } catch (MathUnsupportedOperationException exc){
+                    // Expected behavior
+                }
+                try {
+                    evt.getRightHandSideVector().set(0.0);
+                    Assert.fail("b is modifiable");
+                } catch (MathUnsupportedOperationException exc){
+                    // Expected behavior
+                }
+                try {
+                    evt.getSolution().set(0.0);
+                    Assert.fail("x is modifiable");
+                } catch (MathUnsupportedOperationException exc){
+                    // Expected behavior
+                }
+            }
+
             public void initializationPerformed(final IterationEvent e) {
                 ++count[0];
+                doTestVectorsAreUnmodifiable(e);
             }
 
             public void iterationPerformed(final IterationEvent e) {
                 ++count[2];
                 Assert.assertEquals("iteration performed",
                     count[2], e.getIterations() - 1);
+                doTestVectorsAreUnmodifiable(e);
             }
 
             public void iterationStarted(final IterationEvent e) {
                 ++count[1];
                 Assert.assertEquals("iteration started",
                     count[1], e.getIterations() - 1);
+                doTestVectorsAreUnmodifiable(e);
             }
 
             public void terminationPerformed(final IterationEvent e) {
                 ++count[3];
+                doTestVectorsAreUnmodifiable(e);
             }
         };
         solver = new ConjugateGradient(maxIterations, 1E-10, true);