From c70ebe6544d3a03dd950007bbfbdfd145ff31ff0 Mon Sep 17 00:00:00 2001 From: Elias Pipping <elias.pipping@fu-berlin.de> Date: Wed, 7 Sep 2011 15:43:36 +0200 Subject: [PATCH] Directional derivatives only for unit vectors --- src/bisection-example-flexible.cc | 28 +++++++++++++++++++++------- src/bisection-example.cc | 25 +++++++++++++++++++------ 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/src/bisection-example-flexible.cc b/src/bisection-example-flexible.cc index e8add65b..61398aee 100644 --- a/src/bisection-example-flexible.cc +++ b/src/bisection-example-flexible.cc @@ -34,12 +34,11 @@ class SampleFunctional { return y * v + func_(v.two_norm()); // <1/2 Av - b,v> + H(|v|) } - double directionalDerivative(const SmallVector x, - const SmallVector dir) const { + // |dir|-times the directional derivative wrt dir/|dir|. + double pseudoDirectionalDerivative(const SmallVector x, + const SmallVector dir) const { if (x == SmallVector(0.0)) - // FIXME: Well, not in this way -- but can we compute them? - DUNE_THROW(Dune::Exception, - "Directional derivatives cannot be computed at zero."); + return func_.rightDifferential(0) * dir.two_norm(); if (x * dir > 0) return PlusGrad(x) * dir; @@ -47,6 +46,20 @@ class SampleFunctional { return MinusGrad(x) * dir; } + double directionalDerivative(const SmallVector x, + const SmallVector dir) const { + double norm = dir.two_norm(); + + if (norm == 0) + DUNE_THROW(Dune::Exception, "Directional derivatives cannot be computed " + "w.r.t. the zero-direction."); + + SmallVector tmp = dir; + tmp /= norm; + + return pseudoDirectionalDerivative(x, tmp); + } + SmallVector minimise(const SmallVector x, unsigned int iterations) const { SmallVector descDir = ModifiedGradient(x); if (descDir == SmallVector(0.0)) @@ -160,6 +173,7 @@ class SampleFunctional { return ret; } + // No normalising is done! SmallVector project(const SmallVector z, const SmallVector x) const { SmallVector y = z; y.axpy(-(z * x) / x.two_norm2(), x); @@ -183,7 +197,7 @@ void testSampleFunction() { SampleFunctional J(A, b); std::cout << J.directionalDerivative(b, b) << std::endl; - assert(J.directionalDerivative(b, b) == 10 + 2 * sqrt(5)); + assert(J.pseudoDirectionalDerivative(b, b) == 10 + 2 * sqrt(5)); SampleFunctional::SmallVector start = b; start *= 17; @@ -209,7 +223,7 @@ void testTrivialFunction() { SampleFunctional J(A, b); std::cout << J.directionalDerivative(b, b) << std::endl; - assert(J.directionalDerivative(b, b) == 10); + assert(J.pseudoDirectionalDerivative(b, b) == 10); SampleFunctional::SmallVector start = b; start *= 17; diff --git a/src/bisection-example.cc b/src/bisection-example.cc index 1ae3c95e..37c345ba 100644 --- a/src/bisection-example.cc +++ b/src/bisection-example.cc @@ -32,12 +32,11 @@ template <int dimension> class SampleFunctional { return y * v + H(v.two_norm()); // <1/2 Av - b,v> + H(|v|) } - double directionalDerivative(const SmallVector x, - const SmallVector dir) const { + // |dir|-times the directional derivative wrt dir/|dir|. + double pseudoDirectionalDerivative(const SmallVector x, + const SmallVector dir) const { if (x == SmallVector(0.0)) - // Well, not in this way -- but can we compute them? - DUNE_THROW(Dune::Exception, - "Directional derivatives cannot be computed at zero."); + return HPrimePlus(0) * dir.two_norm(); if (x * dir > 0) return PlusGrad(x) * dir; @@ -45,6 +44,19 @@ template <int dimension> class SampleFunctional { return MinusGrad(x) * dir; } + double directionalDerivative(const SmallVector x, + const SmallVector dir) const { + double norm = dir.two_norm(); + + if (norm == 0) + DUNE_THROW(Dune::Exception, "Directional derivatives cannot be computed " + "w.r.t. the zero-direction."); + + SmallVector tmp = dir; + tmp /= norm; + return pseudoDirectionalDerivative(x, tmp); + } + SmallVector minimise(const SmallVector x, unsigned int iterations) const { SmallVector descDir = ModifiedGradient(x); @@ -153,6 +165,7 @@ template <int dimension> class SampleFunctional { return ret; } + // No normalising is done! SmallVector project(const SmallVector z, const SmallVector x) const { SmallVector y = z; y.axpy(-(z * x) / x.two_norm2(), x); @@ -177,7 +190,7 @@ int main() { SampleFunctional J(A, b); std::cout << J.directionalDerivative(b, b) << std::endl; - assert(J.directionalDerivative(b, b) == 10 + 2 * sqrt(5)); + assert(J.pseudoDirectionalDerivative(b, b) == 10 + 2 * sqrt(5)); SampleFunctional::SmallVector start = b; start *= 17; -- GitLab