From ffaa622afd1dd22ab459bc8a538e127f35890c8c Mon Sep 17 00:00:00 2001 From: Eugene Toder Date: Thu, 14 Nov 2024 12:52:52 -0500 Subject: [PATCH] Make fewer copies of arrays --- ql/math/optimization/levenbergmarquardt.cpp | 28 ++++++++++----------- ql/math/optimization/levenbergmarquardt.hpp | 6 ++--- ql/math/optimization/problem.hpp | 4 +-- ql/termstructures/globalbootstrap.hpp | 9 ++----- 4 files changed, 19 insertions(+), 28 deletions(-) diff --git a/ql/math/optimization/levenbergmarquardt.cpp b/ql/math/optimization/levenbergmarquardt.cpp index 23015289fd2..fff0176de1e 100644 --- a/ql/math/optimization/levenbergmarquardt.cpp +++ b/ql/math/optimization/levenbergmarquardt.cpp @@ -36,17 +36,16 @@ namespace QuantLib { EndCriteria::Type LevenbergMarquardt::minimize(Problem& P, const EndCriteria& endCriteria) { P.reset(); - Array x_ = P.currentValue(); + const Array& initX = P.currentValue(); currentProblem_ = &P; - initCostValues_ = P.costFunction().values(x_); + initCostValues_ = P.costFunction().values(initX); int m = initCostValues_.size(); - int n = x_.size(); - if(useCostFunctionsJacobian_) { + int n = initX.size(); + if (useCostFunctionsJacobian_) { initJacobian_ = Matrix(m,n); - P.costFunction().jacobian(initJacobian_, x_); + P.costFunction().jacobian(initJacobian_, initX); } - std::unique_ptr xx(new Real[n]); - std::copy(x_.begin(), x_.end(), xx.get()); + Array xx = initX; std::unique_ptr fvec(new Real[m]); std::unique_ptr diag(new Real[n]); int mode = 1; @@ -81,15 +80,15 @@ namespace QuantLib { // in n variables by the Levenberg-Marquardt algorithm. MINPACK::LmdifCostFunction lmdifCostFunction = [this](const auto m, const auto n, const auto x, const auto fvec, const auto iflag) { - this->fcn(m, n, x, fvec, iflag); + this->fcn(m, n, x, fvec); }; MINPACK::LmdifCostFunction lmdifJacFunction = useCostFunctionsJacobian_ ? [this](const auto m, const auto n, const auto x, const auto fjac, const auto iflag) { - this->jacFcn(m, n, x, fjac, iflag); + this->jacFcn(m, n, x, fjac); } : MINPACK::LmdifCostFunction(); - MINPACK::lmdif(m, n, xx.get(), fvec.get(), + MINPACK::lmdif(m, n, xx.begin(), fvec.get(), endCriteria.functionEpsilon(), xtol_, gtol_, @@ -132,14 +131,13 @@ namespace QuantLib { QL_FAIL("unknown MINPACK result: " << info); } // set problem - std::copy(xx.get(), xx.get()+n, x_.begin()); - P.setCurrentValue(x_); - P.setFunctionValue(P.costFunction().value(x_)); + P.setCurrentValue(std::move(xx)); + P.setFunctionValue(P.costFunction().value(P.currentValue())); return ecType; } - void LevenbergMarquardt::fcn(int, int n, Real* x, Real* fvec, int*) { + void LevenbergMarquardt::fcn(int, int n, Real* x, Real* fvec) { Array xt(n); std::copy(x, x+n, xt.begin()); // constraint handling needs some improvement in the future: @@ -152,7 +150,7 @@ namespace QuantLib { } } - void LevenbergMarquardt::jacFcn(int m, int n, Real* x, Real* fjac, int*) { + void LevenbergMarquardt::jacFcn(int m, int n, Real* x, Real* fjac) { Array xt(n); std::copy(x, x+n, xt.begin()); // constraint handling needs some improvement in the future: diff --git a/ql/math/optimization/levenbergmarquardt.hpp b/ql/math/optimization/levenbergmarquardt.hpp index 6e60f1f44bc..142339e2a3f 100644 --- a/ql/math/optimization/levenbergmarquardt.hpp +++ b/ql/math/optimization/levenbergmarquardt.hpp @@ -58,13 +58,11 @@ namespace QuantLib { void fcn(int m, int n, Real* x, - Real* fvec, - int* iflag); + Real* fvec); void jacFcn(int m, int n, Real* x, - Real* fjac, - int* iflag); + Real* fjac); /*! \deprecated Don't use this method; inspect the result of minimize instead. Deprecated in version 1.36. diff --git a/ql/math/optimization/problem.hpp b/ql/math/optimization/problem.hpp index ea13f461b42..2b5ae15b595 100644 --- a/ql/math/optimization/problem.hpp +++ b/ql/math/optimization/problem.hpp @@ -73,8 +73,8 @@ namespace QuantLib { //! Cost function CostFunction& costFunction() const { return costFunction_; } - void setCurrentValue(const Array& currentValue) { - currentValue_=currentValue; + void setCurrentValue(Array currentValue) { + currentValue_ = std::move(currentValue); } //! current value of the local minimum diff --git a/ql/termstructures/globalbootstrap.hpp b/ql/termstructures/globalbootstrap.hpp index 4d39501ee37..2dc55352da1 100644 --- a/ql/termstructures/globalbootstrap.hpp +++ b/ql/termstructures/globalbootstrap.hpp @@ -272,12 +272,6 @@ template void GlobalBootstrap::calculate() const { return std::tan((y - lowerBounds_[i]) * M_PI / (upperBounds_[i] - lowerBounds_[i]) - M_PI_2); } - Real value(const Array& x) const override { - Array v = values(x); - std::transform(v.begin(), v.end(), v.begin(), [](Real x) -> Real { return x*x; }); - return std::sqrt(std::accumulate(v.begin(), v.end(), Real(0.0)) / static_cast(v.size())); - } - Array values(const Array& x) const override { for (Size i = 0; i < x.size(); ++i) { Traits::updateGuess(ts_->data_, transformDirect(x[i], i), i + 1); @@ -304,7 +298,8 @@ template void GlobalBootstrap::calculate() const { Curve *ts_; const std::vector lowerBounds_, upperBounds_; }; - TargetFunction cost(firstHelper_, numberHelpers_, additionalErrors_, ts_, lowerBounds, upperBounds); + TargetFunction cost(firstHelper_, numberHelpers_, additionalErrors_, ts_, + std::move(lowerBounds), std::move(upperBounds)); // setup guess Array guess(numberBounds);