From 8fe7f1c7837bcc0c29c956843ddac0f3350bcefe Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Wed, 7 Dec 2022 16:59:17 -0700 Subject: [PATCH 01/65] Fixed issue causing infinite loop on rare occasion. --- .../TypeB/ROL_TypeB_LinMoreAlgorithm_Def.hpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/rol/src/algorithm/TypeB/ROL_TypeB_LinMoreAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeB/ROL_TypeB_LinMoreAlgorithm_Def.hpp index ebd3c0c20fc7..393f217b6bd0 100644 --- a/packages/rol/src/algorithm/TypeB/ROL_TypeB_LinMoreAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeB/ROL_TypeB_LinMoreAlgorithm_Def.hpp @@ -371,7 +371,6 @@ Real LinMoreAlgorithm::dcauchy(Vector &s, Vector &dwa, Vector &dwa1, std::ostream &outStream) { const Real half(0.5); - // const Real zero(0); // Unused Real tol = std::sqrt(ROL_EPSILON()); bool interp = false; Real gs(0), snorm(0); @@ -383,7 +382,6 @@ Real LinMoreAlgorithm::dcauchy(Vector &s, else { model.hessVec(dwa,s,x,tol); nhess_++; gs = s.dot(g); - //q = half * s.dot(dwa.dual()) + gs; q = half * s.apply(dwa) + gs; interp = (q > mu0_*gs); } @@ -391,18 +389,21 @@ Real LinMoreAlgorithm::dcauchy(Vector &s, int cnt = 0; if (interp) { bool search = true; - while (search) { + while (search && cnt < redlim_) { alpha *= interpf_; - snorm = dgpstep(s,g,x,-alpha,outStream); + snorm = dgpstep(s,g,x,-alpha,outStream); if (snorm <= del) { model.hessVec(dwa,s,x,tol); nhess_++; gs = s.dot(g); - //q = half * s.dot(dwa.dual()) + gs; q = half * s.apply(dwa) + gs; - search = (q > mu0_*gs) && (cnt < redlim_); + search = (q > mu0_*gs); } cnt++; } + if (cnt >= redlim_ && q > mu0_*gs) { + outStream << "Cauchy point: The interpolation limit was met without producing sufficient decrease." << std::endl; + outStream << " Lin-More trust-region algorithm may not converge!" << std::endl; + } } else { bool search = true; @@ -411,11 +412,10 @@ Real LinMoreAlgorithm::dcauchy(Vector &s, dwa1.set(dwa); while (search) { alpha *= extrapf_; - snorm = dgpstep(s,g,x,-alpha,outStream); + snorm = dgpstep(s,g,x,-alpha,outStream); if (snorm <= del && cnt < explim_) { model.hessVec(dwa,s,x,tol); nhess_++; gs = s.dot(g); - //q = half * s.dot(dwa.dual()) + gs; q = half * s.apply(dwa) + gs; if (q <= mu0_*gs && std::abs(q-qs) > qtol_*std::abs(qs)) { dwa1.set(dwa); From 625c0ce36a1f35b2e87fba67af0e8b6f95b5319e Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Thu, 15 Dec 2022 09:23:36 -0700 Subject: [PATCH 02/65] Removed unistd.h include. --- .../rol/src/algorithm/TypeB/ROL_TypeB_LSecantBAlgorithm_Def.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/rol/src/algorithm/TypeB/ROL_TypeB_LSecantBAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeB/ROL_TypeB_LSecantBAlgorithm_Def.hpp index 687de9bac171..e0114b087e28 100644 --- a/packages/rol/src/algorithm/TypeB/ROL_TypeB_LSecantBAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeB/ROL_TypeB_LSecantBAlgorithm_Def.hpp @@ -44,7 +44,6 @@ #ifndef ROL_TYPEB_LSecantBALGORITHM_DEF_HPP #define ROL_TYPEB_LSecantBALGORITHM_DEF_HPP -#include "unistd.h" namespace ROL { namespace TypeB { From 7c13802b70f32b2a66777393d0563682a1260d95 Mon Sep 17 00:00:00 2001 From: Bobby Date: Tue, 20 Dec 2022 17:01:50 -0700 Subject: [PATCH 03/65] proximal gradient implementation with l1 norm --- packages/rol/src/CMakeLists.txt | 2 + .../algorithm/TypeP/ROL_TypeP_Algorithm.hpp | 157 ++++++++ .../TypeP/ROL_TypeP_Algorithm_Def.hpp | 184 +++++++++ .../TypeP/ROL_TypeP_ProxGradientAlgorithm.hpp | 98 +++++ .../ROL_TypeP_ProxGradientAlgorithm_Def.hpp | 367 ++++++++++++++++++ .../src/function/objective/ROL_Objective.hpp | 9 + .../function/objective/ROL_l1Objective.hpp | 111 ++++++ packages/rol/test/algorithm/CMakeLists.txt | 1 + .../rol/test/algorithm/TypeP/CMakeLists.txt | 18 + packages/rol/test/algorithm/TypeP/input.xml | 201 ++++++++++ packages/rol/test/algorithm/TypeP/test_01.cpp | 195 ++++++++++ 11 files changed, 1343 insertions(+) create mode 100644 packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm.hpp create mode 100644 packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm_Def.hpp create mode 100644 packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm.hpp create mode 100644 packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp create mode 100644 packages/rol/src/function/objective/ROL_l1Objective.hpp create mode 100644 packages/rol/test/algorithm/TypeP/CMakeLists.txt create mode 100644 packages/rol/test/algorithm/TypeP/input.xml create mode 100644 packages/rol/test/algorithm/TypeP/test_01.cpp diff --git a/packages/rol/src/CMakeLists.txt b/packages/rol/src/CMakeLists.txt index 9655e38cd0c3..00eb7dd9041b 100644 --- a/packages/rol/src/CMakeLists.txt +++ b/packages/rol/src/CMakeLists.txt @@ -153,6 +153,7 @@ INCLUDE_DIRECTORIES(${DIR} ${DIR}/TypeE ${DIR}/TypeG ${DIR}/TypeU + ${DIR}/TypeP ${DIR}/TypeB/pqn ${DIR}/TypeG/augmentedlagrangian/ ${DIR}/TypeG/fletcher @@ -168,6 +169,7 @@ APPEND_GLOB(HEADERS ${DIR}/*.hpp ${DIR}/TypeE/*.hpp ${DIR}/TypeG/*.hpp ${DIR}/TypeU/*.hpp + ${DIR}/TypeP/*.hpp ${DIR}/TypeB/pqn/*.hpp ${DIR}/TypeG/augmentedlagrangian/*.hpp ${DIR}/TypeG/fletcher/*.hpp diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm.hpp new file mode 100644 index 000000000000..a6dc0d84dd4a --- /dev/null +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm.hpp @@ -0,0 +1,157 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +#ifndef ROL_TYPEP_ALGORITHM_H +#define ROL_TYPEP_ALGORITHM_H + +#include "ROL_CombinedStatusTest.hpp" +#include "ROL_Objective.hpp" +#include "ROL_Problem.hpp" + +/** \class ROL::TypeP::Algorithm + \brief Provides an interface to run optimization algorithms to minimize composite optimization problems f+phi. +*/ + +namespace ROL { +namespace TypeP { + +template +struct AlgorithmState : public ROL::AlgorithmState { + Real searchSize, phival; + Ptr> stepVec; + Ptr> gradientVec; + int nprox; + int nphi; + + AlgorithmState() + : searchSize(1), + phival(ROL_INF()), + stepVec(nullPtr), + gradientVec(nullPtr), + nprox(0), + nphi(0) {} + + void reset() { + ROL::AlgorithmState::reset(); + searchSize = static_cast(1); + phival = ROL_INF(); + if (stepVec != nullPtr) { + stepVec->zero(); + } + if (gradientVec != nullPtr) { + gradientVec->zero(); + } + nprox = 0; + nphi = 0; + } +}; + +template +class Algorithm { +protected: + const Ptr> status_; + const Ptr> state_; + + void initialize(const Vector &x, const Vector &g); + +public: + + virtual ~Algorithm() {} + + /** \brief Constructor, given a step and a status test. + */ + Algorithm(); + + void setStatusTest(const Ptr> &status, + bool combineStatus = false); + + /** \brief Run algorithm on unconstrained problems (Type-U). + This is the primary Type-U interface. + */ + virtual void run( Problem &problem, + std::ostream &outStream = std::cout ); + + /** \brief Run algorithm on unconstrained problems (Type-U). + This is the primary Type-U interface. + */ + virtual void run( Vector &x, + Objective &sobj, + Objective &nobj, + std::ostream &outStream = std::cout ); + + /** \brief Run algorithm on unconstrained problems (Type-U). + This general interface supports the use of dual optimization vector spaces, + where the user does not define the dual() method. + */ + virtual void run( Vector &x, + const Vector &g, + Objective &sobj, + Objective &nobj, + std::ostream &outStream = std::cout) = 0; + + /** \brief Print iterate header. + */ + virtual void writeHeader( std::ostream& os ) const; + + /** \brief Print step name. + */ + virtual void writeName( std::ostream& os ) const; + + /** \brief Print iterate status. + */ + virtual void writeOutput( std::ostream& os, bool write_header = false ) const; + + virtual void writeExitStatus( std::ostream& os ) const; + + //Ptr>& getState() const; + Ptr> getState() const; + + void reset(); + +}; // class ROL::TypeP::Algorithm +} // namespace TypeP +} // namespace ROL + +#include "ROL_TypeP_Algorithm_Def.hpp" + +#endif diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm_Def.hpp new file mode 100644 index 000000000000..5a1dfd968eca --- /dev/null +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm_Def.hpp @@ -0,0 +1,184 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +#ifndef ROL_TYPEP_ALGORITHM_DEF_H +#define ROL_TYPEP_ALGORITHM_DEF_H + +#include "ROL_Types.hpp" +#include "ROL_ValidParameters.hpp" + +namespace ROL { +namespace TypeP { + +template +Algorithm::Algorithm() + : status_(makePtr>()), + state_(makePtr>()) { + status_->reset(); + status_->add(makePtr>()); +} + +template +void Algorithm::initialize(const Vector &x, const Vector &g) { + if (state_->iterateVec == nullPtr) { + state_->iterateVec = x.clone(); + } + state_->iterateVec->set(x); + if (state_->stepVec == nullPtr) { + state_->stepVec = x.clone(); + } + state_->stepVec->zero(); + if (state_->gradientVec == nullPtr) { + state_->gradientVec = g.clone(); + } + state_->gradientVec->set(g); + if (state_->minIterVec == nullPtr) { + state_->minIterVec = x.clone(); + } + state_->minIterVec->set(x); + state_->minIter = state_->iter; + state_->minValue = state_->value; +} + +template +void Algorithm::setStatusTest(const Ptr> &status, + bool combineStatus) { + if (!combineStatus) { // Do not combine status tests + status_->reset(); + } + status_->add(status); // Add user-defined StatusTest +} + +template +void Algorithm::run( Problem &problem, + std::ostream &outStream ) { + /*if (problem.getProblemType() == TYPE_P) { + run(*problem.getPrimalOptimizationVector(), + *problem.getDualOptimizationVector(), + *problem.getObjective(), + outStream); + problem.finalizeIteration(); + } + else { + throw Exception::NotImplemented(">>> ROL::TypeP::Algorithm::run : Optimization problem is not Type P!"); + }*/ +} + +template +void Algorithm::run( Vector &x, + Objective &sobj, + Objective &nobj, + std::ostream &outStream ) { + run(x,x.dual(),sobj,nobj,outStream); +} + +template +void Algorithm::writeHeader( std::ostream& os ) const { + std::stringstream hist; + hist << " "; + hist << std::setw(6) << std::left << "iter"; + hist << std::setw(15) << std::left << "value"; + hist << std::setw(15) << std::left << "gnorm"; + hist << std::setw(15) << std::left << "snorm"; + hist << std::setw(10) << std::left << "#fval"; + hist << std::setw(10) << std::left << "#grad"; + hist << std::setw(10) << std::left << "#prox"; + hist << std::endl; + os << hist.str(); +} + +template +void Algorithm::writeName( std::ostream& os ) const { + throw Exception::NotImplemented(">>> ROL::TypeP::Algorithm::writeName() is not implemented!"); +} + +template +void Algorithm::writeOutput( std::ostream& os, bool write_header ) const { + std::stringstream hist; + hist << std::scientific << std::setprecision(6); + if ( write_header ) writeHeader(os); + if ( state_->iter == 0 ) { + hist << " "; + hist << std::setw(6) << std::left << state_->iter; + hist << std::setw(15) << std::left << state_->value; + hist << std::setw(15) << std::left << state_->gnorm; + hist << std::endl; + } + else { + hist << " "; + hist << std::setw(6) << std::left << state_->iter; + hist << std::setw(15) << std::left << state_->value; + hist << std::setw(15) << std::left << state_->gnorm; + hist << std::setw(15) << std::left << state_->snorm; + hist << std::setw(10) << std::left << state_->nfval; + hist << std::setw(10) << std::left << state_->ngrad; + hist << std::setw(10) << std::left << state_->nprox; + hist << std::endl; + } + os << hist.str(); +} + +template +void Algorithm::writeExitStatus( std::ostream& os ) const { + std::stringstream hist; + hist << "Optimization Terminated with Status: "; + hist << EExitStatusToString(state_->statusFlag); + hist << std::endl; + os << hist.str(); +} + +template +//Ptr>& Algorithm::getState() const { +Ptr> Algorithm::getState() const { + return state_; +} + +template +void Algorithm::reset() { + state_->reset(); +} + +} // namespace TypeP +} // namespace ROL + +#endif diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm.hpp new file mode 100644 index 000000000000..a0afe96fb9dd --- /dev/null +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm.hpp @@ -0,0 +1,98 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +#ifndef ROL_TYPEP_PROXGRADIENTALGORITHM_HPP +#define ROL_TYPEP_PROXGRADIENTALGORITHM_HPP + +#include "ROL_TypeP_Algorithm.hpp" + +/** \class ROL::TypeP::ProxGradientAlgorithm + \brief Provides an interface to run the proximal gradient algorithm. +*/ + +namespace ROL { +namespace TypeP { + +template +class ProxGradientAlgorithm : public TypeP::Algorithm { +private: + int maxit_; + Real alpha0_, alpha0bnd_, rhodec_, rhoinc_, c1_, maxAlpha_, t0_; + bool useralpha_, usePrevAlpha_, useAdapt_, normAlpha_; + int verbosity_; + bool writeHeader_; + + using TypeP::Algorithm::status_; + using TypeP::Algorithm::state_; + + void initialize(Vector &x, + const Vector &g, + Objective &sobj, + Objective &nobj, + Vector &px, + std::ostream &outStream = std::cout); +public: + + ProxGradientAlgorithm(ParameterList &list); + + using TypeP::Algorithm::run; + void run( Vector &x, + const Vector &g, + Objective &sobj, + Objective &nobj, + std::ostream &outStream = std::cout) override; + + void writeHeader( std::ostream& os ) const override; + + void writeName( std::ostream& os ) const override; + + void writeOutput( std::ostream& os, bool write_header = false ) const override; + +}; // class ROL::TypeP::GradientAlgorithm + +} // namespace TypeP +} // namespace ROL + +#include "ROL_TypeP_ProxGradientAlgorithm_Def.hpp" + +#endif diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp new file mode 100644 index 000000000000..c10e9b1ab76b --- /dev/null +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp @@ -0,0 +1,367 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +#ifndef ROL_TYPEP_PROXGRADIENTALGORITHM_DEF_HPP +#define ROL_TYPEP_PROXGRADIENTALGORITHM_DEF_HPP + +namespace ROL { +namespace TypeP { + +template +ProxGradientAlgorithm::ProxGradientAlgorithm(ParameterList &list) { + // Set status test + status_->reset(); + status_->add(makePtr>(list)); + + // Parse parameter list + ParameterList &lslist = list.sublist("Step").sublist("Line Search"); + maxit_ = lslist.get("Function Evaluation Limit", 20); + alpha0_ = lslist.get("Initial Step Size", 1.0); + normAlpha_ = lslist.get("Normalize Initial Step Size", false); + alpha0bnd_ = lslist.get("Lower Bound for Initial Step Size", 1e-4); + useralpha_ = lslist.get("User Defined Initial Step Size", false); + usePrevAlpha_ = lslist.get("Use Previous Step Length as Initial Guess", false); + c1_ = lslist.get("Sufficient Decrease Tolerance", 1e-4); + maxAlpha_ = lslist.get("Maximum Step Size", alpha0_); + useAdapt_ = lslist.get("Use Adaptive Step Size Selection", true); + rhodec_ = lslist.sublist("Line-Search Method").get("Backtracking Rate", 0.5); + rhoinc_ = lslist.sublist("Line-Search Method").get("Increase Rate" , 2.0); + t0_ = list.sublist("Status Test").get("Gradient Scale" , 1.0); + verbosity_ = list.sublist("General").get("Output Level", 0); + writeHeader_ = verbosity_ > 2; +} + +template +void ProxGradientAlgorithm::initialize(Vector &x, + const Vector &g, + Objective &sobj, + Objective &nobj, + Vector &px, + std::ostream &outStream) { + const Real one(1); + // Initialize data + TypeP::Algorithm::initialize(x,g); + // Update approximate gradient and approximate objective function. + Real ftol = std::sqrt(ROL_EPSILON()); + nobj.prox(px,x,state_->searchSize,ftol); + x.set(px); //revisit with option to do initial prox or not + sobj.update(x,UpdateType::Initial,state_->iter); + nobj.update(x,UpdateType::Initial,state_->iter); + state_->value = sobj.value(x,ftol); + state_->phival = nobj.value(x,ftol); + state_->nfval++; + state_->nphi++; + sobj.gradient(*state_->gradientVec,x,ftol); + state_->ngrad++; + state_->stepVec->set(x); + state_->stepVec->axpy(-t0_,state_->gradientVec->dual()); + + nobj.prox(px,*state_->stepVec,t0_,ftol); + state_->stepVec->set(px); + Real fnew = state_->value; + if (!useralpha_) { + // Evaluate objective at P(x - g) + sobj.update(*state_->stepVec,UpdateType::Trial); + fnew = sobj.value(*state_->stepVec,ftol); + sobj.update(x,UpdateType::Revert); + state_->nfval++; + } + state_->stepVec->axpy(-one,x); + state_->gnorm = state_->stepVec->norm()/t0_; + state_->snorm = ROL_INF(); + if (!useralpha_) { + const Real half(0.5); + // Minimize quadratic interpolate to compute new alpha + //Real gs = state_->stepVec->dot(state_->gradientVec->dual()); + Real gs = state_->stepVec->apply(*state_->gradientVec); + Real denom = (fnew - state_->value - gs); + bool flag = maxAlpha_ == alpha0_; + alpha0_ = ((denom > ROL_EPSILON()) ? -half*gs/denom : alpha0bnd_); + alpha0_ = ((alpha0_ > alpha0bnd_) ? alpha0_ : one); + if (flag) maxAlpha_ = alpha0_; + } + // Normalize initial CP step length + if (normAlpha_) { + alpha0_ /= state_->gradientVec->norm(); + } + state_->searchSize = alpha0_; +} + +template +void ProxGradientAlgorithm::run( Vector &x, + const Vector &g, + Objective &sobj, + Objective &nobj, + std::ostream &outStream ) { + const Real one(1); + // Initialize trust-region data + Ptr> px = x.clone(); + Ptr> s = x.clone(); + initialize(x,g,sobj,nobj,*px,outStream); + Real ftrial(0), phitrial(0), Qk(0), ftrialP(0),phitrialP(0), alphaP(0), tol(std::sqrt(ROL_EPSILON())); + int ls_nfval = 0; + bool incAlpha = false, accept = true; + + // Output + if (verbosity_ > 0) writeOutput(outStream,true); + + // Compute steepest descent step + state_->stepVec->set(state_->gradientVec->dual()); + while (status_->check(*state_)) { + accept = true; + // Perform backtracking line search + if (!usePrevAlpha_ && !useAdapt_) state_->searchSize = alpha0_; + px->set(x); + px->axpy(-state_->searchSize,*state_->stepVec); + nobj.prox(*state_->iterateVec,*px,state_->searchSize,tol); + nobj.update(*state_->iterateVec,UpdateType::Trial); + sobj.update(*state_->iterateVec,UpdateType::Trial); + ftrial = sobj.value(*state_->iterateVec,tol); + phitrial = nobj.value(*state_->iterateVec,tol); + ls_nfval = 1; + s->set(*state_->iterateVec); + s->axpy(-one,x); + Qk = s->dot(*state_->stepVec) + phitrial - state_->phival; + incAlpha = (state_->value + state_->phival - ftrial - phitrial >= -c1_*Qk); + if (verbosity_ > 1) { + outStream << " In TypeP::GradientAlgorithm: Line Search" << std::endl; + outStream << " Step size: " << state_->searchSize << std::endl; + outStream << " Trial sobj value: " << ftrial << std::endl; + outStream << " Trial nobj value: " << phitrial << std::endl; + outStream << " Computed reduction: " << state_->value + state_->phival - phitrial -ftrial << std::endl; + outStream << " Dot product of gradient and step: " << Qk << std::endl; + outStream << " Sufficient decrease bound: " << -Qk*c1_ << std::endl; + outStream << " Number of function evaluations: " << ls_nfval << std::endl; + outStream << " Increase alpha?: " << incAlpha << std::endl; + } + if (incAlpha && useAdapt_) { + ftrialP = ROL_INF(); + phitrialP = ROL_INF(); + while ( state_->value + state_->phival - ftrial - phitrial >= -c1_*Qk + && ftrial+phitrial <= ftrialP + phitrialP + && state_->searchSize < maxAlpha_ + && ls_nfval < maxit_ ) { + // Previous value was acceptable + sobj.update(*state_->iterateVec,UpdateType::Accept); + nobj.update(*state_->iterateVec,UpdateType::Accept); + alphaP = state_->searchSize; + ftrialP = ftrial; + phitrialP = phitrial; + state_->searchSize *= rhoinc_; + state_->searchSize = std::min(state_->searchSize,maxAlpha_); + px->set(x); + px->axpy(-state_->searchSize,*state_->stepVec); + nobj.prox(*state_->iterateVec,*px,state_->searchSize,tol); + sobj.update(*state_->iterateVec,UpdateType::Trial); + nobj.update(*state_->iterateVec,UpdateType::Trial); + ftrial = sobj.value(*state_->iterateVec,tol); + phitrial = nobj.value(*state_->iterateVec,tol); + ls_nfval++; + s->set(*state_->iterateVec); + s->axpy(-one,x); + Qk = s->dot(*state_->stepVec) + phitrial - state_->phival; + if (verbosity_ > 1) { + outStream << std::endl; + outStream << " Step size: " << state_->searchSize << std::endl; + outStream << " Trial sobj value: " << ftrial << std::endl; + outStream << " Trial nobj value: " << phitrial << std::endl; + outStream << " Computed reduction: " << state_->value + state_->phival - phitrial -ftrial << std::endl; + outStream << " Dot product of gradient and step: " << Qk << std::endl; + outStream << " Sufficient decrease bound: " << -Qk*c1_ << std::endl; + outStream << " Number of function evaluations: " << ls_nfval << std::endl; + } + } + if (state_->value + state_->phival - ftrial - phitrial < -c1_*Qk || phitrial + ftrial > phitrialP + ftrialP) { + ftrial = ftrialP; + phitrial = phitrialP; + state_->searchSize = alphaP; + px->set(x); + px->axpy(-state_->searchSize,*state_->stepVec); + nobj.prox(*state_->iterateVec,*px,state_->searchSize,tol); + s->set(*state_->iterateVec); + s->axpy(-one,x); + accept = false; + } + } + else { + while ( state_->value + state_->phival - phitrial - ftrial < -c1_*Qk && ls_nfval < maxit_ ) { + state_->searchSize *= rhodec_; + px->set(x); + px->axpy(-state_->searchSize,*state_->stepVec); + nobj.prox(*state_->iterateVec,*px,state_->searchSize,tol); + state_->nprox++; + sobj.update(*state_->iterateVec,UpdateType::Trial); + nobj.update(*state_->iterateVec,UpdateType::Trial); + ftrial = sobj.value(*state_->iterateVec,tol); + phitrial = nobj.value(*state_->iterateVec,tol); + ls_nfval++; + s->set(*state_->iterateVec); + s->axpy(-one,x); + Qk = s->dot(*state_->stepVec) + phitrial - state_->phival; + if (verbosity_ > 1) { + outStream << std::endl; + outStream << " Step size: " << state_->searchSize << std::endl; + outStream << " Trial sobj value: " << ftrial << std::endl; + outStream << " Trial nobj value: " << phitrial << std::endl; + outStream << " Computed reduction: " << state_->value + state_->phival - phitrial -ftrial << std::endl; + outStream << " Dot product of gradient and step: " << Qk << std::endl; + outStream << " Sufficient decrease bound: " << -Qk*c1_ << std::endl; + outStream << " Number of function evaluations: " << ls_nfval << std::endl; + } + } + } + state_->nfval += ls_nfval; + state_->nphi += ls_nfval; + // Compute norm of step + state_->stepVec->set(*s); + state_->snorm = state_->stepVec->norm(); + + // Update iterate + x.set(*state_->iterateVec); + + // Compute new value and gradient + state_->iter++; + state_->value = ftrial; + state_->phival = phitrial; + if (accept) { + sobj.update(x,UpdateType::Accept,state_->iter); + nobj.update(x,UpdateType::Accept,state_->iter); + } + else { + sobj.update(x,UpdateType::Revert,state_->iter); + nobj.update(x,UpdateType::Revert,state_->iter); + } + sobj.gradient(*state_->gradientVec,x,tol); + state_->ngrad++; + + // Compute steepest descent step + state_->stepVec->set(state_->gradientVec->dual()); + + // Compute projected gradient norm + s->set(x); s->axpy(-one,*state_->stepVec); + nobj.prox(*px,*s,state_->searchSize,tol); + s->axpy(-one,x); + state_->gnorm = s->norm(); + + // Update Output + if (verbosity_ > 0) writeOutput(outStream,writeHeader_); + } + if (verbosity_ > 0) TypeP::Algorithm::writeExitStatus(outStream); +} + +template +void ProxGradientAlgorithm::writeHeader( std::ostream& os ) const { + std::stringstream hist; + if (verbosity_ > 1) { + hist << std::string(109,'-') << std::endl; + hist << "Projected gradient descent"; + hist << " status output definitions" << std::endl << std::endl; + hist << " iter - Number of iterates (steps taken)" << std::endl; + hist << " sobj - Smooth Objective function value" << std::endl; + hist << " nobj - Nonsmooth Objective function value" << std::endl; + hist << " gnorm - Norm of the gradient" << std::endl; + hist << " snorm - Norm of the step (update to optimization vector)" << std::endl; + hist << " alpha - Line search step length" << std::endl; + hist << " #fval - Cumulative number of times the objective function was evaluated" << std::endl; + hist << " #grad - Cumulative number of times the gradient was computed" << std::endl; + hist << " #prox - Cumulative number of times the proximal operator was computed" << std::endl; + hist << std::string(109,'-') << std::endl; + } + + hist << " "; + hist << std::setw(6) << std::left << "iter"; + hist << std::setw(15) << std::left << "value"; + hist << std::setw(15) << std::left << "gnorm"; + hist << std::setw(15) << std::left << "snorm"; + hist << std::setw(15) << std::left << "alpha"; + hist << std::setw(10) << std::left << "#fval"; + hist << std::setw(10) << std::left << "#grad"; + hist << std::setw(10) << std::left << "#nprox"; + hist << std::endl; + os << hist.str(); +} + +template +void ProxGradientAlgorithm::writeName( std::ostream& os ) const { + std::stringstream hist; + hist << std::endl << "Proximal Gradient Descent with Backtracking Line Search (Type P)" << std::endl; + os << hist.str(); +} + +template +void ProxGradientAlgorithm::writeOutput( std::ostream& os, bool write_header ) const { + std::stringstream hist; + hist << std::scientific << std::setprecision(6); + if ( state_->iter == 0 ) writeName(os); + if ( write_header ) writeHeader(os); + if ( state_->iter == 0 ) { + hist << " "; + hist << std::setw(6) << std::left << state_->iter; + hist << std::setw(15) << std::left << state_->value; + hist << std::setw(15) << std::left << state_->gnorm; + hist << std::setw(15) << std::left << "---"; + hist << std::setw(15) << std::left << "---"; + hist << std::setw(10) << std::left << state_->nfval; + hist << std::setw(10) << std::left << state_->ngrad; + hist << std::setw(10) << std::left << state_->nprox; + hist << std::endl; + } + else { + hist << " "; + hist << std::setw(6) << std::left << state_->iter; + hist << std::setw(15) << std::left << state_->value; + hist << std::setw(15) << std::left << state_->gnorm; + hist << std::setw(15) << std::left << state_->snorm; + hist << std::setw(15) << std::left << state_->searchSize; + hist << std::setw(10) << std::left << state_->nfval; + hist << std::setw(10) << std::left << state_->ngrad; + hist << std::setw(10) << std::left << state_->nprox; + hist << std::endl; + } + os << hist.str(); +} + +} // namespace TypeP +} // namespace ROL + +#endif diff --git a/packages/rol/src/function/objective/ROL_Objective.hpp b/packages/rol/src/function/objective/ROL_Objective.hpp index 760fba316ee8..a4ca1773d66c 100644 --- a/packages/rol/src/function/objective/ROL_Objective.hpp +++ b/packages/rol/src/function/objective/ROL_Objective.hpp @@ -186,6 +186,15 @@ class Objective { Pv.set(v.dual()); } + virtual void prox( Vector &Pv, const Vector &v, Real t, Real &tol){ + ROL_UNUSED(Pv); + ROL_UNUSED(v); + ROL_UNUSED(t); + ROL_UNUSED(tol); + ROL_TEST_FOR_EXCEPTION(true, std::invalid_argument, + ">>> ERROR (ROL::Objective): prox not implemented!"); + } + /** \brief Finite-difference gradient check. This function computes a sequence of one-sided finite-difference checks for the gradient. diff --git a/packages/rol/src/function/objective/ROL_l1Objective.hpp b/packages/rol/src/function/objective/ROL_l1Objective.hpp new file mode 100644 index 000000000000..a04901326ca8 --- /dev/null +++ b/packages/rol/src/function/objective/ROL_l1Objective.hpp @@ -0,0 +1,111 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +#ifndef ROL_L1OBJECTIVE_H +#define ROL_L1OBJECTIVE_H + +#include "ROL_Objective.hpp" + +/** @ingroup func_group + \class ROL::l1Objective + \brief Provides the interface to evaluate the l1 objective. + + --- +*/ + + +namespace ROL { + +template +class l1Objective : public Objective { +private: + const Ptr> weights_, shift_; + Ptr> tmp_; + struct ProjSymBnd : public Elementwise::BinaryFunction { + Real apply(const Real &xc, const Real &yc) const { return std::min(yc, std::max(-yc, xc)); } + } psb_; + +public: + + l1Objective(const Ptr> &weights) : weights_(weights), shift_(weights->clone()) { + shift_->zero(); + tmp_ = shift_->clone(); + } + l1Objective(const Ptr> &weights, const Ptr> &shift) : weights_(weights), shift_(shift) { + tmp_ = shift_->clone(); + } + + Real value( const Vector &x, Real &tol ) { + tmp_->set(x); + tmp_->axpy(static_cast(-1),*shift_); + tmp_->applyUnary(Elementwise::AbsoluteValue()); + Real val = weights_->apply(*tmp_); + return val; + } + + void gradient( Vector &g, const Vector &x, Real &tol ) { + g.set(x); + g.axpy(static_cast(-1),*shift_); + g.applyUnary(Elementwise::Sign()); + g.applyBinary(Elementwise::Multiply(), *weights_); + } + + + Real dirDeriv( const Vector &x, const Vector &d, Real &tol ) { + gradient(*tmp_, x, tol); + return tmp_->apply(d); + } + + + void prox( Vector &Pv, const Vector &v, Real t, Real &tol){ + Pv.set(*shift_); + Pv.axpy(static_cast(-1)/t, v); + Pv.applyBinary(psb_, *weights_); + Pv.scale(t); + Pv.plus(v); + } +}; // class l1Objective + +} // namespace ROL + +#endif diff --git a/packages/rol/test/algorithm/CMakeLists.txt b/packages/rol/test/algorithm/CMakeLists.txt index 2882a4ee8e6f..fc13f0a2b3ee 100644 --- a/packages/rol/test/algorithm/CMakeLists.txt +++ b/packages/rol/test/algorithm/CMakeLists.txt @@ -2,6 +2,7 @@ ADD_SUBDIRECTORY(TypeU) ADD_SUBDIRECTORY(TypeB) ADD_SUBDIRECTORY(TypeE) ADD_SUBDIRECTORY(TypeG) +ADD_SUBDIRECTORY(TypeP) TRIBITS_ADD_EXECUTABLE_AND_TEST( OptimizationSolverStatusTestInput diff --git a/packages/rol/test/algorithm/TypeP/CMakeLists.txt b/packages/rol/test/algorithm/TypeP/CMakeLists.txt new file mode 100644 index 000000000000..7f5af16afb08 --- /dev/null +++ b/packages/rol/test/algorithm/TypeP/CMakeLists.txt @@ -0,0 +1,18 @@ + +TRIBITS_ADD_EXECUTABLE_AND_TEST( + ProximalGradient + SOURCES test_01.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + +TRIBITS_COPY_FILES_TO_BINARY_DIR( + TypePTestDataCopy + SOURCE_FILES + input.xml + SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" + DEST_DIR "${CMAKE_CURRENT_BINARY_DIR}" +) diff --git a/packages/rol/test/algorithm/TypeP/input.xml b/packages/rol/test/algorithm/TypeP/input.xml new file mode 100644 index 000000000000..d5779a1175b5 --- /dev/null +++ b/packages/rol/test/algorithm/TypeP/input.xml @@ -0,0 +1,201 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/rol/test/algorithm/TypeP/test_01.cpp b/packages/rol/test/algorithm/TypeP/test_01.cpp new file mode 100644 index 000000000000..330bbdf6a805 --- /dev/null +++ b/packages/rol/test/algorithm/TypeP/test_01.cpp @@ -0,0 +1,195 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +/*! \file test_23.cpp + \brief Validate projected gradient algorithm. +*/ + +#include "ROL_TypeP_ProxGradientAlgorithm.hpp" +#include "ROL_l1Objective.hpp" +#include "ROL_Stream.hpp" +#include "Teuchos_GlobalMPISession.hpp" +#include "ROL_StdObjective.hpp" + +template +class quad : public ROL::StdObjective { + private: + int dim_; + std::vector a_, b_; + public: + quad(int dim) : dim_(dim) { + a_.resize(dim); + b_.resize(dim); + + for (int i = 0; i(rand())/static_cast(RAND_MAX); + b_[i] = static_cast(2)*static_cast(rand())/static_cast(RAND_MAX) - static_cast(1); + } + } + + Real value(const std::vector &x, Real &tol){ + Real val(0); + for (int i = 0; i(0.5)*a_[i]*x[i]*x[i] + b_[i]*x[i]; + } + return val; + } + + void gradient(std::vector &g, const std::vector &x, Real &tol){ + + for (int i = 0; i &hv, const std::vector &v, const std::vector &x, Real &tol){ + + for (int i = 0; i &x, const std::vector &wts, const std::vector &y) const { + Real tmp(0); + + for (int i = 0; i y[i]){ + x[i] = tmp; + } + else{ + tmp = (wts[i] - b_[i])/a_[i]; + if (tmp < y[i]){ + x[i] = tmp; + } + else{ + x[i] = y[i]; + } + } + } + } +}; + +typedef double RealT; + +int main(int argc, char *argv[]) { + + Teuchos::GlobalMPISession mpiSession(&argc, &argv); + + // This little trick lets us print to std::cout only if a + // (dummy) command-line argument is provided. + int iprint = argc - 1; + ROL::Ptr outStream; + ROL::nullstream bhs; // outputs nothing + if (iprint > 0) + outStream = ROL::makePtrFromRef(std::cout); + else + outStream = ROL::makePtrFromRef(bhs); + + int errorFlag = 0; + + try { + RealT tol = 1e2*std::sqrt(ROL::ROL_EPSILON()); + + ROL::ParameterList list; + list.sublist("Status Test").set("Gradient Tolerance",1e-7); + list.sublist("Status Test").set("Constraint Tolerance",1e-8); + list.sublist("Status Test").set("Step Tolerance",1e-12); + list.sublist("Status Test").set("Iteration Limit", 250); + list.sublist("Step").set("Type","Line Search"); + list.sublist("General").set("Output Level",iprint); + + int dim = 5; + ROL::Ptr> sol, wts, y; + ROL::Ptr> nobj; + ROL::Ptr> sobj; + ROL::Ptr> algo; + std::vector data; + RealT e1, e2, e3, e4, e5, err; + + *outStream << std::endl << "Diagonal LASSO" << std::endl << std::endl; + ROL::Ptr> wtsP = ROL::makePtr>(dim); + ROL::Ptr> yP = ROL::makePtr>(dim); + wts = ROL::makePtr>(wtsP); + y = ROL::makePtr>(yP); + sol = ROL::makePtr>(dim); + wts->randomize(0.0,1.0); + y->randomize(-5.0, 5.0); + sol->zero(); + + + nobj = ROL::makePtr>(wts,y); + sobj = ROL::makePtr>(dim); + + algo = ROL::makePtr>(list); + algo->run(*sol,*sobj,*nobj,*outStream); + + std::vector xstar(dim); + sobj->getSolution(xstar, *wtsP, *yP); + data = *ROL::staticPtrCast>(sol)->getVector(); + *outStream << " Result: x1 = " << data[0] << " x2 = " << data[1] + << " x3 = " << data[2] << " x4 = " << data[3] << " x5 = " << data[4] << std::endl; + e1 = (data[0]-xstar[0]); + e2 = (data[1]-xstar[1]); + e3 = (data[2]-xstar[2]); + e4 = (data[3]-xstar[3]); + e5 = (data[4]-xstar[4]); + err = std::max(std::max(std::max(std::max(std::abs(e1),std::abs(e2)),std::abs(e3)),std::abs(e4)),std::abs(e5)); + *outStream << " Max-Error = " << err << std::endl; + errorFlag += (err > tol ? 1 : 0); + + } + + catch (std::logic_error& err) { + *outStream << err.what() << "\n"; + errorFlag = -1000; + }; // end try + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return 0; +} + From a30badcbe44a0d8e5b7195213d069998d1841660 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Tue, 20 Dec 2022 18:17:04 -0700 Subject: [PATCH 04/65] Proximal gradient code clean up. --- .../algorithm/TypeP/ROL_TypeP_Algorithm.hpp | 34 +-- .../TypeP/ROL_TypeP_Algorithm_Def.hpp | 23 +- .../ROL_TypeP_ProxGradientAlgorithm_Def.hpp | 219 ++++++++++-------- .../function/objective/ROL_l1Objective.hpp | 52 +++-- packages/rol/test/algorithm/TypeP/test_01.cpp | 171 ++++++-------- 5 files changed, 255 insertions(+), 244 deletions(-) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm.hpp index a6dc0d84dd4a..d1d9486440c5 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm.hpp @@ -57,32 +57,32 @@ namespace TypeP { template struct AlgorithmState : public ROL::AlgorithmState { - Real searchSize, phival; - Ptr> stepVec; - Ptr> gradientVec; - int nprox; - int nphi; + Real searchSize, svalue, nvalue; + Ptr> stepVec, gradientVec; + int nprox, nsval, nnval; AlgorithmState() : searchSize(1), - phival(ROL_INF()), + svalue(ROL_INF()), + nvalue(ROL_INF()), stepVec(nullPtr), gradientVec(nullPtr), - nprox(0), - nphi(0) {} + nprox(0), + nsval(0), + nnval(0) {} void reset() { ROL::AlgorithmState::reset(); searchSize = static_cast(1); - phival = ROL_INF(); - if (stepVec != nullPtr) { + svalue = ROL_INF(); + nvalue = ROL_INF(); + if (stepVec != nullPtr) stepVec->zero(); - } - if (gradientVec != nullPtr) { + if (gradientVec != nullPtr) gradientVec->zero(); - } - nprox = 0; - nphi = 0; + nprox = 0; + nsval = 0; + nnval = 0; } }; @@ -90,7 +90,7 @@ template class Algorithm { protected: const Ptr> status_; - const Ptr> state_; + const Ptr> state_; void initialize(const Vector &x, const Vector &g); @@ -109,7 +109,7 @@ class Algorithm { This is the primary Type-U interface. */ virtual void run( Problem &problem, - std::ostream &outStream = std::cout ); + std::ostream &outStream = std::cout ); /** \brief Run algorithm on unconstrained problems (Type-U). This is the primary Type-U interface. diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm_Def.hpp index 5a1dfd968eca..3dcf3bab8cd9 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm_Def.hpp @@ -60,21 +60,17 @@ Algorithm::Algorithm() template void Algorithm::initialize(const Vector &x, const Vector &g) { - if (state_->iterateVec == nullPtr) { + if (state_->iterateVec == nullPtr) state_->iterateVec = x.clone(); - } state_->iterateVec->set(x); - if (state_->stepVec == nullPtr) { + if (state_->stepVec == nullPtr) state_->stepVec = x.clone(); - } state_->stepVec->zero(); - if (state_->gradientVec == nullPtr) { + if (state_->gradientVec == nullPtr) state_->gradientVec = g.clone(); - } state_->gradientVec->set(g); - if (state_->minIterVec == nullPtr) { + if (state_->minIterVec == nullPtr) state_->minIterVec = x.clone(); - } state_->minIterVec->set(x); state_->minIter = state_->iter; state_->minValue = state_->value; @@ -82,10 +78,9 @@ void Algorithm::initialize(const Vector &x, const Vector &g) { template void Algorithm::setStatusTest(const Ptr> &status, - bool combineStatus) { - if (!combineStatus) { // Do not combine status tests + bool combineStatus) { + if (!combineStatus) // Do not combine status tests status_->reset(); - } status_->add(status); // Add user-defined StatusTest } @@ -102,6 +97,7 @@ void Algorithm::run( Problem &problem, else { throw Exception::NotImplemented(">>> ROL::TypeP::Algorithm::run : Optimization problem is not Type P!"); }*/ + throw Exception::NotImplemented(">>> ROL::TypeP::Algorithm::run : Optimization problem is not available for Type P problems!"); } template @@ -122,7 +118,7 @@ void Algorithm::writeHeader( std::ostream& os ) const { hist << std::setw(15) << std::left << "snorm"; hist << std::setw(10) << std::left << "#fval"; hist << std::setw(10) << std::left << "#grad"; - hist << std::setw(10) << std::left << "#prox"; + hist << std::setw(10) << std::left << "#prox"; hist << std::endl; os << hist.str(); } @@ -153,7 +149,7 @@ void Algorithm::writeOutput( std::ostream& os, bool write_header ) const { hist << std::setw(10) << std::left << state_->nfval; hist << std::setw(10) << std::left << state_->ngrad; hist << std::setw(10) << std::left << state_->nprox; - hist << std::endl; + hist << std::endl; } os << hist.str(); } @@ -168,7 +164,6 @@ void Algorithm::writeExitStatus( std::ostream& os ) const { } template -//Ptr>& Algorithm::getState() const { Ptr> Algorithm::getState() const { return state_; } diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp index c10e9b1ab76b..89c0f4e5f7d2 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp @@ -57,7 +57,7 @@ ProxGradientAlgorithm::ProxGradientAlgorithm(ParameterList &list) { ParameterList &lslist = list.sublist("Step").sublist("Line Search"); maxit_ = lslist.get("Function Evaluation Limit", 20); alpha0_ = lslist.get("Initial Step Size", 1.0); - normAlpha_ = lslist.get("Normalize Initial Step Size", false); + normAlpha_ = lslist.get("Normalize Initial Step Size", false); alpha0bnd_ = lslist.get("Lower Bound for Initial Step Size", 1e-4); useralpha_ = lslist.get("User Defined Initial Step Size", false); usePrevAlpha_ = lslist.get("Use Previous Step Length as Initial Guess", false); @@ -66,45 +66,51 @@ ProxGradientAlgorithm::ProxGradientAlgorithm(ParameterList &list) { useAdapt_ = lslist.get("Use Adaptive Step Size Selection", true); rhodec_ = lslist.sublist("Line-Search Method").get("Backtracking Rate", 0.5); rhoinc_ = lslist.sublist("Line-Search Method").get("Increase Rate" , 2.0); - t0_ = list.sublist("Status Test").get("Gradient Scale" , 1.0); + t0_ = list.sublist("Status Test").get("Gradient Scale" , 1.0); verbosity_ = list.sublist("General").get("Output Level", 0); writeHeader_ = verbosity_ > 2; } template -void ProxGradientAlgorithm::initialize(Vector &x, - const Vector &g, - Objective &sobj, - Objective &nobj, - Vector &px, - std::ostream &outStream) { +void ProxGradientAlgorithm::initialize(Vector &x, + const Vector &g, + Objective &sobj, + Objective &nobj, + Vector &px, + std::ostream &outStream) { const Real one(1); // Initialize data TypeP::Algorithm::initialize(x,g); // Update approximate gradient and approximate objective function. Real ftol = std::sqrt(ROL_EPSILON()); nobj.prox(px,x,state_->searchSize,ftol); - x.set(px); //revisit with option to do initial prox or not + state_->nprox++; + x.set(px); //revisit with option to do initial prox or not + // Evaluate objective function sobj.update(x,UpdateType::Initial,state_->iter); + state_->svalue = sobj.value(x,ftol); + state_->nsval++; nobj.update(x,UpdateType::Initial,state_->iter); - state_->value = sobj.value(x,ftol); - state_->phival = nobj.value(x,ftol); - state_->nfval++; - state_->nphi++; + state_->nvalue = nobj.value(x,ftol); + state_->nnval++; + state_->value = state_->svalue + state_->nvalue; + // Evaluate gradient of smooth part sobj.gradient(*state_->gradientVec,x,ftol); state_->ngrad++; + // Evaluate proximal gradient state_->stepVec->set(x); state_->stepVec->axpy(-t0_,state_->gradientVec->dual()); - nobj.prox(px,*state_->stepVec,t0_,ftol); - state_->stepVec->set(px); - Real fnew = state_->value; + state_->nprox++; + state_->stepVec->set(px); + // Compute initial step size + Real fnew = state_->svalue; if (!useralpha_) { // Evaluate objective at P(x - g) sobj.update(*state_->stepVec,UpdateType::Trial); - fnew = sobj.value(*state_->stepVec,ftol); + fnew = sobj.value(*state_->stepVec,ftol); sobj.update(x,UpdateType::Revert); - state_->nfval++; + state_->nsval++; } state_->stepVec->axpy(-one,x); state_->gnorm = state_->stepVec->norm()/t0_; @@ -114,31 +120,30 @@ void ProxGradientAlgorithm::initialize(Vector &x, // Minimize quadratic interpolate to compute new alpha //Real gs = state_->stepVec->dot(state_->gradientVec->dual()); Real gs = state_->stepVec->apply(*state_->gradientVec); - Real denom = (fnew - state_->value - gs); + Real denom = (fnew - state_->svalue - gs); bool flag = maxAlpha_ == alpha0_; alpha0_ = ((denom > ROL_EPSILON()) ? -half*gs/denom : alpha0bnd_); alpha0_ = ((alpha0_ > alpha0bnd_) ? alpha0_ : one); if (flag) maxAlpha_ = alpha0_; } // Normalize initial CP step length - if (normAlpha_) { + if (normAlpha_) alpha0_ /= state_->gradientVec->norm(); - } state_->searchSize = alpha0_; } template -void ProxGradientAlgorithm::run( Vector &x, - const Vector &g, - Objective &sobj, - Objective &nobj, - std::ostream &outStream ) { +void ProxGradientAlgorithm::run( Vector &x, + const Vector &g, + Objective &sobj, + Objective &nobj, + std::ostream &outStream ) { const Real one(1); // Initialize trust-region data - Ptr> px = x.clone(); - Ptr> s = x.clone(); - initialize(x,g,sobj,nobj,*px,outStream); - Real ftrial(0), phitrial(0), Qk(0), ftrialP(0),phitrialP(0), alphaP(0), tol(std::sqrt(ROL_EPSILON())); + Ptr> px = x.clone(), s = x.clone(); + initialize(x,g,sobj,nobj,*px,outStream); + Real strial(0), ntrial(0), Ftrial(0), strialP(0), ntrialP(0), FtrialP(0); + Real Qk(0), alphaP(0), tol(std::sqrt(ROL_EPSILON())); int ls_nfval = 0; bool incAlpha = false, accept = true; @@ -151,107 +156,128 @@ void ProxGradientAlgorithm::run( Vector &x, accept = true; // Perform backtracking line search if (!usePrevAlpha_ && !useAdapt_) state_->searchSize = alpha0_; + // Compute proximal gradient step with initial search size px->set(x); px->axpy(-state_->searchSize,*state_->stepVec); nobj.prox(*state_->iterateVec,*px,state_->searchSize,tol); - nobj.update(*state_->iterateVec,UpdateType::Trial); - sobj.update(*state_->iterateVec,UpdateType::Trial); - ftrial = sobj.value(*state_->iterateVec,tol); - phitrial = nobj.value(*state_->iterateVec,tol); - ls_nfval = 1; + state_->nprox++; s->set(*state_->iterateVec); s->axpy(-one,x); - Qk = s->dot(*state_->stepVec) + phitrial - state_->phival; - incAlpha = (state_->value + state_->phival - ftrial - phitrial >= -c1_*Qk); + // Compute objective function values + sobj.update(*state_->iterateVec,UpdateType::Trial); + strial = sobj.value(*state_->iterateVec,tol); + nobj.update(*state_->iterateVec,UpdateType::Trial); + ntrial = nobj.value(*state_->iterateVec,tol); + Ftrial = strial + ntrial; + ls_nfval = 1; + // Compute decrease indicator + Qk = s->dot(*state_->stepVec) + ntrial - state_->nvalue; + incAlpha = (Ftrial - state_->value <= c1_*Qk); if (verbosity_ > 1) { outStream << " In TypeP::GradientAlgorithm: Line Search" << std::endl; outStream << " Step size: " << state_->searchSize << std::endl; - outStream << " Trial sobj value: " << ftrial << std::endl; - outStream << " Trial nobj value: " << phitrial << std::endl; - outStream << " Computed reduction: " << state_->value + state_->phival - phitrial -ftrial << std::endl; + outStream << " Trial smooth value: " << strial << std::endl; + outStream << " Trial nonsmooth value: " << ntrial << std::endl; + outStream << " Computed reduction: " << state_->value-Ftrial << std::endl; outStream << " Dot product of gradient and step: " << Qk << std::endl; outStream << " Sufficient decrease bound: " << -Qk*c1_ << std::endl; outStream << " Number of function evaluations: " << ls_nfval << std::endl; outStream << " Increase alpha?: " << incAlpha << std::endl; } if (incAlpha && useAdapt_) { - ftrialP = ROL_INF(); - phitrialP = ROL_INF(); - while ( state_->value + state_->phival - ftrial - phitrial >= -c1_*Qk - && ftrial+phitrial <= ftrialP + phitrialP + ntrialP = ROL_INF(); + strialP = ROL_INF(); + FtrialP = ntrialP + strialP; + while ( Ftrial - state_->value <= c1_*Qk + && Ftrial <= FtrialP && state_->searchSize < maxAlpha_ && ls_nfval < maxit_ ) { // Previous value was acceptable sobj.update(*state_->iterateVec,UpdateType::Accept); nobj.update(*state_->iterateVec,UpdateType::Accept); - alphaP = state_->searchSize; - ftrialP = ftrial; - phitrialP = phitrial; + // Increase search size + alphaP = state_->searchSize; + strialP = strial; + ntrialP = ntrial; + FtrialP = Ftrial; state_->searchSize *= rhoinc_; state_->searchSize = std::min(state_->searchSize,maxAlpha_); + // Compute proximal gradient step with new search size px->set(x); px->axpy(-state_->searchSize,*state_->stepVec); nobj.prox(*state_->iterateVec,*px,state_->searchSize,tol); - sobj.update(*state_->iterateVec,UpdateType::Trial); - nobj.update(*state_->iterateVec,UpdateType::Trial); - ftrial = sobj.value(*state_->iterateVec,tol); - phitrial = nobj.value(*state_->iterateVec,tol); - ls_nfval++; + state_->nprox++; s->set(*state_->iterateVec); s->axpy(-one,x); - Qk = s->dot(*state_->stepVec) + phitrial - state_->phival; + // Compute objective function values + sobj.update(*state_->iterateVec,UpdateType::Trial); + strial = sobj.value(*state_->iterateVec,tol); + nobj.update(*state_->iterateVec,UpdateType::Trial); + ntrial = nobj.value(*state_->iterateVec,tol); + Ftrial = strial + ntrial; + ls_nfval++; + // Compute decrease indicator + Qk = s->dot(*state_->stepVec) + ntrial - state_->nvalue; if (verbosity_ > 1) { outStream << std::endl; outStream << " Step size: " << state_->searchSize << std::endl; - outStream << " Trial sobj value: " << ftrial << std::endl; - outStream << " Trial nobj value: " << phitrial << std::endl; - outStream << " Computed reduction: " << state_->value + state_->phival - phitrial -ftrial << std::endl; + outStream << " Trial smooth value: " << strial << std::endl; + outStream << " Trial nonsmooth value: " << ntrial << std::endl; + outStream << " Computed reduction: " << state_->value-Ftrial << std::endl; outStream << " Dot product of gradient and step: " << Qk << std::endl; outStream << " Sufficient decrease bound: " << -Qk*c1_ << std::endl; outStream << " Number of function evaluations: " << ls_nfval << std::endl; } } - if (state_->value + state_->phival - ftrial - phitrial < -c1_*Qk || phitrial + ftrial > phitrialP + ftrialP) { - ftrial = ftrialP; - phitrial = phitrialP; + if (Ftrial - state_->value > c1_*Qk || Ftrial > FtrialP) { + strial = strialP; + ntrial = ntrialP; + Ftrial = FtrialP; state_->searchSize = alphaP; + // Recompute proximal gradient step px->set(x); px->axpy(-state_->searchSize,*state_->stepVec); nobj.prox(*state_->iterateVec,*px,state_->searchSize,tol); + state_->nprox++; s->set(*state_->iterateVec); s->axpy(-one,x); accept = false; } } else { - while ( state_->value + state_->phival - phitrial - ftrial < -c1_*Qk && ls_nfval < maxit_ ) { + while ( Ftrial - state_->value > c1_*Qk && ls_nfval < maxit_ ) { + // Decrease search size state_->searchSize *= rhodec_; + // Compute proximal gradient step with new search size px->set(x); px->axpy(-state_->searchSize,*state_->stepVec); nobj.prox(*state_->iterateVec,*px,state_->searchSize,tol); - state_->nprox++; + state_->nprox++; + s->set(*state_->iterateVec); + s->axpy(-one,x); + // Compute objective function values sobj.update(*state_->iterateVec,UpdateType::Trial); + strial = sobj.value(*state_->iterateVec,tol); nobj.update(*state_->iterateVec,UpdateType::Trial); - ftrial = sobj.value(*state_->iterateVec,tol); - phitrial = nobj.value(*state_->iterateVec,tol); + ntrial = nobj.value(*state_->iterateVec,tol); + Ftrial = strial + ntrial; ls_nfval++; - s->set(*state_->iterateVec); - s->axpy(-one,x); - Qk = s->dot(*state_->stepVec) + phitrial - state_->phival; + // Compute decrease indicator + Qk = s->dot(*state_->stepVec) + ntrial - state_->nvalue; if (verbosity_ > 1) { outStream << std::endl; outStream << " Step size: " << state_->searchSize << std::endl; - outStream << " Trial sobj value: " << ftrial << std::endl; - outStream << " Trial nobj value: " << phitrial << std::endl; - outStream << " Computed reduction: " << state_->value + state_->phival - phitrial -ftrial << std::endl; + outStream << " Trial smooth value: " << strial << std::endl; + outStream << " Trial nonsmooth value: " << ntrial << std::endl; + outStream << " Computed reduction: " << state_->value-Ftrial << std::endl; outStream << " Dot product of gradient and step: " << Qk << std::endl; outStream << " Sufficient decrease bound: " << -Qk*c1_ << std::endl; outStream << " Number of function evaluations: " << ls_nfval << std::endl; } } } - state_->nfval += ls_nfval; - state_->nphi += ls_nfval; + state_->nsval += ls_nfval; + state_->nnval += ls_nfval; // Compute norm of step state_->stepVec->set(*s); state_->snorm = state_->stepVec->norm(); @@ -261,16 +287,17 @@ void ProxGradientAlgorithm::run( Vector &x, // Compute new value and gradient state_->iter++; - state_->value = ftrial; - state_->phival = phitrial; + state_->svalue = strial; + state_->nvalue = ntrial; + state_->value = Ftrial; if (accept) { - sobj.update(x,UpdateType::Accept,state_->iter); - nobj.update(x,UpdateType::Accept,state_->iter); - } + sobj.update(x,UpdateType::Accept,state_->iter); + nobj.update(x,UpdateType::Accept,state_->iter); + } else { - sobj.update(x,UpdateType::Revert,state_->iter); + sobj.update(x,UpdateType::Revert,state_->iter); nobj.update(x,UpdateType::Revert,state_->iter); - } + } sobj.gradient(*state_->gradientVec,x,tol); state_->ngrad++; @@ -278,10 +305,11 @@ void ProxGradientAlgorithm::run( Vector &x, state_->stepVec->set(state_->gradientVec->dual()); // Compute projected gradient norm - s->set(x); s->axpy(-one,*state_->stepVec); - nobj.prox(*px,*s,state_->searchSize,tol); + s->set(x); s->axpy(-t0_,*state_->stepVec); + nobj.prox(*px,*s,t0_,tol); + state_->nprox++; s->axpy(-one,x); - state_->gnorm = s->norm(); + state_->gnorm = s->norm() / t0_; // Update Output if (verbosity_ > 0) writeOutput(outStream,writeHeader_); @@ -294,17 +322,17 @@ void ProxGradientAlgorithm::writeHeader( std::ostream& os ) const { std::stringstream hist; if (verbosity_ > 1) { hist << std::string(109,'-') << std::endl; - hist << "Projected gradient descent"; + hist << "Proximal gradient descent"; hist << " status output definitions" << std::endl << std::endl; hist << " iter - Number of iterates (steps taken)" << std::endl; - hist << " sobj - Smooth Objective function value" << std::endl; - hist << " nobj - Nonsmooth Objective function value" << std::endl; - hist << " gnorm - Norm of the gradient" << std::endl; + hist << " obj - Objective function value" << std::endl; + hist << " gnorm - Norm of the proximal gradient" << std::endl; hist << " snorm - Norm of the step (update to optimization vector)" << std::endl; hist << " alpha - Line search step length" << std::endl; - hist << " #fval - Cumulative number of times the objective function was evaluated" << std::endl; + hist << " #sval - Cumulative number of times the smooth objective function was evaluated" << std::endl; + hist << " #nval - Cumulative number of times the nonsmooth objective function was evaluated" << std::endl; hist << " #grad - Cumulative number of times the gradient was computed" << std::endl; - hist << " #prox - Cumulative number of times the proximal operator was computed" << std::endl; + hist << " #prox - Cumulative number of times the proximal operator was computed" << std::endl; hist << std::string(109,'-') << std::endl; } @@ -314,9 +342,10 @@ void ProxGradientAlgorithm::writeHeader( std::ostream& os ) const { hist << std::setw(15) << std::left << "gnorm"; hist << std::setw(15) << std::left << "snorm"; hist << std::setw(15) << std::left << "alpha"; - hist << std::setw(10) << std::left << "#fval"; + hist << std::setw(10) << std::left << "#sval"; + hist << std::setw(10) << std::left << "#nval"; hist << std::setw(10) << std::left << "#grad"; - hist << std::setw(10) << std::left << "#nprox"; + hist << std::setw(10) << std::left << "#nprox"; hist << std::endl; os << hist.str(); } @@ -324,7 +353,7 @@ void ProxGradientAlgorithm::writeHeader( std::ostream& os ) const { template void ProxGradientAlgorithm::writeName( std::ostream& os ) const { std::stringstream hist; - hist << std::endl << "Proximal Gradient Descent with Backtracking Line Search (Type P)" << std::endl; + hist << std::endl << "Proximal Gradient Descent with Bidirectional Line Search (Type P)" << std::endl; os << hist.str(); } @@ -341,9 +370,10 @@ void ProxGradientAlgorithm::writeOutput( std::ostream& os, bool write_head hist << std::setw(15) << std::left << state_->gnorm; hist << std::setw(15) << std::left << "---"; hist << std::setw(15) << std::left << "---"; - hist << std::setw(10) << std::left << state_->nfval; + hist << std::setw(10) << std::left << state_->nsval; + hist << std::setw(10) << std::left << state_->nnval; hist << std::setw(10) << std::left << state_->ngrad; - hist << std::setw(10) << std::left << state_->nprox; + hist << std::setw(10) << std::left << state_->nprox; hist << std::endl; } else { @@ -353,9 +383,10 @@ void ProxGradientAlgorithm::writeOutput( std::ostream& os, bool write_head hist << std::setw(15) << std::left << state_->gnorm; hist << std::setw(15) << std::left << state_->snorm; hist << std::setw(15) << std::left << state_->searchSize; - hist << std::setw(10) << std::left << state_->nfval; + hist << std::setw(10) << std::left << state_->nsval; + hist << std::setw(10) << std::left << state_->nnval; hist << std::setw(10) << std::left << state_->ngrad; - hist << std::setw(10) << std::left << state_->nprox; + hist << std::setw(10) << std::left << state_->nprox; hist << std::endl; } os << hist.str(); diff --git a/packages/rol/src/function/objective/ROL_l1Objective.hpp b/packages/rol/src/function/objective/ROL_l1Objective.hpp index a04901326ca8..c0ace5a13163 100644 --- a/packages/rol/src/function/objective/ROL_l1Objective.hpp +++ b/packages/rol/src/function/objective/ROL_l1Objective.hpp @@ -48,7 +48,7 @@ /** @ingroup func_group \class ROL::l1Objective - \brief Provides the interface to evaluate the l1 objective. + \brief Provides the interface to evaluate the weighted/shifted l1 objective function. --- */ @@ -60,49 +60,51 @@ template class l1Objective : public Objective { private: const Ptr> weights_, shift_; - Ptr> tmp_; + Ptr> tmp_; + struct ProjSymBnd : public Elementwise::BinaryFunction { Real apply(const Real &xc, const Real &yc) const { return std::min(yc, std::max(-yc, xc)); } - } psb_; + } psb_; public: - l1Objective(const Ptr> &weights) : weights_(weights), shift_(weights->clone()) { - shift_->zero(); - tmp_ = shift_->clone(); - } - l1Objective(const Ptr> &weights, const Ptr> &shift) : weights_(weights), shift_(shift) { - tmp_ = shift_->clone(); - } + l1Objective(const Ptr> &weights) + : weights_(weights), shift_(weights->clone()) { + shift_->zero(); + tmp_ = shift_->clone(); + } + + l1Objective(const Ptr> &weights, const Ptr> &shift) + : weights_(weights), shift_(shift) { + tmp_ = shift_->clone(); + } Real value( const Vector &x, Real &tol ) { - tmp_->set(x); + tmp_->set(x); tmp_->axpy(static_cast(-1),*shift_); tmp_->applyUnary(Elementwise::AbsoluteValue()); Real val = weights_->apply(*tmp_); return val; - } + } void gradient( Vector &g, const Vector &x, Real &tol ) { - g.set(x); + g.set(x); g.axpy(static_cast(-1),*shift_); g.applyUnary(Elementwise::Sign()); g.applyBinary(Elementwise::Multiply(), *weights_); - } + } - Real dirDeriv( const Vector &x, const Vector &d, Real &tol ) { - gradient(*tmp_, x, tol); - return tmp_->apply(d); - } + gradient(*tmp_, x, tol); + return tmp_->apply(d); + } - - void prox( Vector &Pv, const Vector &v, Real t, Real &tol){ - Pv.set(*shift_); - Pv.axpy(static_cast(-1)/t, v); - Pv.applyBinary(psb_, *weights_); - Pv.scale(t); - Pv.plus(v); + void prox( Vector &Pv, const Vector &v, Real t, Real &tol){ + Pv.set(*shift_); + Pv.axpy(static_cast(-1)/t, v); + Pv.applyBinary(psb_, *weights_); + Pv.scale(t); + Pv.plus(v); } }; // class l1Objective diff --git a/packages/rol/test/algorithm/TypeP/test_01.cpp b/packages/rol/test/algorithm/TypeP/test_01.cpp index 330bbdf6a805..d39ab7c50d11 100644 --- a/packages/rol/test/algorithm/TypeP/test_01.cpp +++ b/packages/rol/test/algorithm/TypeP/test_01.cpp @@ -41,73 +41,53 @@ // ************************************************************************ // @HEADER -/*! \file test_23.cpp - \brief Validate projected gradient algorithm. +/*! \file test_01.cpp + \brief Validate proximal gradient algorithm. */ #include "ROL_TypeP_ProxGradientAlgorithm.hpp" +#include "ROL_StdObjective.hpp" #include "ROL_l1Objective.hpp" #include "ROL_Stream.hpp" #include "Teuchos_GlobalMPISession.hpp" -#include "ROL_StdObjective.hpp" -template -class quad : public ROL::StdObjective { - private: - int dim_; - std::vector a_, b_; - public: - quad(int dim) : dim_(dim) { - a_.resize(dim); - b_.resize(dim); - - for (int i = 0; i(rand())/static_cast(RAND_MAX); - b_[i] = static_cast(2)*static_cast(rand())/static_cast(RAND_MAX) - static_cast(1); - } - } - - Real value(const std::vector &x, Real &tol){ - Real val(0); - for (int i = 0; i(0.5)*a_[i]*x[i]*x[i] + b_[i]*x[i]; - } - return val; - } - - void gradient(std::vector &g, const std::vector &x, Real &tol){ - - for (int i = 0; i &hv, const std::vector &v, const std::vector &x, Real &tol){ - - for (int i = 0; i &x, const std::vector &wts, const std::vector &y) const { - Real tmp(0); - - for (int i = 0; i y[i]){ - x[i] = tmp; - } - else{ - tmp = (wts[i] - b_[i])/a_[i]; - if (tmp < y[i]){ - x[i] = tmp; - } - else{ - x[i] = y[i]; - } - } - } - } +template +class QuadraticTypeP_Test01 : public ROL::StdObjective { +private: + int dim_; + std::vector a_, b_; + +public: + QuadraticTypeP_Test01(int dim) : dim_(dim) { + a_.resize(dim); + b_.resize(dim); + for (int i = 0; i < dim; ++i) { + a_[i] = static_cast(5)*static_cast(rand())/static_cast(RAND_MAX); + b_[i] = static_cast(20)*static_cast(rand())/static_cast(RAND_MAX) - static_cast(10); + } + } + + Real value(const std::vector &x, Real &tol) { + Real val(0); + for (int i = 0; i < dim_; ++i) + val += static_cast(0.5)*a_[i]*x[i]*x[i] + b_[i]*x[i]; + return val; + } + + void gradient(std::vector &g, const std::vector &x, Real &tol) { + for (int i = 0; i < dim_; ++i) + g[i] = a_[i]*x[i] + b_[i]; + } + + void hessVec(std::vector &hv, const std::vector &v, const std::vector &x, Real &tol) { + for (int i = 0; i < dim_; ++i) + hv[i] = a_[i]*v[i]; + } + + void getSolution(std::vector &x, const std::vector &wts, const std::vector &y) const { + for (int i = 0; i < dim_; ++i) + x[i] = (std::min(wts[i], std::max(-wts[i], a_[i]*y[i] + b_[i])) - b_[i]) / a_[i]; + } }; typedef double RealT; @@ -130,56 +110,60 @@ int main(int argc, char *argv[]) { try { RealT tol = 1e2*std::sqrt(ROL::ROL_EPSILON()); - + ROL::ParameterList list; + list.sublist("General").set("Output Level",iprint); + list.sublist("Step").set("Type","Line Search"); + list.sublist("Step").sublist("Line Search").set("Initial Step Size",1e0); + list.sublist("Step").sublist("Line Search").set("Maximum Step Size",1e8); + list.sublist("Step").sublist("Line Search").set("User Defined Initial Step Size",true); + list.sublist("Step").sublist("Line Search").set("Use Adaptive Step Size Selection",true); list.sublist("Status Test").set("Gradient Tolerance",1e-7); list.sublist("Status Test").set("Constraint Tolerance",1e-8); list.sublist("Status Test").set("Step Tolerance",1e-12); - list.sublist("Status Test").set("Iteration Limit", 250); - list.sublist("Step").set("Type","Line Search"); - list.sublist("General").set("Output Level",iprint); - - int dim = 5; - ROL::Ptr> sol, wts, y; - ROL::Ptr> nobj; - ROL::Ptr> sobj; + list.sublist("Status Test").set("Iteration Limit", 10000); + + int dim = 5; + ROL::Ptr> sol, wts, y; + ROL::Ptr> sobj; + ROL::Ptr> nobj; ROL::Ptr> algo; std::vector data; - RealT e1, e2, e3, e4, e5, err; + RealT err(0); - *outStream << std::endl << "Diagonal LASSO" << std::endl << std::endl; - ROL::Ptr> wtsP = ROL::makePtr>(dim); - ROL::Ptr> yP = ROL::makePtr>(dim); - wts = ROL::makePtr>(wtsP); + *outStream << std::endl << "Random Diagonal LASSO Test Problem" << std::endl << std::endl; + ROL::Ptr> wtsP = ROL::makePtr>(dim); + ROL::Ptr> yP = ROL::makePtr>(dim); + wts = ROL::makePtr>(wtsP); y = ROL::makePtr>(yP); sol = ROL::makePtr>(dim); - wts->randomize(0.0,1.0); - y->randomize(-5.0, 5.0); - sol->zero(); - + wts->randomize(static_cast(0),static_cast(1)); + y->randomize(static_cast(-5),static_cast(5)); + sol->zero(); - nobj = ROL::makePtr>(wts,y); - sobj = ROL::makePtr>(dim); + nobj = ROL::makePtr>(wts,y); + sobj = ROL::makePtr>(dim); algo = ROL::makePtr>(list); algo->run(*sol,*sobj,*nobj,*outStream); - std::vector xstar(dim); - sobj->getSolution(xstar, *wtsP, *yP); + std::vector xstar(dim); + sobj->getSolution(xstar, *wtsP, *yP); data = *ROL::staticPtrCast>(sol)->getVector(); - *outStream << " Result: x1 = " << data[0] << " x2 = " << data[1] - << " x3 = " << data[2] << " x4 = " << data[3] << " x5 = " << data[4] << std::endl; - e1 = (data[0]-xstar[0]); - e2 = (data[1]-xstar[1]); - e3 = (data[2]-xstar[2]); - e4 = (data[3]-xstar[3]); - e5 = (data[4]-xstar[4]); - err = std::max(std::max(std::max(std::max(std::abs(e1),std::abs(e2)),std::abs(e3)),std::abs(e4)),std::abs(e5)); + *outStream << " Result: "; + for (int i = 0; i < dim; ++i) { + *outStream << " x" << i+1 << " = " << data[i]; + err = std::max(err,std::abs(data[i]-xstar[i])); + } + *outStream << std::endl; + *outStream << " Truth: "; + for (int i = 0; i < dim; ++i) { + *outStream << " x" << i+1 << " = " << xstar[i]; + } + *outStream << std::endl; *outStream << " Max-Error = " << err << std::endl; errorFlag += (err > tol ? 1 : 0); - - } - + } catch (std::logic_error& err) { *outStream << err.what() << "\n"; errorFlag = -1000; @@ -192,4 +176,3 @@ int main(int argc, char *argv[]) { return 0; } - From 4d06e8cbab1e24a325e288e1394858d36b560429 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Tue, 20 Dec 2022 20:19:24 -0700 Subject: [PATCH 05/65] Update ROL_TypeP_ProxGradientAlgorithm_Def.hpp Fixed issue with optimality criterion. --- .../algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp index 89c0f4e5f7d2..2fc63aa8c485 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp @@ -308,8 +308,8 @@ void ProxGradientAlgorithm::run( Vector &x, s->set(x); s->axpy(-t0_,*state_->stepVec); nobj.prox(*px,*s,t0_,tol); state_->nprox++; - s->axpy(-one,x); - state_->gnorm = s->norm() / t0_; + px->axpy(-one,x); + state_->gnorm = px->norm() / t0_; // Update Output if (verbosity_ > 0) writeOutput(outStream,writeHeader_); From fd58b9f519d1064d1862f3aec223f2a9d154d0af Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Tue, 20 Dec 2022 20:37:38 -0700 Subject: [PATCH 06/65] Minor clean up. --- .../TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp | 12 +++++------- .../rol/src/function/objective/ROL_l1Objective.hpp | 5 ++--- packages/rol/test/algorithm/TypeP/test_01.cpp | 2 +- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp index 2fc63aa8c485..b644de1adc15 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp @@ -140,7 +140,7 @@ void ProxGradientAlgorithm::run( Vector &x, std::ostream &outStream ) { const Real one(1); // Initialize trust-region data - Ptr> px = x.clone(), s = x.clone(); + Ptr> px = x.clone(), s = x.clone(), pxP = x.clone(); initialize(x,g,sobj,nobj,*px,outStream); Real strial(0), ntrial(0), Ftrial(0), strialP(0), ntrialP(0), FtrialP(0); Real Qk(0), alphaP(0), tol(std::sqrt(ROL_EPSILON())); @@ -195,11 +195,13 @@ void ProxGradientAlgorithm::run( Vector &x, // Previous value was acceptable sobj.update(*state_->iterateVec,UpdateType::Accept); nobj.update(*state_->iterateVec,UpdateType::Accept); - // Increase search size + // Backup previous values to avoid recomputation + pxP->set(*state_->iterateVec); alphaP = state_->searchSize; strialP = strial; ntrialP = ntrial; FtrialP = Ftrial; + // Increase search size state_->searchSize *= rhoinc_; state_->searchSize = std::min(state_->searchSize,maxAlpha_); // Compute proximal gradient step with new search size @@ -230,15 +232,11 @@ void ProxGradientAlgorithm::run( Vector &x, } } if (Ftrial - state_->value > c1_*Qk || Ftrial > FtrialP) { + state_->iterateVec->set(*pxP); strial = strialP; ntrial = ntrialP; Ftrial = FtrialP; state_->searchSize = alphaP; - // Recompute proximal gradient step - px->set(x); - px->axpy(-state_->searchSize,*state_->stepVec); - nobj.prox(*state_->iterateVec,*px,state_->searchSize,tol); - state_->nprox++; s->set(*state_->iterateVec); s->axpy(-one,x); accept = false; diff --git a/packages/rol/src/function/objective/ROL_l1Objective.hpp b/packages/rol/src/function/objective/ROL_l1Objective.hpp index c0ace5a13163..cf5217944a9d 100644 --- a/packages/rol/src/function/objective/ROL_l1Objective.hpp +++ b/packages/rol/src/function/objective/ROL_l1Objective.hpp @@ -69,7 +69,7 @@ class l1Objective : public Objective { public: l1Objective(const Ptr> &weights) - : weights_(weights), shift_(weights->clone()) { + : weights_(weights), shift_(weights->dual().clone()) { shift_->zero(); tmp_ = shift_->clone(); } @@ -83,8 +83,7 @@ class l1Objective : public Objective { tmp_->set(x); tmp_->axpy(static_cast(-1),*shift_); tmp_->applyUnary(Elementwise::AbsoluteValue()); - Real val = weights_->apply(*tmp_); - return val; + return weights_->apply(*tmp_); } void gradient( Vector &g, const Vector &x, Real &tol ) { diff --git a/packages/rol/test/algorithm/TypeP/test_01.cpp b/packages/rol/test/algorithm/TypeP/test_01.cpp index d39ab7c50d11..7322a0ca3f01 100644 --- a/packages/rol/test/algorithm/TypeP/test_01.cpp +++ b/packages/rol/test/algorithm/TypeP/test_01.cpp @@ -112,7 +112,7 @@ int main(int argc, char *argv[]) { RealT tol = 1e2*std::sqrt(ROL::ROL_EPSILON()); ROL::ParameterList list; - list.sublist("General").set("Output Level",iprint); + list.sublist("General").set("Output Level",iprint+10); list.sublist("Step").set("Type","Line Search"); list.sublist("Step").sublist("Line Search").set("Initial Step Size",1e0); list.sublist("Step").sublist("Line Search").set("Maximum Step Size",1e8); From a76e245ccb6df99cef1f92f381364dc458457a07 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Wed, 21 Dec 2022 09:38:34 -0700 Subject: [PATCH 07/65] Fixed bug in l1 prox. Further clean ups of PG code. --- .../TypeP/ROL_TypeP_ProxGradientAlgorithm.hpp | 15 ++- .../ROL_TypeP_ProxGradientAlgorithm_Def.hpp | 91 +++++++++---------- .../function/objective/ROL_l1Objective.hpp | 3 +- packages/rol/test/algorithm/TypeP/test_01.cpp | 13 ++- 4 files changed, 69 insertions(+), 53 deletions(-) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm.hpp index a0afe96fb9dd..03ad5cd1fa45 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm.hpp @@ -69,7 +69,8 @@ class ProxGradientAlgorithm : public TypeP::Algorithm { const Vector &g, Objective &sobj, Objective &nobj, - Vector &px, + Vector &px, + Vector &dg, std::ostream &outStream = std::cout); public: @@ -79,7 +80,7 @@ class ProxGradientAlgorithm : public TypeP::Algorithm { void run( Vector &x, const Vector &g, Objective &sobj, - Objective &nobj, + Objective &nobj, std::ostream &outStream = std::cout) override; void writeHeader( std::ostream& os ) const override; @@ -88,6 +89,16 @@ class ProxGradientAlgorithm : public TypeP::Algorithm { void writeOutput( std::ostream& os, bool write_header = false ) const override; +private: + + void pgstep(Vector &pgiter, // pgiter = Prox(x - t dg) + Vector &pgstep, // pgstep = pgiter - x + Objective &nobj, // nobj = nonsmooth objective + const Vector &x, // x = current iterate + const Vector &dg, // dg = dual of current gradient + Real t, // t = prox parameter + Real &tol) const; + }; // class ROL::TypeP::GradientAlgorithm } // namespace TypeP diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp index b644de1adc15..ccadb19ee227 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp @@ -77,15 +77,16 @@ void ProxGradientAlgorithm::initialize(Vector &x, Objective &sobj, Objective &nobj, Vector &px, + Vector &dg, std::ostream &outStream) { const Real one(1); // Initialize data TypeP::Algorithm::initialize(x,g); // Update approximate gradient and approximate objective function. Real ftol = std::sqrt(ROL_EPSILON()); - nobj.prox(px,x,state_->searchSize,ftol); + nobj.prox(*state_->iterateVec,x,state_->searchSize,ftol); state_->nprox++; - x.set(px); //revisit with option to do initial prox or not + x.set(*state_->iterateVec); //revisit with option to do initial prox or not // Evaluate objective function sobj.update(x,UpdateType::Initial,state_->iter); state_->svalue = sobj.value(x,ftol); @@ -97,23 +98,19 @@ void ProxGradientAlgorithm::initialize(Vector &x, // Evaluate gradient of smooth part sobj.gradient(*state_->gradientVec,x,ftol); state_->ngrad++; + dg.set(state_->gradientVec->dual()); // Evaluate proximal gradient - state_->stepVec->set(x); - state_->stepVec->axpy(-t0_,state_->gradientVec->dual()); - nobj.prox(px,*state_->stepVec,t0_,ftol); - state_->nprox++; - state_->stepVec->set(px); + pgstep(px, *state_->stepVec, nobj, x, dg, t0_, ftol); // Compute initial step size Real fnew = state_->svalue; if (!useralpha_) { - // Evaluate objective at P(x - g) - sobj.update(*state_->stepVec,UpdateType::Trial); - fnew = sobj.value(*state_->stepVec,ftol); + // Evaluate objective at Prox(x - t0 dg) + sobj.update(px,UpdateType::Trial); + fnew = sobj.value(px,ftol); sobj.update(x,UpdateType::Revert); state_->nsval++; } - state_->stepVec->axpy(-one,x); - state_->gnorm = state_->stepVec->norm()/t0_; + state_->gnorm = state_->stepVec->norm() / t0_; state_->snorm = ROL_INF(); if (!useralpha_) { const Real half(0.5); @@ -139,11 +136,12 @@ void ProxGradientAlgorithm::run( Vector &x, Objective &nobj, std::ostream &outStream ) { const Real one(1); + Real tol(std::sqrt(ROL_EPSILON())); // Initialize trust-region data - Ptr> px = x.clone(), s = x.clone(), pxP = x.clone(); - initialize(x,g,sobj,nobj,*px,outStream); - Real strial(0), ntrial(0), Ftrial(0), strialP(0), ntrialP(0), FtrialP(0); - Real Qk(0), alphaP(0), tol(std::sqrt(ROL_EPSILON())); + Ptr> px = x.clone(), pxP = x.clone(), dg = x.clone(); + initialize(x,g,sobj,nobj,*px,*dg,outStream); + Real strial(0), ntrial(0), Ftrial(0), Qk(0); + Real strialP(0), ntrialP(0), FtrialP(0), alphaP(0); int ls_nfval = 0; bool incAlpha = false, accept = true; @@ -151,18 +149,12 @@ void ProxGradientAlgorithm::run( Vector &x, if (verbosity_ > 0) writeOutput(outStream,true); // Compute steepest descent step - state_->stepVec->set(state_->gradientVec->dual()); while (status_->check(*state_)) { accept = true; // Perform backtracking line search if (!usePrevAlpha_ && !useAdapt_) state_->searchSize = alpha0_; // Compute proximal gradient step with initial search size - px->set(x); - px->axpy(-state_->searchSize,*state_->stepVec); - nobj.prox(*state_->iterateVec,*px,state_->searchSize,tol); - state_->nprox++; - s->set(*state_->iterateVec); - s->axpy(-one,x); + pgstep(*state_->iterateVec, *state_->stepVec, nobj, x, *dg, state_->searchSize, tol); // Compute objective function values sobj.update(*state_->iterateVec,UpdateType::Trial); strial = sobj.value(*state_->iterateVec,tol); @@ -171,7 +163,7 @@ void ProxGradientAlgorithm::run( Vector &x, Ftrial = strial + ntrial; ls_nfval = 1; // Compute decrease indicator - Qk = s->dot(*state_->stepVec) + ntrial - state_->nvalue; + Qk = state_->gradientVec->apply(*state_->stepVec) + ntrial - state_->nvalue; incAlpha = (Ftrial - state_->value <= c1_*Qk); if (verbosity_ > 1) { outStream << " In TypeP::GradientAlgorithm: Line Search" << std::endl; @@ -205,12 +197,7 @@ void ProxGradientAlgorithm::run( Vector &x, state_->searchSize *= rhoinc_; state_->searchSize = std::min(state_->searchSize,maxAlpha_); // Compute proximal gradient step with new search size - px->set(x); - px->axpy(-state_->searchSize,*state_->stepVec); - nobj.prox(*state_->iterateVec,*px,state_->searchSize,tol); - state_->nprox++; - s->set(*state_->iterateVec); - s->axpy(-one,x); + pgstep(*state_->iterateVec, *state_->stepVec, nobj, x, *dg, state_->searchSize, tol); // Compute objective function values sobj.update(*state_->iterateVec,UpdateType::Trial); strial = sobj.value(*state_->iterateVec,tol); @@ -219,7 +206,7 @@ void ProxGradientAlgorithm::run( Vector &x, Ftrial = strial + ntrial; ls_nfval++; // Compute decrease indicator - Qk = s->dot(*state_->stepVec) + ntrial - state_->nvalue; + Qk = state_->gradientVec->apply(*state_->stepVec) + ntrial - state_->nvalue; if (verbosity_ > 1) { outStream << std::endl; outStream << " Step size: " << state_->searchSize << std::endl; @@ -237,8 +224,8 @@ void ProxGradientAlgorithm::run( Vector &x, ntrial = ntrialP; Ftrial = FtrialP; state_->searchSize = alphaP; - s->set(*state_->iterateVec); - s->axpy(-one,x); + state_->stepVec->set(*state_->iterateVec); + state_->stepVec->axpy(-one,x); accept = false; } } @@ -247,12 +234,7 @@ void ProxGradientAlgorithm::run( Vector &x, // Decrease search size state_->searchSize *= rhodec_; // Compute proximal gradient step with new search size - px->set(x); - px->axpy(-state_->searchSize,*state_->stepVec); - nobj.prox(*state_->iterateVec,*px,state_->searchSize,tol); - state_->nprox++; - s->set(*state_->iterateVec); - s->axpy(-one,x); + pgstep(*state_->iterateVec, *state_->stepVec, nobj, x, *dg, state_->searchSize, tol); // Compute objective function values sobj.update(*state_->iterateVec,UpdateType::Trial); strial = sobj.value(*state_->iterateVec,tol); @@ -261,7 +243,7 @@ void ProxGradientAlgorithm::run( Vector &x, Ftrial = strial + ntrial; ls_nfval++; // Compute decrease indicator - Qk = s->dot(*state_->stepVec) + ntrial - state_->nvalue; + Qk = state_->gradientVec->apply(*state_->stepVec) + ntrial - state_->nvalue; if (verbosity_ > 1) { outStream << std::endl; outStream << " Step size: " << state_->searchSize << std::endl; @@ -276,15 +258,15 @@ void ProxGradientAlgorithm::run( Vector &x, } state_->nsval += ls_nfval; state_->nnval += ls_nfval; + // Compute norm of step - state_->stepVec->set(*s); state_->snorm = state_->stepVec->norm(); // Update iterate + state_->iter++; x.set(*state_->iterateVec); // Compute new value and gradient - state_->iter++; state_->svalue = strial; state_->nvalue = ntrial; state_->value = Ftrial; @@ -298,15 +280,10 @@ void ProxGradientAlgorithm::run( Vector &x, } sobj.gradient(*state_->gradientVec,x,tol); state_->ngrad++; - - // Compute steepest descent step - state_->stepVec->set(state_->gradientVec->dual()); + dg->set(state_->gradientVec->dual()); // Compute projected gradient norm - s->set(x); s->axpy(-t0_,*state_->stepVec); - nobj.prox(*px,*s,t0_,tol); - state_->nprox++; - px->axpy(-one,x); + pgstep(*pxP, *px, nobj, x, *dg, t0_, tol); state_->gnorm = px->norm() / t0_; // Update Output @@ -315,6 +292,22 @@ void ProxGradientAlgorithm::run( Vector &x, if (verbosity_ > 0) TypeP::Algorithm::writeExitStatus(outStream); } +template +void ProxGradientAlgorithm::pgstep(Vector &pgiter, + Vector &pgstep, + Objective &nobj, + const Vector &x, + const Vector &dg, + Real t, + Real &tol) const { + pgstep.set(x); + pgstep.axpy(-t,dg); + nobj.prox(pgiter,pgstep,t,tol); + state_->nprox++; + pgstep.set(pgiter); + pgstep.axpy(static_cast(-1),x); +} + template void ProxGradientAlgorithm::writeHeader( std::ostream& os ) const { std::stringstream hist; diff --git a/packages/rol/src/function/objective/ROL_l1Objective.hpp b/packages/rol/src/function/objective/ROL_l1Objective.hpp index cf5217944a9d..4ca6eace5e19 100644 --- a/packages/rol/src/function/objective/ROL_l1Objective.hpp +++ b/packages/rol/src/function/objective/ROL_l1Objective.hpp @@ -100,7 +100,8 @@ class l1Objective : public Objective { void prox( Vector &Pv, const Vector &v, Real t, Real &tol){ Pv.set(*shift_); - Pv.axpy(static_cast(-1)/t, v); + Pv.axpy(static_cast(-1), v); + Pv.scale(static_cast(1) / t); Pv.applyBinary(psb_, *weights_); Pv.scale(t); Pv.plus(v); diff --git a/packages/rol/test/algorithm/TypeP/test_01.cpp b/packages/rol/test/algorithm/TypeP/test_01.cpp index 7322a0ca3f01..433bab64d368 100644 --- a/packages/rol/test/algorithm/TypeP/test_01.cpp +++ b/packages/rol/test/algorithm/TypeP/test_01.cpp @@ -112,7 +112,7 @@ int main(int argc, char *argv[]) { RealT tol = 1e2*std::sqrt(ROL::ROL_EPSILON()); ROL::ParameterList list; - list.sublist("General").set("Output Level",iprint+10); + list.sublist("General").set("Output Level",iprint); list.sublist("Step").set("Type","Line Search"); list.sublist("Step").sublist("Line Search").set("Initial Step Size",1e0); list.sublist("Step").sublist("Line Search").set("Maximum Step Size",1e8); @@ -144,6 +144,17 @@ int main(int argc, char *argv[]) { nobj = ROL::makePtr>(wts,y); sobj = ROL::makePtr>(dim); + // Check derivatives of smooth function + ROL::Ptr> xd = sol->clone(); + xd->randomize(-1.0,1.0); + ROL::Ptr> yd = sol->clone(); + yd->randomize(-1.0,1.0); + ROL::Ptr> zd = sol->clone(); + zd->randomize(-1.0,1.0); + sobj->checkGradient(*xd,*yd,true,*outStream); + sobj->checkHessVec(*xd,*yd,true,*outStream); + sobj->checkHessSym(*xd,*yd,*zd,true,*outStream); + algo = ROL::makePtr>(list); algo->run(*sol,*sobj,*nobj,*outStream); From 7b3104d4322ea11eae71b2dca5581f4bf4de6fa9 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Wed, 21 Dec 2022 10:58:13 -0700 Subject: [PATCH 08/65] Added SPG implementation for TypeP. --- .../algorithm/TypeP/ROL_TypeP_Algorithm.hpp | 7 + .../TypeP/ROL_TypeP_Algorithm_Def.hpp | 16 + .../TypeP/ROL_TypeP_ProxGradientAlgorithm.hpp | 11 +- .../ROL_TypeP_ProxGradientAlgorithm_Def.hpp | 18 +- .../ROL_TypeP_SpectralGradientAlgorithm.hpp | 99 ++++++ ...OL_TypeP_SpectralGradientAlgorithm_Def.hpp | 298 ++++++++++++++++++ .../rol/test/algorithm/TypeP/CMakeLists.txt | 9 + packages/rol/test/algorithm/TypeP/test_02.cpp | 185 +++++++++++ 8 files changed, 616 insertions(+), 27 deletions(-) create mode 100644 packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm.hpp create mode 100644 packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm_Def.hpp create mode 100644 packages/rol/test/algorithm/TypeP/test_02.cpp diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm.hpp index d1d9486440c5..3384540ae7ad 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm.hpp @@ -93,6 +93,13 @@ class Algorithm { const Ptr> state_; void initialize(const Vector &x, const Vector &g); + void pgstep(Vector &pgiter, // pgiter = Prox(x - t dg) + Vector &pgstep, // pgstep = pgiter - x + Objective &nobj, // nobj = nonsmooth objective + const Vector &x, // x = current iterate + const Vector &dg, // dg = dual of current gradient + Real t, // t = prox parameter + Real &tol) const; public: diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm_Def.hpp index 3dcf3bab8cd9..86f97130d81c 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm_Def.hpp @@ -76,6 +76,22 @@ void Algorithm::initialize(const Vector &x, const Vector &g) { state_->minValue = state_->value; } +template +void Algorithm::pgstep(Vector &pgiter, + Vector &pgstep, + Objective &nobj, + const Vector &x, + const Vector &dg, + Real t, + Real &tol) const { + pgstep.set(x); + pgstep.axpy(-t,dg); + nobj.prox(pgiter,pgstep,t,tol); + state_->nprox++; + pgstep.set(pgiter); + pgstep.axpy(static_cast(-1),x); +} + template void Algorithm::setStatusTest(const Ptr> &status, bool combineStatus) { diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm.hpp index 03ad5cd1fa45..57be7af87c9c 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm.hpp @@ -64,6 +64,7 @@ class ProxGradientAlgorithm : public TypeP::Algorithm { using TypeP::Algorithm::status_; using TypeP::Algorithm::state_; + using TypeP::Algorithm::pgstep; void initialize(Vector &x, const Vector &g, @@ -89,16 +90,6 @@ class ProxGradientAlgorithm : public TypeP::Algorithm { void writeOutput( std::ostream& os, bool write_header = false ) const override; -private: - - void pgstep(Vector &pgiter, // pgiter = Prox(x - t dg) - Vector &pgstep, // pgstep = pgiter - x - Objective &nobj, // nobj = nonsmooth objective - const Vector &x, // x = current iterate - const Vector &dg, // dg = dual of current gradient - Real t, // t = prox parameter - Real &tol) const; - }; // class ROL::TypeP::GradientAlgorithm } // namespace TypeP diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp index ccadb19ee227..046414d693e8 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp @@ -292,22 +292,6 @@ void ProxGradientAlgorithm::run( Vector &x, if (verbosity_ > 0) TypeP::Algorithm::writeExitStatus(outStream); } -template -void ProxGradientAlgorithm::pgstep(Vector &pgiter, - Vector &pgstep, - Objective &nobj, - const Vector &x, - const Vector &dg, - Real t, - Real &tol) const { - pgstep.set(x); - pgstep.axpy(-t,dg); - nobj.prox(pgiter,pgstep,t,tol); - state_->nprox++; - pgstep.set(pgiter); - pgstep.axpy(static_cast(-1),x); -} - template void ProxGradientAlgorithm::writeHeader( std::ostream& os ) const { std::stringstream hist; @@ -316,7 +300,7 @@ void ProxGradientAlgorithm::writeHeader( std::ostream& os ) const { hist << "Proximal gradient descent"; hist << " status output definitions" << std::endl << std::endl; hist << " iter - Number of iterates (steps taken)" << std::endl; - hist << " obj - Objective function value" << std::endl; + hist << " value - Objective function value" << std::endl; hist << " gnorm - Norm of the proximal gradient" << std::endl; hist << " snorm - Norm of the step (update to optimization vector)" << std::endl; hist << " alpha - Line search step length" << std::endl; diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm.hpp new file mode 100644 index 000000000000..b5f93e7778c7 --- /dev/null +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm.hpp @@ -0,0 +1,99 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +#ifndef ROL_TYPEP_SPECTRALGRADIENTALGORITHM_HPP +#define ROL_TYPEP_SPECTRALGRADIENTALGORITHM_HPP + +#include "ROL_TypeP_Algorithm.hpp" + +/** \class ROL::TypeP::SpectralGradientAlgorithm + \brief Provides an interface to run the proximal gradient algorithm. +*/ + +namespace ROL { +namespace TypeP { + +template +class SpectralGradientAlgorithm : public TypeP::Algorithm { +private: + int maxit_, maxSize_; + Real lambda_, lambdaMin_, lambdaMax_, sigma1_, sigma2_, rhodec_, gamma_, t0_; + int verbosity_; + bool writeHeader_; + + using TypeP::Algorithm::status_; + using TypeP::Algorithm::state_; + using TypeP::Algorithm::pgstep; + + void initialize(Vector &x, + const Vector &g, + Objective &sobj, + Objective &nobj, + Vector &px, + Vector &dg, + std::ostream &outStream = std::cout); +public: + + SpectralGradientAlgorithm(ParameterList &list); + + using TypeP::Algorithm::run; + void run( Vector &x, + const Vector &g, + Objective &sobj, + Objective &nobj, + std::ostream &outStream = std::cout) override; + + void writeHeader( std::ostream& os ) const override; + + void writeName( std::ostream& os ) const override; + + void writeOutput( std::ostream& os, bool write_header = false ) const override; + +}; // class ROL::TypeP::SpectralGradientAlgorithm + +} // namespace TypeP +} // namespace ROL + +#include "ROL_TypeP_SpectralGradientAlgorithm_Def.hpp" + +#endif diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm_Def.hpp new file mode 100644 index 000000000000..b6ee3d73c73e --- /dev/null +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm_Def.hpp @@ -0,0 +1,298 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +#ifndef ROL_TYPEP_SPECTRALGRADIENTALGORITHM_DEF_HPP +#define ROL_TYPEP_SPECTRALGRADIENTALGORITHM_DEF_HPP + +namespace ROL { +namespace TypeP { + +template +SpectralGradientAlgorithm::SpectralGradientAlgorithm(ParameterList &list) { + // Set status test + status_->reset(); + status_->add(makePtr>(list)); + + // Parse parameter list + ParameterList &lslist = list.sublist("Step").sublist("Spectral Gradient"); + maxit_ = lslist.get("Function Evaluation Limit", 20); + lambda_ = lslist.get("Initial Spectral Step Size", -1.0); + lambdaMin_ = lslist.get("Minimum Spectral Step Size", 1e-8); + lambdaMax_ = lslist.get("Maximum Spectral Step Size", 1e8); + sigma1_ = lslist.get("Lower Step Size Safeguard", 0.1); + sigma2_ = lslist.get("Upper Step Size Safeguard", 0.9); + rhodec_ = lslist.get("Backtracking Rate", 1e-1); + gamma_ = lslist.get("Sufficient Decrease Tolerance", 1e-4); + maxSize_ = lslist.get("Maximum Storage Size", 10); + t0_ = list.sublist("Status Test").get("Gradient Scale" , 1.0); + verbosity_ = list.sublist("General").get("Output Level", 0); + writeHeader_ = verbosity_ > 2; +} + +template +void SpectralGradientAlgorithm::initialize(Vector &x, + const Vector &g, + Objective &sobj, + Objective &nobj, + Vector &px, + Vector &dg, + std::ostream &outStream) { + const Real zero(0); + Real ftol = std::sqrt(ROL_EPSILON()); + // Initialize data + TypeP::Algorithm::initialize(x,g); + // Update approximate gradient and approximate objective function. + nobj.prox(*state_->iterateVec,x,t0_,ftol); state_->nprox++; + x.set(*state_->iterateVec); + sobj.update(x,UpdateType::Initial,state_->iter); + state_->svalue = sobj.value(x,ftol); state_->nsval++; + nobj.update(x,UpdateType::Initial,state_->iter); + state_->nvalue = nobj.value(x,ftol); state_->nnval++; + sobj.gradient(*state_->gradientVec,x,ftol); state_->ngrad++; + dg.set(state_->gradientVec->dual()); + pgstep(px, *state_->stepVec, nobj, x, dg, t0_, ftol); + state_->gnorm = state_->stepVec->norm() / t0_; + state_->snorm = ROL_INF(); + if (lambda_ <= zero && state_->gnorm != zero) + lambda_ = std::max(lambdaMin_,std::min(t0_,lambdaMax_)); +} + +template +void SpectralGradientAlgorithm::run( Vector &x, + const Vector &g, + Objective &sobj, + Objective &nobj, + std::ostream &outStream ) { + const Real half(0.5), one(1), eps(std::sqrt(ROL_EPSILON())); + // Initialize trust-region data + Ptr> s = x.clone(), px = x.clone(), dg = x.clone(), y = g.clone(), xmin = x.clone(); + initialize(x,g,sobj,nobj,*s,*dg,outStream); + Real strial(0), ntrial(0), Ftrial(0), Fmin(0), Fmax(0), Qk(0), alpha(1), alphaTmp(1); + Real gs(0), ys(0), ss(0), tol(std::sqrt(ROL_EPSILON())); + int ls_nfval = 0; + std::deque Fqueue; Fqueue.push_back(state_->value); + + Fmin = state_->value; + xmin->set(x); + + // Output + if (verbosity_ > 0) writeOutput(outStream, true); + + // Iterate spectral projected gradient + while (status_->check(*state_)) { + // Compute spectral proximal gradient step + pgstep(*state_->iterateVec, *state_->stepVec, nobj, x, *dg, lambda_, tol); + + // Nonmonotone Linesearch + ls_nfval = 0; + sobj.update(*state_->iterateVec,UpdateType::Trial); + strial = sobj.value(*state_->iterateVec,tol); + nobj.update(*state_->iterateVec,UpdateType::Trial); + ntrial = nobj.value(*state_->iterateVec,tol); + Ftrial = strial + ntrial; + ls_nfval++; + alpha = one; + Fmax = *std::max_element(Fqueue.begin(),Fqueue.end()); + gs = state_->gradientVec->apply(*state_->stepVec); + Qk = gs + ntrial - state_->nvalue; + if (verbosity_ > 1) { + outStream << " In TypeP::SpectralGradientAlgorithm Line Search" << std::endl; + outStream << " Step size: " << alpha << std::endl; + outStream << " Trial objective value: " << Ftrial << std::endl; + outStream << " Max stored objective value: " << Fmax << std::endl; + outStream << " Computed reduction: " << Fmax-Ftrial << std::endl; + outStream << " Dot product of gradient and step: " << Qk << std::endl; + outStream << " Sufficient decrease bound: " << -Qk*gamma_ << std::endl; + outStream << " Number of function evaluations: " << ls_nfval << std::endl; + } + while (Ftrial > Fmax + gamma_*Qk && ls_nfval < maxit_) { + alphaTmp = (-half*Qk/(strial-state_->svalue-alpha*gs))*alpha; + alpha = (sigma1_*alpha <= alphaTmp && alphaTmp <= sigma2_*alpha) ? alphaTmp : rhodec_*alpha; + state_->iterateVec->set(x); + state_->iterateVec->axpy(alpha,*state_->stepVec); + sobj.update(*state_->iterateVec,UpdateType::Trial); + strial = sobj.value(*state_->iterateVec,tol); + nobj.update(*state_->iterateVec,UpdateType::Trial); + ntrial = nobj.value(*state_->iterateVec,tol); + Ftrial = strial + ntrial; + ls_nfval++; + Qk = alpha * gs + ntrial - state_->nvalue; + if (verbosity_ > 1) { + outStream << " In TypeP::SpectralGradientAlgorithm: Line Search" << std::endl; + outStream << " Step size: " << alpha << std::endl; + outStream << " Trial objective value: " << Ftrial << std::endl; + outStream << " Max stored objective value: " << Fmax << std::endl; + outStream << " Computed reduction: " << Fmax-Ftrial << std::endl; + outStream << " Dot product of gradient and step: " << Qk << std::endl; + outStream << " Sufficient decrease bound: " << -Qk*gamma_ << std::endl; + outStream << " Number of function evaluations: " << ls_nfval << std::endl; + } + } + state_->nsval += ls_nfval; + state_->nnval += ls_nfval; + if (static_cast(Fqueue.size()) == maxSize_) Fqueue.pop_front(); + Fqueue.push_back(Ftrial); + + // Update state + state_->iter++; + state_->value = Ftrial; + state_->svalue = strial; + state_->nvalue = ntrial; + state_->searchSize = alpha; + x.set(*state_->iterateVec); + sobj.update(x,UpdateType::Accept,state_->iter); + nobj.update(x,UpdateType::Accept,state_->iter); + state_->stepVec->scale(alpha); + + // Store the best iterate + if (state_->value <= Fmin) { + Fmin = state_->value; + xmin->set(x); + } + + // Compute spectral step length + y->set(*state_->gradientVec); + y->scale(-one); + sobj.gradient(*state_->gradientVec,x,tol); state_->ngrad++; + dg->set(state_->gradientVec->dual()); + y->plus(*state_->gradientVec); + ys = y->apply(*state_->stepVec); + ss = state_->stepVec->dot(*state_->stepVec); + state_->snorm = std::sqrt(ss); + lambda_ = (ys<=eps*state_->snorm ? lambdaMax_ : std::max(lambdaMin_,std::min(ss/ys,lambdaMax_))); + + // Compute projected gradient norm + pgstep(*px,*s,nobj,x,*dg,t0_,tol); + state_->gnorm = s->norm() / t0_; + + // Update Output + if (verbosity_ > 0) writeOutput(outStream,writeHeader_); + } + x.set(*xmin); + state_->value = Fmin; + if (verbosity_ > 0) TypeP::Algorithm::writeExitStatus(outStream); +} + +template +void SpectralGradientAlgorithm::writeHeader( std::ostream& os ) const { + std::stringstream hist; + if (verbosity_ > 1) { + hist << std::string(109,'-') << std::endl; + hist << "Spectral proximal gradient algorithm"; + hist << " status output definitions" << std::endl << std::endl; + hist << " iter - Number of iterates (steps taken)" << std::endl; + hist << " value - Objective function value" << std::endl; + hist << " gnorm - Norm of the proximal gradient" << std::endl; + hist << " snorm - Norm of the step (update to optimization vector)" << std::endl; + hist << " alpha - Line search step length" << std::endl; + hist << " lambda - Spectral step length" << std::endl; + hist << " #sval - Cumulative number of times the smooth objective function was evaluated" << std::endl; + hist << " #nval - Cumulative number of times the nonsmooth objective function was evaluated" << std::endl; + hist << " #grad - Cumulative number of times the gradient was computed" << std::endl; + hist << " #prox - Cumulative number of times the proximal operator was computed" << std::endl; + hist << std::string(109,'-') << std::endl; + } + + hist << " "; + hist << std::setw(6) << std::left << "iter"; + hist << std::setw(15) << std::left << "value"; + hist << std::setw(15) << std::left << "gnorm"; + hist << std::setw(15) << std::left << "snorm"; + hist << std::setw(15) << std::left << "alpha"; + hist << std::setw(15) << std::left << "lambda"; + hist << std::setw(10) << std::left << "#sval"; + hist << std::setw(10) << std::left << "#nval"; + hist << std::setw(10) << std::left << "#grad"; + hist << std::setw(10) << std::left << "#nprox"; + hist << std::endl; + os << hist.str(); +} + +template +void SpectralGradientAlgorithm::writeName( std::ostream& os ) const { + std::stringstream hist; + hist << std::endl << "Spectral Proximal Gradient Algorithm (Type P)" << std::endl; + os << hist.str(); +} + +template +void SpectralGradientAlgorithm::writeOutput( std::ostream& os, bool write_header ) const { + std::stringstream hist; + hist << std::scientific << std::setprecision(6); + if ( state_->iter == 0 ) writeName(os); + if ( write_header ) writeHeader(os); + if ( state_->iter == 0 ) { + hist << " "; + hist << std::setw(6) << std::left << state_->iter; + hist << std::setw(15) << std::left << state_->value; + hist << std::setw(15) << std::left << state_->gnorm; + hist << std::setw(15) << std::left << "---"; + hist << std::setw(15) << std::left << "---"; + hist << std::setw(15) << std::left << lambda_; + hist << std::setw(10) << std::left << state_->nsval; + hist << std::setw(10) << std::left << state_->nnval; + hist << std::setw(10) << std::left << state_->ngrad; + hist << std::setw(10) << std::left << state_->nprox; + hist << std::endl; + } + else { + hist << " "; + hist << std::setw(6) << std::left << state_->iter; + hist << std::setw(15) << std::left << state_->value; + hist << std::setw(15) << std::left << state_->gnorm; + hist << std::setw(15) << std::left << state_->snorm; + hist << std::setw(15) << std::left << state_->searchSize; + hist << std::setw(15) << std::left << lambda_; + hist << std::setw(10) << std::left << state_->nsval; + hist << std::setw(10) << std::left << state_->nnval; + hist << std::setw(10) << std::left << state_->ngrad; + hist << std::setw(10) << std::left << state_->nprox; + hist << std::endl; + } + os << hist.str(); +} + +} // namespace TypeP +} // namespace ROL + +#endif diff --git a/packages/rol/test/algorithm/TypeP/CMakeLists.txt b/packages/rol/test/algorithm/TypeP/CMakeLists.txt index 7f5af16afb08..58ce16a620a9 100644 --- a/packages/rol/test/algorithm/TypeP/CMakeLists.txt +++ b/packages/rol/test/algorithm/TypeP/CMakeLists.txt @@ -8,6 +8,15 @@ TRIBITS_ADD_EXECUTABLE_AND_TEST( ADD_DIR_TO_NAME ) +TRIBITS_ADD_EXECUTABLE_AND_TEST( + SpectralGradient + SOURCES test_02.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + TRIBITS_COPY_FILES_TO_BINARY_DIR( TypePTestDataCopy diff --git a/packages/rol/test/algorithm/TypeP/test_02.cpp b/packages/rol/test/algorithm/TypeP/test_02.cpp new file mode 100644 index 000000000000..30df2064ba79 --- /dev/null +++ b/packages/rol/test/algorithm/TypeP/test_02.cpp @@ -0,0 +1,185 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +/*! \file test_02.cpp + \brief Validate proximal gradient algorithm. +*/ + +#include "ROL_TypeP_SpectralGradientAlgorithm.hpp" +#include "ROL_StdObjective.hpp" +#include "ROL_l1Objective.hpp" +#include "ROL_Stream.hpp" +#include "Teuchos_GlobalMPISession.hpp" + +template +class QuadraticTypeP_Test01 : public ROL::StdObjective { +private: + int dim_; + std::vector a_, b_; + +public: + QuadraticTypeP_Test01(int dim) : dim_(dim) { + a_.resize(dim); + b_.resize(dim); + for (int i = 0; i < dim; ++i) { + a_[i] = static_cast(5)*static_cast(rand())/static_cast(RAND_MAX); + b_[i] = static_cast(20)*static_cast(rand())/static_cast(RAND_MAX) - static_cast(10); + } + } + + Real value(const std::vector &x, Real &tol) { + Real val(0); + for (int i = 0; i < dim_; ++i) + val += static_cast(0.5)*a_[i]*x[i]*x[i] + b_[i]*x[i]; + return val; + } + + void gradient(std::vector &g, const std::vector &x, Real &tol) { + for (int i = 0; i < dim_; ++i) + g[i] = a_[i]*x[i] + b_[i]; + } + + void hessVec(std::vector &hv, const std::vector &v, const std::vector &x, Real &tol) { + for (int i = 0; i < dim_; ++i) + hv[i] = a_[i]*v[i]; + } + + void getSolution(std::vector &x, const std::vector &wts, const std::vector &y) const { + for (int i = 0; i < dim_; ++i) + x[i] = (std::min(wts[i], std::max(-wts[i], a_[i]*y[i] + b_[i])) - b_[i]) / a_[i]; + } +}; + +typedef double RealT; + +int main(int argc, char *argv[]) { + + Teuchos::GlobalMPISession mpiSession(&argc, &argv); + + // This little trick lets us print to std::cout only if a + // (dummy) command-line argument is provided. + int iprint = argc - 1; + ROL::Ptr outStream; + ROL::nullstream bhs; // outputs nothing + if (iprint > 0) + outStream = ROL::makePtrFromRef(std::cout); + else + outStream = ROL::makePtrFromRef(bhs); + + int errorFlag = 0; + + try { + RealT tol = 1e2*std::sqrt(ROL::ROL_EPSILON()); + + ROL::ParameterList list; + list.sublist("General").set("Output Level",iprint); + list.sublist("Step").set("Type","Line Search"); + list.sublist("Status Test").set("Gradient Tolerance",1e-7); + list.sublist("Status Test").set("Constraint Tolerance",1e-8); + list.sublist("Status Test").set("Step Tolerance",1e-12); + list.sublist("Status Test").set("Iteration Limit", 10000); + + int dim = 5; + ROL::Ptr> sol, wts, y; + ROL::Ptr> sobj; + ROL::Ptr> nobj; + ROL::Ptr> algo; + std::vector data; + RealT err(0); + + *outStream << std::endl << "Random Diagonal LASSO Test Problem" << std::endl << std::endl; + ROL::Ptr> wtsP = ROL::makePtr>(dim); + ROL::Ptr> yP = ROL::makePtr>(dim); + wts = ROL::makePtr>(wtsP); + y = ROL::makePtr>(yP); + sol = ROL::makePtr>(dim); + wts->randomize(static_cast(0),static_cast(1)); + y->randomize(static_cast(-5),static_cast(5)); + sol->zero(); + + nobj = ROL::makePtr>(wts,y); + sobj = ROL::makePtr>(dim); + + // Check derivatives of smooth function + ROL::Ptr> xd = sol->clone(); + xd->randomize(-1.0,1.0); + ROL::Ptr> yd = sol->clone(); + yd->randomize(-1.0,1.0); + ROL::Ptr> zd = sol->clone(); + zd->randomize(-1.0,1.0); + sobj->checkGradient(*xd,*yd,true,*outStream); + sobj->checkHessVec(*xd,*yd,true,*outStream); + sobj->checkHessSym(*xd,*yd,*zd,true,*outStream); + + algo = ROL::makePtr>(list); + algo->run(*sol,*sobj,*nobj,*outStream); + + std::vector xstar(dim); + sobj->getSolution(xstar, *wtsP, *yP); + data = *ROL::staticPtrCast>(sol)->getVector(); + *outStream << " Result: "; + for (int i = 0; i < dim; ++i) { + *outStream << " x" << i+1 << " = " << data[i]; + err = std::max(err,std::abs(data[i]-xstar[i])); + } + *outStream << std::endl; + *outStream << " Truth: "; + for (int i = 0; i < dim; ++i) { + *outStream << " x" << i+1 << " = " << xstar[i]; + } + *outStream << std::endl; + *outStream << " Max-Error = " << err << std::endl; + errorFlag += (err > tol ? 1 : 0); + } + catch (std::logic_error& err) { + *outStream << err.what() << "\n"; + errorFlag = -1000; + }; // end try + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return 0; +} From 0f07b7fd5f8f5b9a958fa96fd4809339bb94b75b Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Wed, 21 Dec 2022 11:07:25 -0700 Subject: [PATCH 09/65] Changed output for TypeP SPG. --- .../TypeP/ROL_TypeP_SpectralGradientAlgorithm_Def.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm_Def.hpp index b6ee3d73c73e..cb3b24ff52b4 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm_Def.hpp @@ -218,7 +218,7 @@ void SpectralGradientAlgorithm::writeHeader( std::ostream& os ) const { std::stringstream hist; if (verbosity_ > 1) { hist << std::string(109,'-') << std::endl; - hist << "Spectral proximal gradient algorithm"; + hist << "Spectral proximal gradient with nonmonotone line search"; hist << " status output definitions" << std::endl << std::endl; hist << " iter - Number of iterates (steps taken)" << std::endl; hist << " value - Objective function value" << std::endl; @@ -251,7 +251,7 @@ void SpectralGradientAlgorithm::writeHeader( std::ostream& os ) const { template void SpectralGradientAlgorithm::writeName( std::ostream& os ) const { std::stringstream hist; - hist << std::endl << "Spectral Proximal Gradient Algorithm (Type P)" << std::endl; + hist << std::endl << "Spectral Proximal Gradient with Nonmonotone Line Search (Type P)" << std::endl; os << hist.str(); } From 9507cb47d3915af359052e6c06b4fc932c1ab019 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Wed, 21 Dec 2022 11:15:37 -0700 Subject: [PATCH 10/65] More clean up of TypeP SPG. --- ...ROL_TypeP_SpectralGradientAlgorithm_Def.hpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm_Def.hpp index cb3b24ff52b4..3ffe0f3483cb 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm_Def.hpp @@ -107,7 +107,7 @@ void SpectralGradientAlgorithm::run( Vector &x, // Initialize trust-region data Ptr> s = x.clone(), px = x.clone(), dg = x.clone(), y = g.clone(), xmin = x.clone(); initialize(x,g,sobj,nobj,*s,*dg,outStream); - Real strial(0), ntrial(0), Ftrial(0), Fmin(0), Fmax(0), Qk(0), alpha(1), alphaTmp(1); + Real strial(0), ntrial(0), Ftrial(0), Fmin(0), Fmax(0), Qk(0), alpha(1), rhoTmp(1); Real gs(0), ys(0), ss(0), tol(std::sqrt(ROL_EPSILON())); int ls_nfval = 0; std::deque Fqueue; Fqueue.push_back(state_->value); @@ -146,10 +146,14 @@ void SpectralGradientAlgorithm::run( Vector &x, outStream << " Number of function evaluations: " << ls_nfval << std::endl; } while (Ftrial > Fmax + gamma_*Qk && ls_nfval < maxit_) { - alphaTmp = (-half*Qk/(strial-state_->svalue-alpha*gs))*alpha; - alpha = (sigma1_*alpha <= alphaTmp && alphaTmp <= sigma2_*alpha) ? alphaTmp : rhodec_*alpha; + // Compute reduction factor by minimizing 1D quadratic model + rhoTmp = std::min(one,-half*Qk/(strial-state_->svalue-alpha*gs)); + // Safeguard step size selection with back tracking + alpha = ((sigma1_ <= rhoTmp && rhoTmp <= sigma2_) ? rhoTmp : rhodec_)*alpha; + // Update iterate vector state_->iterateVec->set(x); state_->iterateVec->axpy(alpha,*state_->stepVec); + // Recompute objective function values sobj.update(*state_->iterateVec,UpdateType::Trial); strial = sobj.value(*state_->iterateVec,tol); nobj.update(*state_->iterateVec,UpdateType::Trial); @@ -175,14 +179,14 @@ void SpectralGradientAlgorithm::run( Vector &x, // Update state state_->iter++; - state_->value = Ftrial; - state_->svalue = strial; - state_->nvalue = ntrial; + state_->value = Ftrial; + state_->svalue = strial; + state_->nvalue = ntrial; state_->searchSize = alpha; + state_->stepVec->scale(alpha); x.set(*state_->iterateVec); sobj.update(x,UpdateType::Accept,state_->iter); nobj.update(x,UpdateType::Accept,state_->iter); - state_->stepVec->scale(alpha); // Store the best iterate if (state_->value <= Fmin) { From 80d2de826a7c72a2f7bdf2c185622e111a73d57d Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Wed, 21 Dec 2022 11:36:22 -0700 Subject: [PATCH 11/65] Reduced number of prox evaluations by using computed pg step for gnorm. --- .../TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp | 15 ++++++++++----- .../ROL_TypeP_SpectralGradientAlgorithm_Def.hpp | 12 +++++------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp index 046414d693e8..dd4b819e1f00 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp @@ -135,7 +135,7 @@ void ProxGradientAlgorithm::run( Vector &x, Objective &sobj, Objective &nobj, std::ostream &outStream ) { - const Real one(1); + const Real one(1), alphaMin(1e-12*t0_), alphaMax(1e12*t0_); Real tol(std::sqrt(ROL_EPSILON())); // Initialize trust-region data Ptr> px = x.clone(), pxP = x.clone(), dg = x.clone(); @@ -282,9 +282,14 @@ void ProxGradientAlgorithm::run( Vector &x, state_->ngrad++; dg->set(state_->gradientVec->dual()); - // Compute projected gradient norm - pgstep(*pxP, *px, nobj, x, *dg, t0_, tol); - state_->gnorm = px->norm() / t0_; + // Compute projected gradient norm, ensuring that t is in [alphaMin*t0,alphaMax*t0] + if (state_->searchSize >= alphaMin && state_->searchSize <= alphaMax) { + state_->gnorm = state_->snorm / state_->searchSize; + } + else { + pgstep(*pxP, *px, nobj, x, *dg, t0_, tol); + state_->gnorm = px->norm() / t0_; + } // Update Output if (verbosity_ > 0) writeOutput(outStream,writeHeader_); @@ -301,7 +306,7 @@ void ProxGradientAlgorithm::writeHeader( std::ostream& os ) const { hist << " status output definitions" << std::endl << std::endl; hist << " iter - Number of iterates (steps taken)" << std::endl; hist << " value - Objective function value" << std::endl; - hist << " gnorm - Norm of the proximal gradient" << std::endl; + hist << " gnorm - Norm of the proximal gradient with parameter alpha" << std::endl; hist << " snorm - Norm of the step (update to optimization vector)" << std::endl; hist << " alpha - Line search step length" << std::endl; hist << " #sval - Cumulative number of times the smooth objective function was evaluated" << std::endl; diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm_Def.hpp index 3ffe0f3483cb..1afd6c1906fc 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm_Def.hpp @@ -183,6 +183,9 @@ void SpectralGradientAlgorithm::run( Vector &x, state_->svalue = strial; state_->nvalue = ntrial; state_->searchSize = alpha; + state_->gnorm = state_->stepVec->norm(); + state_->snorm = alpha * state_->gnorm; + state_->gnorm /= lambda_; state_->stepVec->scale(alpha); x.set(*state_->iterateVec); sobj.update(x,UpdateType::Accept,state_->iter); @@ -201,14 +204,9 @@ void SpectralGradientAlgorithm::run( Vector &x, dg->set(state_->gradientVec->dual()); y->plus(*state_->gradientVec); ys = y->apply(*state_->stepVec); - ss = state_->stepVec->dot(*state_->stepVec); - state_->snorm = std::sqrt(ss); + ss = state_->snorm * state_->snorm; lambda_ = (ys<=eps*state_->snorm ? lambdaMax_ : std::max(lambdaMin_,std::min(ss/ys,lambdaMax_))); - // Compute projected gradient norm - pgstep(*px,*s,nobj,x,*dg,t0_,tol); - state_->gnorm = s->norm() / t0_; - // Update Output if (verbosity_ > 0) writeOutput(outStream,writeHeader_); } @@ -226,7 +224,7 @@ void SpectralGradientAlgorithm::writeHeader( std::ostream& os ) const { hist << " status output definitions" << std::endl << std::endl; hist << " iter - Number of iterates (steps taken)" << std::endl; hist << " value - Objective function value" << std::endl; - hist << " gnorm - Norm of the proximal gradient" << std::endl; + hist << " gnorm - Norm of the proximal gradient with parameter lambda" << std::endl; hist << " snorm - Norm of the step (update to optimization vector)" << std::endl; hist << " alpha - Line search step length" << std::endl; hist << " lambda - Spectral step length" << std::endl; From ea9e4e5b4f0b98f527d3cec56025c43d7ebecb00 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Wed, 21 Dec 2022 11:41:44 -0700 Subject: [PATCH 12/65] Added option to PG and SPG to avoid prox of initial guess. --- .../algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm.hpp | 2 +- .../TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp | 9 ++++++--- .../TypeP/ROL_TypeP_SpectralGradientAlgorithm.hpp | 1 + .../TypeP/ROL_TypeP_SpectralGradientAlgorithm_Def.hpp | 8 ++++++-- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm.hpp index 57be7af87c9c..7af191cfa48c 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm.hpp @@ -58,7 +58,7 @@ class ProxGradientAlgorithm : public TypeP::Algorithm { private: int maxit_; Real alpha0_, alpha0bnd_, rhodec_, rhoinc_, c1_, maxAlpha_, t0_; - bool useralpha_, usePrevAlpha_, useAdapt_, normAlpha_; + bool useralpha_, usePrevAlpha_, useAdapt_, normAlpha_, initProx_; int verbosity_; bool writeHeader_; diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp index dd4b819e1f00..00995e2d0c6a 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp @@ -64,6 +64,7 @@ ProxGradientAlgorithm::ProxGradientAlgorithm(ParameterList &list) { c1_ = lslist.get("Sufficient Decrease Tolerance", 1e-4); maxAlpha_ = lslist.get("Maximum Step Size", alpha0_); useAdapt_ = lslist.get("Use Adaptive Step Size Selection", true); + initProx_ = lslist.get("Apply Prox to Initial Guess", false); rhodec_ = lslist.sublist("Line-Search Method").get("Backtracking Rate", 0.5); rhoinc_ = lslist.sublist("Line-Search Method").get("Increase Rate" , 2.0); t0_ = list.sublist("Status Test").get("Gradient Scale" , 1.0); @@ -84,9 +85,11 @@ void ProxGradientAlgorithm::initialize(Vector &x, TypeP::Algorithm::initialize(x,g); // Update approximate gradient and approximate objective function. Real ftol = std::sqrt(ROL_EPSILON()); - nobj.prox(*state_->iterateVec,x,state_->searchSize,ftol); - state_->nprox++; - x.set(*state_->iterateVec); //revisit with option to do initial prox or not + if (initProx_) { + nobj.prox(*state_->iterateVec,x,state_->searchSize,ftol); + state_->nprox++; + x.set(*state_->iterateVec); //revisit with option to do initial prox or not + } // Evaluate objective function sobj.update(x,UpdateType::Initial,state_->iter); state_->svalue = sobj.value(x,ftol); diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm.hpp index b5f93e7778c7..550cfdae6fd8 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm.hpp @@ -58,6 +58,7 @@ class SpectralGradientAlgorithm : public TypeP::Algorithm { private: int maxit_, maxSize_; Real lambda_, lambdaMin_, lambdaMax_, sigma1_, sigma2_, rhodec_, gamma_, t0_; + bool initProx_; int verbosity_; bool writeHeader_; diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm_Def.hpp index 1afd6c1906fc..89382ec92bf0 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm_Def.hpp @@ -64,6 +64,7 @@ SpectralGradientAlgorithm::SpectralGradientAlgorithm(ParameterList &list) rhodec_ = lslist.get("Backtracking Rate", 1e-1); gamma_ = lslist.get("Sufficient Decrease Tolerance", 1e-4); maxSize_ = lslist.get("Maximum Storage Size", 10); + initProx_ = lslist.get("Apply Prox to Initial Guess", false); t0_ = list.sublist("Status Test").get("Gradient Scale" , 1.0); verbosity_ = list.sublist("General").get("Output Level", 0); writeHeader_ = verbosity_ > 2; @@ -82,12 +83,15 @@ void SpectralGradientAlgorithm::initialize(Vector &x, // Initialize data TypeP::Algorithm::initialize(x,g); // Update approximate gradient and approximate objective function. - nobj.prox(*state_->iterateVec,x,t0_,ftol); state_->nprox++; - x.set(*state_->iterateVec); + if (initProx_) { + nobj.prox(*state_->iterateVec,x,t0_,ftol); state_->nprox++; + x.set(*state_->iterateVec); + } sobj.update(x,UpdateType::Initial,state_->iter); state_->svalue = sobj.value(x,ftol); state_->nsval++; nobj.update(x,UpdateType::Initial,state_->iter); state_->nvalue = nobj.value(x,ftol); state_->nnval++; + state_->value = state_->svalue + state_->nvalue; sobj.gradient(*state_->gradientVec,x,ftol); state_->ngrad++; dg.set(state_->gradientVec->dual()); pgstep(px, *state_->stepVec, nobj, x, dg, t0_, ftol); From 17ebfb05348f7f3152525d92ff872d85e59c8726 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Wed, 21 Dec 2022 11:43:19 -0700 Subject: [PATCH 13/65] Removed unneeded comment. --- .../src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp index 00995e2d0c6a..74592012ea28 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp @@ -88,7 +88,7 @@ void ProxGradientAlgorithm::initialize(Vector &x, if (initProx_) { nobj.prox(*state_->iterateVec,x,state_->searchSize,ftol); state_->nprox++; - x.set(*state_->iterateVec); //revisit with option to do initial prox or not + x.set(*state_->iterateVec); } // Evaluate objective function sobj.update(x,UpdateType::Initial,state_->iter); From d0e3d1cd2cd6a05f71d66b60c20bcd3db525c883 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Wed, 21 Dec 2022 12:02:15 -0700 Subject: [PATCH 14/65] Changed estimate for initial alpha in PG. Now, we estimate the Lipschitz constant using the curvature estimate 2| f(x+s) - f(x) - f'(x)s | / ||s||^2 --- .../ROL_TypeP_ProxGradientAlgorithm_Def.hpp | 27 +++++++++---------- packages/rol/test/algorithm/TypeP/test_01.cpp | 1 - 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp index 74592012ea28..37b9fb2fadb0 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp @@ -104,26 +104,23 @@ void ProxGradientAlgorithm::initialize(Vector &x, dg.set(state_->gradientVec->dual()); // Evaluate proximal gradient pgstep(px, *state_->stepVec, nobj, x, dg, t0_, ftol); - // Compute initial step size - Real fnew = state_->svalue; + state_->snorm = state_->stepVec->norm(); + state_->gnorm = state_->snorm / t0_; + // Compute initial step size as 2/L + // where L = 2|f(x+s) - f(x) - f'(x)s|/||s||^2 + // is a lower estimate of the Lipschitz constant of f if (!useralpha_) { + const Real two(2); // Evaluate objective at Prox(x - t0 dg) sobj.update(px,UpdateType::Trial); - fnew = sobj.value(px,ftol); + Real snew = sobj.value(px,ftol); sobj.update(x,UpdateType::Revert); state_->nsval++; - } - state_->gnorm = state_->stepVec->norm() / t0_; - state_->snorm = ROL_INF(); - if (!useralpha_) { - const Real half(0.5); - // Minimize quadratic interpolate to compute new alpha - //Real gs = state_->stepVec->dot(state_->gradientVec->dual()); - Real gs = state_->stepVec->apply(*state_->gradientVec); - Real denom = (fnew - state_->svalue - gs); - bool flag = maxAlpha_ == alpha0_; - alpha0_ = ((denom > ROL_EPSILON()) ? -half*gs/denom : alpha0bnd_); - alpha0_ = ((alpha0_ > alpha0bnd_) ? alpha0_ : one); + bool flag = maxAlpha_ == alpha0_; + Real gs = state_->gradientVec->apply(*state_->stepVec); + Real L = two * std::abs(snew - state_->svalue - gs) / (state_->snorm * state_->snorm); + alpha0_ = two / L; + alpha0_ = ((alpha0_ > alpha0bnd_) ? alpha0_ : one); if (flag) maxAlpha_ = alpha0_; } // Normalize initial CP step length diff --git a/packages/rol/test/algorithm/TypeP/test_01.cpp b/packages/rol/test/algorithm/TypeP/test_01.cpp index 433bab64d368..e94ee65ca0ea 100644 --- a/packages/rol/test/algorithm/TypeP/test_01.cpp +++ b/packages/rol/test/algorithm/TypeP/test_01.cpp @@ -116,7 +116,6 @@ int main(int argc, char *argv[]) { list.sublist("Step").set("Type","Line Search"); list.sublist("Step").sublist("Line Search").set("Initial Step Size",1e0); list.sublist("Step").sublist("Line Search").set("Maximum Step Size",1e8); - list.sublist("Step").sublist("Line Search").set("User Defined Initial Step Size",true); list.sublist("Step").sublist("Line Search").set("Use Adaptive Step Size Selection",true); list.sublist("Status Test").set("Gradient Tolerance",1e-7); list.sublist("Status Test").set("Constraint Tolerance",1e-8); From fe78acd9d4c7685921f7810626ddc31e5740812b Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Wed, 21 Dec 2022 12:05:54 -0700 Subject: [PATCH 15/65] Cleaned up initial alpha computation in PG. --- .../TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp index 37b9fb2fadb0..48a7b8ae89a3 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp @@ -106,20 +106,17 @@ void ProxGradientAlgorithm::initialize(Vector &x, pgstep(px, *state_->stepVec, nobj, x, dg, t0_, ftol); state_->snorm = state_->stepVec->norm(); state_->gnorm = state_->snorm / t0_; - // Compute initial step size as 2/L - // where L = 2|f(x+s) - f(x) - f'(x)s|/||s||^2 + // Compute initial step size as 2/L, where L = 2|f(x+s)-f(x)-f'(x)s|/||s||^2 // is a lower estimate of the Lipschitz constant of f if (!useralpha_) { - const Real two(2); + bool flag = maxAlpha_ == alpha0_; // Evaluate objective at Prox(x - t0 dg) sobj.update(px,UpdateType::Trial); Real snew = sobj.value(px,ftol); sobj.update(x,UpdateType::Revert); state_->nsval++; - bool flag = maxAlpha_ == alpha0_; Real gs = state_->gradientVec->apply(*state_->stepVec); - Real L = two * std::abs(snew - state_->svalue - gs) / (state_->snorm * state_->snorm); - alpha0_ = two / L; + alpha0_ = (state_->snorm * state_->snorm) / std::abs(snew - state_->svalue - gs); alpha0_ = ((alpha0_ > alpha0bnd_) ? alpha0_ : one); if (flag) maxAlpha_ = alpha0_; } From 72e1065fac32ec4b76987fa8be71320bd0721b26 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Wed, 21 Dec 2022 12:06:31 -0700 Subject: [PATCH 16/65] Whitespace clean up. --- .../algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp index 48a7b8ae89a3..6773d28f5cef 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp @@ -115,9 +115,9 @@ void ProxGradientAlgorithm::initialize(Vector &x, Real snew = sobj.value(px,ftol); sobj.update(x,UpdateType::Revert); state_->nsval++; - Real gs = state_->gradientVec->apply(*state_->stepVec); - alpha0_ = (state_->snorm * state_->snorm) / std::abs(snew - state_->svalue - gs); - alpha0_ = ((alpha0_ > alpha0bnd_) ? alpha0_ : one); + Real gs = state_->gradientVec->apply(*state_->stepVec); + alpha0_ = (state_->snorm * state_->snorm) / std::abs(snew - state_->svalue - gs); + alpha0_ = ((alpha0_ > alpha0bnd_) ? alpha0_ : one); if (flag) maxAlpha_ = alpha0_; } // Normalize initial CP step length From 30798b50544d69cf66fdd05cbb1882854c93e3ad Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Wed, 21 Dec 2022 12:17:04 -0700 Subject: [PATCH 17/65] Added TypeP Algorithm Factory. --- .../TypeP/ROL_TypeP_AlgorithmFactory.hpp | 131 ++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 packages/rol/src/algorithm/TypeP/ROL_TypeP_AlgorithmFactory.hpp diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_AlgorithmFactory.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_AlgorithmFactory.hpp new file mode 100644 index 000000000000..43c6e9d41236 --- /dev/null +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_AlgorithmFactory.hpp @@ -0,0 +1,131 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +#ifndef ROL_TYPEP_ALGORITHMFACTORY_H +#define ROL_TYPEP_ALGORITHMFACTORY_H + +#include "ROL_TypeP_ProxGradientAlgorithm.hpp" +#include "ROL_TypeP_SpectralGradientAlgorithm.hpp" +#include "ROL_Types.hpp" + +namespace ROL { +namespace TypeP { + +/** \enum ROL::EAlgorithmP + \brief Enumeration of bound constrained algorithm types. + + \arg ALGORITHM_P_PROXIMALGRADIENT describe + \arg ALGORITHM_P_SPECTRALGRADIENT describe + */ +enum EAlgorithmP{ + ALGORITHM_P_PROXIMALGRADIENT = 0, + ALGORITHM_P_SPECTRALGRADIENT, + ALGORITHM_P_LAST +}; + +inline std::string EAlgorithmPToString(EAlgorithmP alg) { + std::string retString; + switch(alg) { + case ALGORITHM_P_PROXIMALGRADIENT: retString = "Proximal Gradient"; break; + case ALGORITHM_P_SPECTRALGRADIENT: retString = "Spectral Gradient"; break; + case ALGORITHM_P_LAST: retString = "Last Type (Dummy)"; break; + default: retString = "INVALID EAlgorithmP"; + } + return retString; +} + +/** \brief Verifies validity of a AlgorithmP enum. + + \param ls [in] - enum of the AlgorithmP + \return 1 if the argument is a valid AlgorithmP; 0 otherwise. + */ +inline int isValidAlgorithmP(EAlgorithmP alg){ + return( (alg == ALGORITHM_P_PROXIMALGRADIENT) || + (alg == ALGORITHM_P_SPECTRALGRADIENT) || + (alg == ALGORITHM_P_LAST) + ); +} + +inline EAlgorithmP & operator++(EAlgorithmP &type) { + return type = static_cast(type+1); +} + +inline EAlgorithmP operator++(EAlgorithmP &type, int) { + EAlgorithmP oldval = type; + ++type; + return oldval; +} + +inline EAlgorithmP & operator--(EAlgorithmP &type) { + return type = static_cast(type-1); +} + +inline EAlgorithmP operator--(EAlgorithmP &type, int) { + EAlgorithmP oldval = type; + --type; + return oldval; +} + +inline EAlgorithmP StringToEAlgorithmP(std::string s) { + s = removeStringFormat(s); + for ( EAlgorithmP alg = ALGORITHM_P_PROXIMALGRADIENT; alg < ALGORITHM_P_LAST; alg++ ) { + if ( !s.compare(removeStringFormat(EAlgorithmPToString(alg))) ) { + return alg; + } + } + return ALGORITHM_P_SPECTRALGRADIENT; +} + +template +inline Ptr> AlgorithmFactory(ParameterList &parlist) { + EAlgorithmP ealg = StringToEAlgorithmP(parlist.sublist("Step").get("Type","Spectral Gradient")); + switch(ealg) { + case ALGORITHM_P_PROXIMALGRADIENT: return makePtr>(parlist); + case ALGORITHM_P_SPECTRALGRADIENT: return makePtr>(parlist); + default: return nullPtr; + } +} +} // namespace TypeP +} // namespace ROL + +#endif From a3b6295a7b112a03bd7c9e5cc3df3245a99cd2cb Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Wed, 21 Dec 2022 20:25:03 -0700 Subject: [PATCH 18/65] Fixed bug in PG and SPG where the gnorm used was from the previous iteration, not the current iteration. --- .../ROL_TypeP_ProxGradientAlgorithm_Def.hpp | 40 +++++++++---------- ...OL_TypeP_SpectralGradientAlgorithm_Def.hpp | 20 +++++----- 2 files changed, 28 insertions(+), 32 deletions(-) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp index 6773d28f5cef..e7f554fa1f31 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_ProxGradientAlgorithm_Def.hpp @@ -92,25 +92,20 @@ void ProxGradientAlgorithm::initialize(Vector &x, } // Evaluate objective function sobj.update(x,UpdateType::Initial,state_->iter); - state_->svalue = sobj.value(x,ftol); - state_->nsval++; nobj.update(x,UpdateType::Initial,state_->iter); - state_->nvalue = nobj.value(x,ftol); - state_->nnval++; + state_->svalue = sobj.value(x,ftol); state_->nsval++; + state_->nvalue = nobj.value(x,ftol); state_->nnval++; state_->value = state_->svalue + state_->nvalue; // Evaluate gradient of smooth part - sobj.gradient(*state_->gradientVec,x,ftol); - state_->ngrad++; + sobj.gradient(*state_->gradientVec,x,ftol); state_->ngrad++; dg.set(state_->gradientVec->dual()); - // Evaluate proximal gradient - pgstep(px, *state_->stepVec, nobj, x, dg, t0_, ftol); - state_->snorm = state_->stepVec->norm(); - state_->gnorm = state_->snorm / t0_; // Compute initial step size as 2/L, where L = 2|f(x+s)-f(x)-f'(x)s|/||s||^2 // is a lower estimate of the Lipschitz constant of f if (!useralpha_) { bool flag = maxAlpha_ == alpha0_; // Evaluate objective at Prox(x - t0 dg) + pgstep(px, *state_->stepVec, nobj, x, dg, t0_, ftol); + state_->snorm = state_->stepVec->norm(); sobj.update(px,UpdateType::Trial); Real snew = sobj.value(px,ftol); sobj.update(x,UpdateType::Revert); @@ -124,6 +119,10 @@ void ProxGradientAlgorithm::initialize(Vector &x, if (normAlpha_) alpha0_ /= state_->gradientVec->norm(); state_->searchSize = alpha0_; + // Evaluate proximal gradient + pgstep(*state_->iterateVec, *state_->stepVec, nobj, x, dg, state_->searchSize, ftol); + state_->snorm = state_->stepVec->norm(); + state_->gnorm = state_->snorm / state_->searchSize; } template @@ -132,13 +131,14 @@ void ProxGradientAlgorithm::run( Vector &x, Objective &sobj, Objective &nobj, std::ostream &outStream ) { - const Real one(1), alphaMin(1e-12*t0_), alphaMax(1e12*t0_); + const Real one(1); Real tol(std::sqrt(ROL_EPSILON())); // Initialize trust-region data Ptr> px = x.clone(), pxP = x.clone(), dg = x.clone(); initialize(x,g,sobj,nobj,*px,*dg,outStream); Real strial(0), ntrial(0), Ftrial(0), Qk(0); Real strialP(0), ntrialP(0), FtrialP(0), alphaP(0); + Real snorm(state_->snorm), searchSize(state_->searchSize); int ls_nfval = 0; bool incAlpha = false, accept = true; @@ -149,9 +149,7 @@ void ProxGradientAlgorithm::run( Vector &x, while (status_->check(*state_)) { accept = true; // Perform backtracking line search - if (!usePrevAlpha_ && !useAdapt_) state_->searchSize = alpha0_; - // Compute proximal gradient step with initial search size - pgstep(*state_->iterateVec, *state_->stepVec, nobj, x, *dg, state_->searchSize, tol); + state_->searchSize = searchSize; // Compute objective function values sobj.update(*state_->iterateVec,UpdateType::Trial); strial = sobj.value(*state_->iterateVec,tol); @@ -279,14 +277,12 @@ void ProxGradientAlgorithm::run( Vector &x, state_->ngrad++; dg->set(state_->gradientVec->dual()); - // Compute projected gradient norm, ensuring that t is in [alphaMin*t0,alphaMax*t0] - if (state_->searchSize >= alphaMin && state_->searchSize <= alphaMax) { - state_->gnorm = state_->snorm / state_->searchSize; - } - else { - pgstep(*pxP, *px, nobj, x, *dg, t0_, tol); - state_->gnorm = px->norm() / t0_; - } + // Compute proximal gradient step with initial search size + searchSize = state_->searchSize; + if (!usePrevAlpha_ && !useAdapt_) searchSize = alpha0_; + pgstep(*state_->iterateVec, *state_->stepVec, nobj, x, *dg, searchSize, tol); + snorm = state_->stepVec->norm(); + state_->gnorm = snorm / searchSize; // Update Output if (verbosity_ > 0) writeOutput(outStream,writeHeader_); diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm_Def.hpp index 89382ec92bf0..5f7039beaee6 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_SpectralGradientAlgorithm_Def.hpp @@ -94,11 +94,11 @@ void SpectralGradientAlgorithm::initialize(Vector &x, state_->value = state_->svalue + state_->nvalue; sobj.gradient(*state_->gradientVec,x,ftol); state_->ngrad++; dg.set(state_->gradientVec->dual()); - pgstep(px, *state_->stepVec, nobj, x, dg, t0_, ftol); - state_->gnorm = state_->stepVec->norm() / t0_; - state_->snorm = ROL_INF(); if (lambda_ <= zero && state_->gnorm != zero) lambda_ = std::max(lambdaMin_,std::min(t0_,lambdaMax_)); + pgstep(*state_->iterateVec, *state_->stepVec, nobj, x, dg, lambda_, ftol); + state_->snorm = state_->stepVec->norm(); + state_->gnorm = state_->snorm / lambda_; } template @@ -112,7 +112,7 @@ void SpectralGradientAlgorithm::run( Vector &x, Ptr> s = x.clone(), px = x.clone(), dg = x.clone(), y = g.clone(), xmin = x.clone(); initialize(x,g,sobj,nobj,*s,*dg,outStream); Real strial(0), ntrial(0), Ftrial(0), Fmin(0), Fmax(0), Qk(0), alpha(1), rhoTmp(1); - Real gs(0), ys(0), ss(0), tol(std::sqrt(ROL_EPSILON())); + Real gs(0), ys(0), snorm(state_->snorm), ss(0), tol(std::sqrt(ROL_EPSILON())); int ls_nfval = 0; std::deque Fqueue; Fqueue.push_back(state_->value); @@ -124,9 +124,6 @@ void SpectralGradientAlgorithm::run( Vector &x, // Iterate spectral projected gradient while (status_->check(*state_)) { - // Compute spectral proximal gradient step - pgstep(*state_->iterateVec, *state_->stepVec, nobj, x, *dg, lambda_, tol); - // Nonmonotone Linesearch ls_nfval = 0; sobj.update(*state_->iterateVec,UpdateType::Trial); @@ -187,9 +184,7 @@ void SpectralGradientAlgorithm::run( Vector &x, state_->svalue = strial; state_->nvalue = ntrial; state_->searchSize = alpha; - state_->gnorm = state_->stepVec->norm(); - state_->snorm = alpha * state_->gnorm; - state_->gnorm /= lambda_; + state_->snorm = alpha * snorm; state_->stepVec->scale(alpha); x.set(*state_->iterateVec); sobj.update(x,UpdateType::Accept,state_->iter); @@ -211,6 +206,11 @@ void SpectralGradientAlgorithm::run( Vector &x, ss = state_->snorm * state_->snorm; lambda_ = (ys<=eps*state_->snorm ? lambdaMax_ : std::max(lambdaMin_,std::min(ss/ys,lambdaMax_))); + // Compute spectral proximal gradient step + pgstep(*state_->iterateVec, *state_->stepVec, nobj, x, *dg, lambda_, tol); + snorm = state_->stepVec->norm(); + state_->gnorm = snorm / lambda_; + // Update Output if (verbosity_ > 0) writeOutput(outStream,writeHeader_); } From 0a8badf341010249fbff23a6fe66e6d3f83fc5c0 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Thu, 22 Dec 2022 10:41:04 -0700 Subject: [PATCH 19/65] Added iPiano algorithm and test. --- .../TypeP/ROL_TypeP_AlgorithmFactory.hpp | 6 + .../TypeP/ROL_TypeP_iPianoAlgorithm.hpp | 100 ++++++ .../TypeP/ROL_TypeP_iPianoAlgorithm_Def.hpp | 325 ++++++++++++++++++ .../rol/test/algorithm/TypeP/CMakeLists.txt | 9 + packages/rol/test/algorithm/TypeP/test_03.cpp | 185 ++++++++++ 5 files changed, 625 insertions(+) create mode 100644 packages/rol/src/algorithm/TypeP/ROL_TypeP_iPianoAlgorithm.hpp create mode 100644 packages/rol/src/algorithm/TypeP/ROL_TypeP_iPianoAlgorithm_Def.hpp create mode 100644 packages/rol/test/algorithm/TypeP/test_03.cpp diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_AlgorithmFactory.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_AlgorithmFactory.hpp index 43c6e9d41236..5a0c17652e48 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_AlgorithmFactory.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_AlgorithmFactory.hpp @@ -46,6 +46,7 @@ #include "ROL_TypeP_ProxGradientAlgorithm.hpp" #include "ROL_TypeP_SpectralGradientAlgorithm.hpp" +#include "ROL_TypeP_iPianoAlgorithm.hpp" #include "ROL_Types.hpp" namespace ROL { @@ -56,10 +57,12 @@ namespace TypeP { \arg ALGORITHM_P_PROXIMALGRADIENT describe \arg ALGORITHM_P_SPECTRALGRADIENT describe + \arg ALGORITHM_P_IPIANO describe */ enum EAlgorithmP{ ALGORITHM_P_PROXIMALGRADIENT = 0, ALGORITHM_P_SPECTRALGRADIENT, + ALGORITHM_P_IPIANO, ALGORITHM_P_LAST }; @@ -68,6 +71,7 @@ inline std::string EAlgorithmPToString(EAlgorithmP alg) { switch(alg) { case ALGORITHM_P_PROXIMALGRADIENT: retString = "Proximal Gradient"; break; case ALGORITHM_P_SPECTRALGRADIENT: retString = "Spectral Gradient"; break; + case ALGORITHM_P_IPIANO: retString = "iPiano"; break; case ALGORITHM_P_LAST: retString = "Last Type (Dummy)"; break; default: retString = "INVALID EAlgorithmP"; } @@ -82,6 +86,7 @@ inline std::string EAlgorithmPToString(EAlgorithmP alg) { inline int isValidAlgorithmP(EAlgorithmP alg){ return( (alg == ALGORITHM_P_PROXIMALGRADIENT) || (alg == ALGORITHM_P_SPECTRALGRADIENT) || + (alg == ALGORITHM_P_IPIANO) || (alg == ALGORITHM_P_LAST) ); } @@ -122,6 +127,7 @@ inline Ptr> AlgorithmFactory(ParameterList &parlist) { switch(ealg) { case ALGORITHM_P_PROXIMALGRADIENT: return makePtr>(parlist); case ALGORITHM_P_SPECTRALGRADIENT: return makePtr>(parlist); + case ALGORITHM_P_IPIANO: return makePtr>(parlist); default: return nullPtr; } } diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_iPianoAlgorithm.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_iPianoAlgorithm.hpp new file mode 100644 index 000000000000..bb1c6188af76 --- /dev/null +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_iPianoAlgorithm.hpp @@ -0,0 +1,100 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +#ifndef ROL_TYPEP_IPIANOALGORITHM_HPP +#define ROL_TYPEP_IPIANOALGORITHM_HPP + +#include "ROL_TypeP_Algorithm.hpp" + +/** \class ROL::TypeP::iPianoAlgorithm + \brief Provides an interface to run the proximal gradient algorithm. +*/ + +namespace ROL { +namespace TypeP { + +template +class iPianoAlgorithm : public TypeP::Algorithm { +private: + int maxit_; + Real t0_, alpha_, beta_, rhodec_, rhoinc_, c1_, c2_, L_; + bool useConstBeta_, initProx_; + int verbosity_; + bool writeHeader_; + + using TypeP::Algorithm::status_; + using TypeP::Algorithm::state_; + using TypeP::Algorithm::pgstep; + + void initialize(Vector &x, + const Vector &g, + Objective &sobj, + Objective &nobj, + Vector &px, + Vector &dg, + std::ostream &outStream = std::cout); +public: + + iPianoAlgorithm(ParameterList &list); + + using TypeP::Algorithm::run; + void run( Vector &x, + const Vector &g, + Objective &sobj, + Objective &nobj, + std::ostream &outStream = std::cout) override; + + void writeHeader( std::ostream& os ) const override; + + void writeName( std::ostream& os ) const override; + + void writeOutput( std::ostream& os, bool write_header = false ) const override; + +}; // class ROL::TypeP::iPianoAlgorithm + +} // namespace TypeP +} // namespace ROL + +#include "ROL_TypeP_iPianoAlgorithm_Def.hpp" + +#endif diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_iPianoAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_iPianoAlgorithm_Def.hpp new file mode 100644 index 000000000000..a848831fa29e --- /dev/null +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_iPianoAlgorithm_Def.hpp @@ -0,0 +1,325 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +#ifndef ROL_TYPEP_IPIANOALGORITHM_DEF_HPP +#define ROL_TYPEP_IPIANOALGORITHM_DEF_HPP + +namespace ROL { +namespace TypeP { + +template +iPianoAlgorithm::iPianoAlgorithm(ParameterList &list) { + // Set status test + status_->reset(); + status_->add(makePtr>(list)); + + // Parse parameter list + ParameterList &lslist = list.sublist("Step").sublist("iPiano"); + t0_ = list.sublist("Status Test").get("Gradient Scale", 1.0); + maxit_ = lslist.get("Reduction Iteration Limit", 20); + useConstBeta_ = lslist.get("Use Constant Beta", false); + beta_ = lslist.get("Momentum Parameter", 0.25); + rhodec_ = lslist.get("Backtracking Rate", 0.5); + rhoinc_ = lslist.get("Increase Rate", 2.0); + c1_ = lslist.get("Upper Interpolation Factor", 1e-5); + c2_ = lslist.get("Lower Interpolation Factor", 1e-6); + L_ = lslist.get("Initial Lipschitz Constant Estimate", 0.5/t0_); + initProx_ = lslist.get("Apply Prox to Initial Guess", false); + verbosity_ = list.sublist("General").get("Output Level", 0); + writeHeader_ = verbosity_ > 2; +} + +template +void iPianoAlgorithm::initialize(Vector &x, + const Vector &g, + Objective &sobj, + Objective &nobj, + Vector &px, + Vector &dg, + std::ostream &outStream) { + Real ftol = std::sqrt(ROL_EPSILON()); + // Initialize data + TypeP::Algorithm::initialize(x,g); + // Update approximate gradient and approximate objective function. + if (initProx_) { + nobj.prox(*state_->iterateVec,x,t0_,ftol); state_->nprox++; + x.set(*state_->iterateVec); + } + sobj.update(x,UpdateType::Initial,state_->iter); + state_->svalue = sobj.value(x,ftol); state_->nsval++; + nobj.update(x,UpdateType::Initial,state_->iter); + state_->nvalue = nobj.value(x,ftol); state_->nnval++; + state_->value = state_->svalue + state_->nvalue; + sobj.gradient(*state_->gradientVec,x,ftol); state_->ngrad++; + dg.set(state_->gradientVec->dual()); + pgstep(*state_->iterateVec, *state_->stepVec, nobj, x, dg, t0_, ftol); + state_->snorm = state_->stepVec->norm(); + state_->gnorm = state_->snorm / t0_; +} + +template +void iPianoAlgorithm::run( Vector &x, + const Vector &g, + Objective &sobj, + Objective &nobj, + std::ostream &outStream ) { + const Real half(0.5), one(1), two(2); + // Initialize trust-region data + Ptr> sP = x.clone(), xP = x.clone(), dg = x.clone(), xold = x.clone(); + initialize(x,g,sobj,nobj,*sP,*dg,outStream); + Real strial(0), strialP(0), snormP(0), LP(0), alphaP(0), betaP(0), gs(0), b(0); + Real tol(std::sqrt(ROL_EPSILON())); + bool accept(true); + + xold->set(x); + + // Output + if (verbosity_ > 0) writeOutput(outStream, true); + + // Iterate spectral projected gradient + while (status_->check(*state_)) { + // Compute parameters alpha and beta + if (!useConstBeta_) { + b = (c1_ + half * L_) / (c2_ + half * L_); + beta_ = (b - one) / (b - half); + } + alpha_ = two * (1 - beta_) / (two * c2_ + L_); + // Compute inertial step + state_->stepVec->set(x); + state_->stepVec->axpy(-alpha_, *dg); + state_->stepVec->axpy(beta_, x); + state_->stepVec->axpy(-beta_, *xold); + nobj.prox(*state_->iterateVec, *state_->stepVec, alpha_, tol); state_->nprox++; + state_->stepVec->set(*state_->iterateVec); + state_->stepVec->axpy(-one,x); + state_->snorm = state_->stepVec->norm(); + // Compute smooth objective value + sobj.update(*state_->iterateVec,UpdateType::Trial); + strial = sobj.value(*state_->iterateVec,tol); state_->nsval++; + gs = state_->gradientVec->apply(*state_->stepVec); + // Estimate Lipschitz constant of sobj + if (strial <= state_->svalue + gs + half * L_ * state_->snorm * state_->snorm) { + accept = true; + for (int i = 0; i < maxit_; ++i) { + // Store previously computed information + sobj.update(*state_->iterateVec,UpdateType::Accept); + LP = L_; + alphaP = alpha_; + betaP = beta_; + strialP = strial; + snormP = state_->snorm; + xP->set(*state_->iterateVec); + sP->set(*state_->stepVec); + // Update alpha and beta with new Lipschitz constant estimate + L_ /= rhoinc_; + if (!useConstBeta_) { + b = (c1_ + half * L_) / (c2_ + half * L_); + beta_ = (b - one) / (b - half); + } + alpha_ = two * (one - beta_) / (two * c2_ + L_); + // Compute updated inertial step + state_->stepVec->set(x); + state_->stepVec->axpy(-alpha_, *dg); + state_->stepVec->axpy(beta_, x); + state_->stepVec->axpy(-beta_, *xold); + nobj.prox(*state_->iterateVec, *state_->stepVec, alpha_, tol); state_->nprox++; + state_->stepVec->set(*state_->iterateVec); + state_->stepVec->axpy(-one,x); + state_->snorm = state_->stepVec->norm(); + // Compute smooth objective value + sobj.update(*state_->iterateVec,UpdateType::Trial); + strial = sobj.value(*state_->iterateVec,tol); state_->nsval++; + gs = state_->gradientVec->apply(*state_->stepVec); + if (strial > state_->svalue + gs + half * L_ * state_->snorm * state_->snorm) { + accept = false; + L_ = LP; + alpha_ = alphaP; + beta_ = betaP; + strial = strialP; + state_->snorm = snormP; + state_->iterateVec->set(*xP); + state_->stepVec->set(*sP); + break; + } + } + if (accept) { + sobj.update(*state_->iterateVec,UpdateType::Accept); + nobj.update(*state_->iterateVec,UpdateType::Accept); + } + else { + sobj.update(*state_->iterateVec,UpdateType::Revert); + nobj.update(*state_->iterateVec,UpdateType::Revert); + } + } + else { + while (strial > state_->svalue + gs + half * L_ * state_->snorm * state_->snorm) { + // Update alpha and beta with new Lipschitz constant estimate + L_ /= rhodec_; + if (!useConstBeta_) { + b = (c1_ + half * L_) / (c2_ + half * L_); + beta_ = (b - one) / (b - half); + } + alpha_ = two * (one - beta_) / (two * c2_ + L_); + // Compute updated inertial step + state_->stepVec->set(x); + state_->stepVec->axpy(-alpha_, *dg); + state_->stepVec->axpy(beta_, x); + state_->stepVec->axpy(-beta_, *xold); + nobj.prox(*state_->iterateVec, *state_->stepVec, alpha_, tol); state_->nprox++; + state_->stepVec->set(*state_->iterateVec); + state_->stepVec->axpy(-one,x); + state_->snorm = state_->stepVec->norm(); + // Compute smooth objective value + sobj.update(*state_->iterateVec,UpdateType::Trial); + strial = sobj.value(*state_->iterateVec,tol); state_->nsval++; + gs = state_->gradientVec->apply(*state_->stepVec); + } + sobj.update(*state_->iterateVec,UpdateType::Accept); + nobj.update(*state_->iterateVec,UpdateType::Accept); + } + // Update iteration + state_->iter++; + xold->set(x); + x.set(*state_->iterateVec); + state_->svalue = strial; + state_->nvalue = nobj.value(x,tol); state_->nnval++; + state_->value = state_->svalue + state_->nvalue; + sobj.gradient(*state_->gradientVec,x,tol); state_->ngrad++; + dg->set(state_->gradientVec->dual()); + // Compute proximal gradient for status check + pgstep(*xP,*sP,nobj,x,*dg,t0_,tol); + state_->gnorm = sP->norm() / t0_; + + // Update Output + if (verbosity_ > 0) writeOutput(outStream,writeHeader_); + } + if (verbosity_ > 0) TypeP::Algorithm::writeExitStatus(outStream); +} + +template +void iPianoAlgorithm::writeHeader( std::ostream& os ) const { + std::stringstream hist; + if (verbosity_ > 1) { + hist << std::string(109,'-') << std::endl; + hist << "iPiano: Inertial proximal algorithm for nonconvex optimization"; + hist << " status output definitions" << std::endl << std::endl; + hist << " iter - Number of iterates (steps taken)" << std::endl; + hist << " value - Objective function value" << std::endl; + hist << " gnorm - Norm of the proximal gradient with parameter lambda" << std::endl; + hist << " snorm - Norm of the step (update to optimization vector)" << std::endl; + hist << " alpha - Inertial gradient parameter" << std::endl; + hist << " beta - Inertial step parameter" << std::endl; + hist << " L - Lipschitz constant estimate" << std::endl; + hist << " #sval - Cumulative number of times the smooth objective function was evaluated" << std::endl; + hist << " #nval - Cumulative number of times the nonsmooth objective function was evaluated" << std::endl; + hist << " #grad - Cumulative number of times the gradient was computed" << std::endl; + hist << " #prox - Cumulative number of times the proximal operator was computed" << std::endl; + hist << std::string(109,'-') << std::endl; + } + + hist << " "; + hist << std::setw(6) << std::left << "iter"; + hist << std::setw(15) << std::left << "value"; + hist << std::setw(15) << std::left << "gnorm"; + hist << std::setw(15) << std::left << "snorm"; + hist << std::setw(15) << std::left << "alpha"; + hist << std::setw(15) << std::left << "beta"; + hist << std::setw(15) << std::left << "L"; + hist << std::setw(10) << std::left << "#sval"; + hist << std::setw(10) << std::left << "#nval"; + hist << std::setw(10) << std::left << "#grad"; + hist << std::setw(10) << std::left << "#nprox"; + hist << std::endl; + os << hist.str(); +} + +template +void iPianoAlgorithm::writeName( std::ostream& os ) const { + std::stringstream hist; + hist << std::endl << "iPiano: Inertial Proximal Algorithm for Nonconvex Optimization (Type P)" << std::endl; + os << hist.str(); +} + +template +void iPianoAlgorithm::writeOutput( std::ostream& os, bool write_header ) const { + std::stringstream hist; + hist << std::scientific << std::setprecision(6); + if ( state_->iter == 0 ) writeName(os); + if ( write_header ) writeHeader(os); + if ( state_->iter == 0 ) { + hist << " "; + hist << std::setw(6) << std::left << state_->iter; + hist << std::setw(15) << std::left << state_->value; + hist << std::setw(15) << std::left << state_->gnorm; + hist << std::setw(15) << std::left << "---"; + hist << std::setw(15) << std::left << "---"; + hist << std::setw(15) << std::left << "---"; + hist << std::setw(15) << std::left << L_; + hist << std::setw(10) << std::left << state_->nsval; + hist << std::setw(10) << std::left << state_->nnval; + hist << std::setw(10) << std::left << state_->ngrad; + hist << std::setw(10) << std::left << state_->nprox; + hist << std::endl; + } + else { + hist << " "; + hist << std::setw(6) << std::left << state_->iter; + hist << std::setw(15) << std::left << state_->value; + hist << std::setw(15) << std::left << state_->gnorm; + hist << std::setw(15) << std::left << state_->snorm; + hist << std::setw(15) << std::left << alpha_; + hist << std::setw(15) << std::left << beta_; + hist << std::setw(15) << std::left << L_; + hist << std::setw(10) << std::left << state_->nsval; + hist << std::setw(10) << std::left << state_->nnval; + hist << std::setw(10) << std::left << state_->ngrad; + hist << std::setw(10) << std::left << state_->nprox; + hist << std::endl; + } + os << hist.str(); +} + +} // namespace TypeP +} // namespace ROL + +#endif diff --git a/packages/rol/test/algorithm/TypeP/CMakeLists.txt b/packages/rol/test/algorithm/TypeP/CMakeLists.txt index 58ce16a620a9..973289b4b084 100644 --- a/packages/rol/test/algorithm/TypeP/CMakeLists.txt +++ b/packages/rol/test/algorithm/TypeP/CMakeLists.txt @@ -17,6 +17,15 @@ TRIBITS_ADD_EXECUTABLE_AND_TEST( ADD_DIR_TO_NAME ) +TRIBITS_ADD_EXECUTABLE_AND_TEST( + iPiano + SOURCES test_03.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + TRIBITS_COPY_FILES_TO_BINARY_DIR( TypePTestDataCopy diff --git a/packages/rol/test/algorithm/TypeP/test_03.cpp b/packages/rol/test/algorithm/TypeP/test_03.cpp new file mode 100644 index 000000000000..55c1a73811bf --- /dev/null +++ b/packages/rol/test/algorithm/TypeP/test_03.cpp @@ -0,0 +1,185 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +/*! \file test_03.cpp + \brief Validate iPiano algorithm. +*/ + +#include "ROL_TypeP_iPianoAlgorithm.hpp" +#include "ROL_StdObjective.hpp" +#include "ROL_l1Objective.hpp" +#include "ROL_Stream.hpp" +#include "Teuchos_GlobalMPISession.hpp" + +template +class QuadraticTypeP_Test01 : public ROL::StdObjective { +private: + int dim_; + std::vector a_, b_; + +public: + QuadraticTypeP_Test01(int dim) : dim_(dim) { + a_.resize(dim); + b_.resize(dim); + for (int i = 0; i < dim; ++i) { + a_[i] = static_cast(5)*static_cast(rand())/static_cast(RAND_MAX); + b_[i] = static_cast(20)*static_cast(rand())/static_cast(RAND_MAX) - static_cast(10); + } + } + + Real value(const std::vector &x, Real &tol) { + Real val(0); + for (int i = 0; i < dim_; ++i) + val += static_cast(0.5)*a_[i]*x[i]*x[i] + b_[i]*x[i]; + return val; + } + + void gradient(std::vector &g, const std::vector &x, Real &tol) { + for (int i = 0; i < dim_; ++i) + g[i] = a_[i]*x[i] + b_[i]; + } + + void hessVec(std::vector &hv, const std::vector &v, const std::vector &x, Real &tol) { + for (int i = 0; i < dim_; ++i) + hv[i] = a_[i]*v[i]; + } + + void getSolution(std::vector &x, const std::vector &wts, const std::vector &y) const { + for (int i = 0; i < dim_; ++i) + x[i] = (std::min(wts[i], std::max(-wts[i], a_[i]*y[i] + b_[i])) - b_[i]) / a_[i]; + } +}; + +typedef double RealT; + +int main(int argc, char *argv[]) { + + Teuchos::GlobalMPISession mpiSession(&argc, &argv); + + // This little trick lets us print to std::cout only if a + // (dummy) command-line argument is provided. + int iprint = argc - 1; + ROL::Ptr outStream; + ROL::nullstream bhs; // outputs nothing + if (iprint > 0) + outStream = ROL::makePtrFromRef(std::cout); + else + outStream = ROL::makePtrFromRef(bhs); + + int errorFlag = 0; + + try { + RealT tol = 1e2*std::sqrt(ROL::ROL_EPSILON()); + + ROL::ParameterList list; + list.sublist("General").set("Output Level",iprint); + list.sublist("Step").set("Type","iPiano"); + list.sublist("Status Test").set("Gradient Tolerance",1e-7); + list.sublist("Status Test").set("Constraint Tolerance",1e-8); + list.sublist("Status Test").set("Step Tolerance",1e-12); + list.sublist("Status Test").set("Iteration Limit", 10000); + + int dim = 5; + ROL::Ptr> sol, wts, y; + ROL::Ptr> sobj; + ROL::Ptr> nobj; + ROL::Ptr> algo; + std::vector data; + RealT err(0); + + *outStream << std::endl << "Random Diagonal LASSO Test Problem" << std::endl << std::endl; + ROL::Ptr> wtsP = ROL::makePtr>(dim); + ROL::Ptr> yP = ROL::makePtr>(dim); + wts = ROL::makePtr>(wtsP); + y = ROL::makePtr>(yP); + sol = ROL::makePtr>(dim); + wts->randomize(static_cast(0),static_cast(1)); + y->randomize(static_cast(-5),static_cast(5)); + sol->zero(); + + nobj = ROL::makePtr>(wts,y); + sobj = ROL::makePtr>(dim); + + // Check derivatives of smooth function + ROL::Ptr> xd = sol->clone(); + xd->randomize(-1.0,1.0); + ROL::Ptr> yd = sol->clone(); + yd->randomize(-1.0,1.0); + ROL::Ptr> zd = sol->clone(); + zd->randomize(-1.0,1.0); + sobj->checkGradient(*xd,*yd,true,*outStream); + sobj->checkHessVec(*xd,*yd,true,*outStream); + sobj->checkHessSym(*xd,*yd,*zd,true,*outStream); + + algo = ROL::makePtr>(list); + algo->run(*sol,*sobj,*nobj,*outStream); + + std::vector xstar(dim); + sobj->getSolution(xstar, *wtsP, *yP); + data = *ROL::staticPtrCast>(sol)->getVector(); + *outStream << " Result: "; + for (int i = 0; i < dim; ++i) { + *outStream << " x" << i+1 << " = " << data[i]; + err = std::max(err,std::abs(data[i]-xstar[i])); + } + *outStream << std::endl; + *outStream << " Truth: "; + for (int i = 0; i < dim; ++i) { + *outStream << " x" << i+1 << " = " << xstar[i]; + } + *outStream << std::endl; + *outStream << " Max-Error = " << err << std::endl; + errorFlag += (err > tol ? 1 : 0); + } + catch (std::logic_error& err) { + *outStream << err.what() << "\n"; + errorFlag = -1000; + }; // end try + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return 0; +} From fbf1cff7f1f922e1b56d66f01a174e587c2e43d6 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Thu, 22 Dec 2022 10:43:19 -0700 Subject: [PATCH 20/65] Corrected nonsmooth objective update. --- .../rol/src/algorithm/TypeP/ROL_TypeP_iPianoAlgorithm_Def.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_iPianoAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_iPianoAlgorithm_Def.hpp index a848831fa29e..e43dbc4efc99 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_iPianoAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_iPianoAlgorithm_Def.hpp @@ -135,6 +135,7 @@ void iPianoAlgorithm::run( Vector &x, state_->snorm = state_->stepVec->norm(); // Compute smooth objective value sobj.update(*state_->iterateVec,UpdateType::Trial); + nobj.update(*state_->iterateVec,UpdateType::Trial); strial = sobj.value(*state_->iterateVec,tol); state_->nsval++; gs = state_->gradientVec->apply(*state_->stepVec); // Estimate Lipschitz constant of sobj @@ -143,6 +144,7 @@ void iPianoAlgorithm::run( Vector &x, for (int i = 0; i < maxit_; ++i) { // Store previously computed information sobj.update(*state_->iterateVec,UpdateType::Accept); + nobj.update(*state_->iterateVec,UpdateType::Accept); LP = L_; alphaP = alpha_; betaP = beta_; From 5ef08b58b7ff2916ab475f69988ba5344cc0d358 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Thu, 22 Dec 2022 15:06:00 -0700 Subject: [PATCH 21/65] Removed "update" and "checkMultiplier" functions for BoundConstraints_SimOpt. --- .../simopt/ROL_BoundConstraint_SimOpt.hpp | 40 ------------------- 1 file changed, 40 deletions(-) diff --git a/packages/rol/src/function/simopt/ROL_BoundConstraint_SimOpt.hpp b/packages/rol/src/function/simopt/ROL_BoundConstraint_SimOpt.hpp index 9a5f1642dfd0..95f34c0ee25f 100644 --- a/packages/rol/src/function/simopt/ROL_BoundConstraint_SimOpt.hpp +++ b/packages/rol/src/function/simopt/ROL_BoundConstraint_SimOpt.hpp @@ -93,24 +93,6 @@ class BoundConstraint_SimOpt : public BoundConstraint { } } - /** \brief Update bounds. - - The update function allows the user to update the bounds at each new iterations. - @param[in] x is the optimization variable. - @param[in] flag is set to true if control is changed. - @param[in] iter is the outer algorithm iterations count. - */ - void update( const Vector &x, bool flag = true, int iter = -1 ) { - const Vector_SimOpt &xs = dynamic_cast&>( - dynamic_cast&>(x)); - if ( bnd1_->isActivated() ) { - bnd1_->update(*(xs.get_1()),flag,iter); - } - if ( bnd2_->isActivated() ) { - bnd2_->update(*(xs.get_2()),flag,iter); - } - } - /** \brief Project optimization variables onto the bounds. This function implements the projection of \f$x\f$ onto the bounds, i.e., @@ -151,28 +133,6 @@ class BoundConstraint_SimOpt : public BoundConstraint { } } - /** \brief Determine if a vector of Lagrange multipliers is nonnegative components. - - This function returns true if components of \f$l\f$ corresponding to the components of \f$x\f$ - that are active at the upper bound are nonpositive or the components of \f$l\f$ corresponding - to the components of \f$x\f$ that are active at the lower bound are nonnegative. - */ - bool checkMultipliers( const Vector &l, const Vector &x ) { - const Vector_SimOpt &ls = dynamic_cast&>( - dynamic_cast&>(l)); - const Vector_SimOpt &xs = dynamic_cast&>( - dynamic_cast&>(x)); - bool nn1 = true; - if ( bnd1_->isActivated() ) { - nn1 = bnd1_->checkMultipliers(*(ls.get_1()),*(xs.get_1())); - } - bool nn2 = true; - if ( bnd2_->isActivated() ) { - nn2 = bnd2_->checkMultipliers(*(ls.get_2()),*(xs.get_2())); - } - return (nn1 && nn2); - } - /** \brief Set variables to zero if they correspond to the upper \f$\epsilon\f$-active set. This function sets \f$v(\xi)=0\f$ if \f$\xi\in\mathcal{A}^+_\epsilon(x)\f$. Here, From d6c9d3348393745c6372bffff4a4d5e965e03960 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Fri, 23 Dec 2022 16:59:48 -0700 Subject: [PATCH 22/65] Added a basic quasi-Newton TypeP algorithm. At each iteration, the method solves min 1/2 + + f(x_k) + phi(x) using SPG, PG or iPiano. This produces a trial iterate x and step s = x-x_k. The method then performs a backtracking line search to determine a steplength t and the iterate x_k + t s. The quasi-Newton approximation B_k is for the Hessian of the smooth part of the objective function, f. --- .../TypeP/ROL_TypeP_QuasiNewtonAlgorithm.hpp | 120 +++++++ .../ROL_TypeP_QuasiNewtonAlgorithm_Def.hpp | 325 ++++++++++++++++++ .../rol/test/algorithm/TypeP/CMakeLists.txt | 9 + packages/rol/test/algorithm/TypeP/test_05.cpp | 185 ++++++++++ 4 files changed, 639 insertions(+) create mode 100644 packages/rol/src/algorithm/TypeP/ROL_TypeP_QuasiNewtonAlgorithm.hpp create mode 100644 packages/rol/src/algorithm/TypeP/ROL_TypeP_QuasiNewtonAlgorithm_Def.hpp create mode 100644 packages/rol/test/algorithm/TypeP/test_05.cpp diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_QuasiNewtonAlgorithm.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_QuasiNewtonAlgorithm.hpp new file mode 100644 index 000000000000..294b22f0b439 --- /dev/null +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_QuasiNewtonAlgorithm.hpp @@ -0,0 +1,120 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +#ifndef ROL_TYPEP_QUASINEWTONALGORITHM_HPP +#define ROL_TYPEP_QUASINEWTONALGORITHM_HPP + +#include "ROL_TypeP_Algorithm.hpp" +#include "ROL_SecantFactory.hpp" + +/** \class ROL::TypeP::QuasiNewtonAlgorithm + \brief Provides an interface to run the projected secant algorithm. +*/ + +namespace ROL { +namespace TypeP { + +template +class QuasiNewtonAlgorithm : public TypeP::Algorithm { +private: + Ptr> secant_; ///< Secant object (used for quasi-Newton) + ESecant esec_; ///< Secant type + std::string secantName_; ///< Secant name + + int t0_; + bool initProx_; + + int maxit_; ///< Maximum number of line search steps (default: 20) + Real rhodec_; ///< Backtracking rate (default: 0.5) + Real c1_; ///< Sufficient Decrease Parameter (default: 1e-4) + Real sigma1_; ///< Lower safeguard for quadratic line search (default: 0.1) + Real sigma2_; ///< Upper safeguard for quadratic line search (default: 0.9) + Real sp_tol1_; + Real sp_tol2_; + Real sp_tol_min_; + std::string algoName_; + + ParameterList list_; + + bool hasLEC_; + int ls_nfval_, spgIter_; + int verbosity_; + bool writeHeader_; + + using TypeP::Algorithm::pgstep; + using TypeP::Algorithm::status_; + using TypeP::Algorithm::state_; + + void initialize(Vector &x, + const Vector &g, + Objective &sobj, + Objective &nobj, + Vector &dg, + std::ostream &outStream = std::cout); + +public: + + QuasiNewtonAlgorithm(ParameterList &list, const Ptr> &secant = nullPtr); + + using TypeP::Algorithm::run; + + void run( Vector &x, + const Vector &g, + Objective &sobj, + Objective &nobj, + std::ostream &outStream = std::cout) override; + + void writeHeader( std::ostream& os ) const override; + + void writeName( std::ostream& os ) const override; + + void writeOutput( std::ostream &os, bool write_header = false ) const override; + +}; // class ROL::TypeP::QuasiNewtonAlgorithm + +} // namespace TypeP +} // namespace ROL + +#include "ROL_TypeP_QuasiNewtonAlgorithm_Def.hpp" + +#endif diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_QuasiNewtonAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_QuasiNewtonAlgorithm_Def.hpp new file mode 100644 index 000000000000..977a8ee07f08 --- /dev/null +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_QuasiNewtonAlgorithm_Def.hpp @@ -0,0 +1,325 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +#ifndef ROL_TYPEP_QUASINEWTONALGORITHM_DEF_HPP +#define ROL_TYPEP_QUASINEWTONALGORITHM_DEF_HPP + +#include "ROL_TypeP_ProxGradientAlgorithm.hpp" +#include "ROL_TypeP_SpectralGradientAlgorithm.hpp" +#include "ROL_TypeP_iPianoAlgorithm.hpp" +#include "ROL_PQNObjective.hpp" + +namespace ROL { +namespace TypeP { + +template +QuasiNewtonAlgorithm::QuasiNewtonAlgorithm(ParameterList &list, + const Ptr> &secant) + : secant_(secant), esec_(SECANT_USERDEFINED), list_(list), hasLEC_(true) { + // Set status test + status_->reset(); + status_->add(makePtr>(list)); + + // Parse parameter list + ParameterList &lslist = list.sublist("Step").sublist("Line Search"); + t0_ = list.sublist("Status Test").get("Gradient Scale" , 1.0); + initProx_ = lslist.get("Apply Prox to Initial Guess", false); + maxit_ = lslist.get("Function Evaluation Limit", 20); + c1_ = lslist.get("Sufficient Decrease Tolerance", 1e-4); + rhodec_ = lslist.sublist("Line-Search Method").get("Backtracking Rate", 0.5); + sigma1_ = lslist.sublist("PQN").get("Lower Step Size Safeguard", 0.1); + sigma2_ = lslist.sublist("PQN").get("Upper Step Size Safeguard", 0.9); + algoName_ = lslist.sublist("PQN").get("Subproblem Solver","Spectral Gradient"); + int sp_maxit = lslist.sublist("PQN").get("Subproblem Iteration Limit", 1000); + sp_tol1_ = lslist.sublist("PQN").get("Subproblem Absolute Tolerance", 1e-4); + sp_tol2_ = lslist.sublist("PQN").get("Subproblem Relative Tolerance", 1e-2); + Real opt_tol = lslist.sublist("Status Test").get("Gradient Tolerance", 1e-8); + sp_tol_min_ = static_cast(1e-2)*opt_tol; + verbosity_ = list.sublist("General").get("Output Level", 0); + writeHeader_ = verbosity_ > 2; + + list_.sublist("Status Test").set("Iteration Limit", sp_maxit); + list_.sublist("General").set("Output Level", verbosity_>0 ? verbosity_-1 : 0); + + if ( secant_ == nullPtr ) { + secantName_ = list.sublist("General").sublist("Secant").get("Type","Limited-Memory BFGS"); + esec_ = StringToESecant(secantName_); + secant_ = SecantFactory(list); + } + else { + secantName_ = list.sublist("General").sublist("Secant").get("User Defined Secant Name", + "Unspecified User Defined Secant Method"); + } +} + + +template +void QuasiNewtonAlgorithm::initialize(Vector &x, + const Vector &g, + Objective &sobj, + Objective &nobj, + Vector &dg, + std::ostream &outStream) { + const Real one(1); + Real tol(std::sqrt(ROL_EPSILON())); + // Initialize data + TypeP::Algorithm::initialize(x,g); + // Update approximate gradient and approximate objective function. + Real ftol = std::sqrt(ROL_EPSILON()); + if (initProx_) { + state_->iterateVec->set(x); + nobj.prox(x,*state_->iterateVec,one,tol); state_->nprox++; + } + sobj.update(x,UpdateType::Initial,state_->iter); + nobj.update(x,UpdateType::Initial,state_->iter); + state_->svalue = sobj.value(x,ftol); state_->nsval++; + state_->nvalue = nobj.value(x,ftol); state_->nnval++; + state_->value = state_->svalue + state_->nvalue; + sobj.gradient(*state_->gradientVec,x,ftol); state_->ngrad++; + dg.set(state_->gradientVec->dual()); + pgstep(*state_->iterateVec,*state_->stepVec,nobj,x,dg,t0_,tol); + state_->gnorm = state_->stepVec->norm() / t0_; + state_->snorm = ROL_INF(); + state_->iterateVec->set(x); +} + +template +void QuasiNewtonAlgorithm::run( Vector &x, + const Vector &g, + Objective &sobj, + Objective &nobj, + std::ostream &outStream ) { + const Real half(0.5), one(1); + // Initialize trust-region data + Ptr> s = x.clone(), gp = x.clone(), gold = g.clone(), xs = x.clone(); + initialize(x,g,sobj,nobj,*gp,outStream); + Real strial(0), ntrial(0), ftrial(0), gs(0), Qk(0), rhoTmp(0); + Real tol(std::sqrt(ROL_EPSILON())), gtol(1); + + Ptr> algo; + Ptr> qobj = makePtr>(secant_,x,g); + //Ptr> problem = makePtr>(qobj,xs); + + // Output + if (verbosity_ > 0) writeOutput(outStream,true); + + // Compute steepest descent step + while (status_->check(*state_)) { + // Compute step + qobj->setAnchor(x,*state_->gradientVec); + pgstep(*xs,*s,nobj,x,*gp,one,tol); + gtol = std::max(sp_tol_min_,std::min(sp_tol1_,sp_tol2_*state_->gnorm)); + list_.sublist("Status Test").set("Gradient Tolerance",gtol); + if (algoName_ == "Line Search") algo = makePtr>(list_); + else if (algoName_ == "iPiano") algo = makePtr>(list_); + else algo = makePtr>(list_); + algo->run(*xs,*qobj,nobj,outStream); + s->set(*xs); s->axpy(-one,x); + spgIter_ = algo->getState()->iter; + state_->nprox += staticPtrCast>(algo->getState())->nprox; + + // Perform backtracking line search + state_->searchSize = one; + x.set(*state_->iterateVec); + x.axpy(state_->searchSize,*s); + sobj.update(x,UpdateType::Trial); + nobj.update(x,UpdateType::Trial); + strial = sobj.value(x,tol); + ntrial = nobj.value(x,tol); + ftrial = strial + ntrial; + ls_nfval_ = 1; + gs = state_->gradientVec->apply(*s); + Qk = gs + ntrial - state_->nvalue; + if (verbosity_ > 1) { + outStream << " In TypeP::QuasiNewtonAlgorithm: Line Search" << std::endl; + outStream << " Step size: " << state_->searchSize << std::endl; + outStream << " Trial objective value: " << ftrial << std::endl; + outStream << " Computed reduction: " << state_->value-ftrial << std::endl; + outStream << " Dot product of gradient and step: " << gs << std::endl; + outStream << " Sufficient decrease bound: " << -Qk*c1_ << std::endl; + outStream << " Number of function evaluations: " << ls_nfval_ << std::endl; + } + while ( ftrial > state_->value + c1_*Qk && ls_nfval_ < maxit_ ) { + rhoTmp = -half * Qk / (strial-state_->svalue-state_->searchSize*gs); + state_->searchSize = ((sigma1_ <= rhoTmp && rhoTmp <= sigma2_) ? rhoTmp : rhodec_) * state_->searchSize; + x.set(*state_->iterateVec); + x.axpy(state_->searchSize,*s); + sobj.update(x,UpdateType::Trial); + nobj.update(x,UpdateType::Trial); + strial = sobj.value(x,tol); + ntrial = nobj.value(x,tol); + ftrial = strial + ntrial; + Qk = state_->searchSize * gs + ntrial - state_->nvalue; + ls_nfval_++; + if (verbosity_ > 1) { + outStream << std::endl; + outStream << " Step size: " << state_->searchSize << std::endl; + outStream << " Trial objective value: " << ftrial << std::endl; + outStream << " Computed reduction: " << state_->value-ftrial << std::endl; + outStream << " Dot product of gradient and step: " << gs << std::endl; + outStream << " Sufficient decrease bound: " << -Qk*c1_ << std::endl; + outStream << " Number of function evaluations: " << ls_nfval_ << std::endl; + } + } + state_->nsval += ls_nfval_; + state_->nnval += ls_nfval_; + + // Compute norm of step + state_->stepVec->set(*s); + state_->stepVec->scale(state_->searchSize); + state_->snorm = state_->stepVec->norm(); + + // Update iterate + state_->iterateVec->set(x); + + // Compute new value and gradient + state_->iter++; + state_->value = ftrial; + state_->svalue = strial; + state_->nvalue = ntrial; + sobj.update(x,UpdateType::Accept,state_->iter); + nobj.update(x,UpdateType::Accept,state_->iter); + gold->set(*state_->gradientVec); + sobj.gradient(*state_->gradientVec,x,tol); state_->ngrad++; + gp->set(state_->gradientVec->dual()); + + // Compute projected gradient norm + pgstep(*xs,*s,nobj,x,*gp,t0_,tol); + state_->gnorm = s->norm() / t0_; + + // Update secant + secant_->updateStorage(x,*state_->gradientVec,*gold,*state_->stepVec,state_->snorm,state_->iter); + + // Update Output + if (verbosity_ > 0) writeOutput(outStream,writeHeader_); + } + if (verbosity_ > 0) TypeP::Algorithm::writeExitStatus(outStream); +} + +template +void QuasiNewtonAlgorithm::writeHeader( std::ostream& os ) const { + std::stringstream hist; + if (verbosity_ > 1) { + hist << std::string(114,'-') << std::endl; + hist << "Line-Search Proximal Quasi-Newton with " << secantName_ << " Hessian approximation"; + hist << " status output definitions" << std::endl << std::endl; + hist << " iter - Number of iterates (steps taken)" << std::endl; + hist << " value - Objective function value" << std::endl; + hist << " gnorm - Norm of the gradient" << std::endl; + hist << " snorm - Norm of the step (update to optimization vector)" << std::endl; + hist << " alpha - Line search step length" << std::endl; + hist << " #sval - Cumulative number of times the smooth objective function was evaluated" << std::endl; + hist << " #nval - Cumulative number of times the nonsmooth objective function was evaluated" << std::endl; + hist << " #grad - Cumulative number of times the gradient was computed" << std::endl; + hist << " #prox - Cumulative number of times the projection was computed" << std::endl; + hist << " ls_#fval - Number of the times the objective function was evaluated during the line search" << std::endl; + hist << " sp_iter - Number iterations to compute quasi-Newton step" << std::endl; + hist << std::string(114,'-') << std::endl; + } + + hist << " "; + hist << std::setw(6) << std::left << "iter"; + hist << std::setw(15) << std::left << "value"; + hist << std::setw(15) << std::left << "gnorm"; + hist << std::setw(15) << std::left << "snorm"; + hist << std::setw(15) << std::left << "alpha"; + hist << std::setw(10) << std::left << "#sval"; + hist << std::setw(10) << std::left << "#nval"; + hist << std::setw(10) << std::left << "#grad"; + hist << std::setw(10) << std::left << "#prox"; + hist << std::setw(10) << std::left << "#ls_fval"; + hist << std::setw(10) << std::left << "sp_iter"; + hist << std::endl; + os << hist.str(); +} + +template +void QuasiNewtonAlgorithm::writeName( std::ostream& os ) const { + std::stringstream hist; + hist << std::endl << "Line-Search Proximal Quasi-Newton (Type P)" << std::endl; + os << hist.str(); +} + +template +void QuasiNewtonAlgorithm::writeOutput( std::ostream& os, bool write_header ) const { + std::stringstream hist; + hist << std::scientific << std::setprecision(6); + if ( state_->iter == 0 ) writeName(os); + if ( write_header ) writeHeader(os); + if ( state_->iter == 0 ) { + hist << " "; + hist << std::setw(6) << std::left << state_->iter; + hist << std::setw(15) << std::left << state_->value; + hist << std::setw(15) << std::left << state_->gnorm; + hist << std::setw(15) << std::left << "---"; + hist << std::setw(15) << std::left << "---"; + hist << std::setw(10) << std::left << state_->nsval; + hist << std::setw(10) << std::left << state_->nnval; + hist << std::setw(10) << std::left << state_->ngrad; + hist << std::setw(10) << std::left << state_->nprox; + hist << std::setw(10) << std::left << "---"; + hist << std::setw(10) << std::left << "---"; + hist << std::endl; + } + else { + hist << " "; + hist << std::setw(6) << std::left << state_->iter; + hist << std::setw(15) << std::left << state_->value; + hist << std::setw(15) << std::left << state_->gnorm; + hist << std::setw(15) << std::left << state_->snorm; + hist << std::setw(15) << std::left << state_->searchSize; + hist << std::setw(10) << std::left << state_->nsval; + hist << std::setw(10) << std::left << state_->nnval; + hist << std::setw(10) << std::left << state_->ngrad; + hist << std::setw(10) << std::left << state_->nprox; + hist << std::setw(10) << std::left << ls_nfval_; + hist << std::setw(10) << std::left << spgIter_; + hist << std::endl; + } + os << hist.str(); +} + +} // namespace TypeP +} // namespace ROL + +#endif diff --git a/packages/rol/test/algorithm/TypeP/CMakeLists.txt b/packages/rol/test/algorithm/TypeP/CMakeLists.txt index 973289b4b084..b31c4939612e 100644 --- a/packages/rol/test/algorithm/TypeP/CMakeLists.txt +++ b/packages/rol/test/algorithm/TypeP/CMakeLists.txt @@ -26,6 +26,15 @@ TRIBITS_ADD_EXECUTABLE_AND_TEST( ADD_DIR_TO_NAME ) +TRIBITS_ADD_EXECUTABLE_AND_TEST( + QuasiNewton + SOURCES test_05.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + TRIBITS_COPY_FILES_TO_BINARY_DIR( TypePTestDataCopy diff --git a/packages/rol/test/algorithm/TypeP/test_05.cpp b/packages/rol/test/algorithm/TypeP/test_05.cpp new file mode 100644 index 000000000000..2a4500ec7143 --- /dev/null +++ b/packages/rol/test/algorithm/TypeP/test_05.cpp @@ -0,0 +1,185 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +/*! \file test_05.cpp + \brief Validate proximal quasi-Newton algorithm. +*/ + +#include "ROL_TypeP_QuasiNewtonAlgorithm.hpp" +#include "ROL_StdObjective.hpp" +#include "ROL_l1Objective.hpp" +#include "ROL_Stream.hpp" +#include "Teuchos_GlobalMPISession.hpp" + +template +class QuadraticTypeP_Test01 : public ROL::StdObjective { +private: + int dim_; + std::vector a_, b_; + +public: + QuadraticTypeP_Test01(int dim) : dim_(dim) { + a_.resize(dim); + b_.resize(dim); + for (int i = 0; i < dim; ++i) { + a_[i] = static_cast(5)*static_cast(rand())/static_cast(RAND_MAX); + b_[i] = static_cast(20)*static_cast(rand())/static_cast(RAND_MAX) - static_cast(10); + } + } + + Real value(const std::vector &x, Real &tol) { + Real val(0); + for (int i = 0; i < dim_; ++i) + val += static_cast(0.5)*a_[i]*x[i]*x[i] + b_[i]*x[i]; + return val; + } + + void gradient(std::vector &g, const std::vector &x, Real &tol) { + for (int i = 0; i < dim_; ++i) + g[i] = a_[i]*x[i] + b_[i]; + } + + void hessVec(std::vector &hv, const std::vector &v, const std::vector &x, Real &tol) { + for (int i = 0; i < dim_; ++i) + hv[i] = a_[i]*v[i]; + } + + void getSolution(std::vector &x, const std::vector &wts, const std::vector &y) const { + for (int i = 0; i < dim_; ++i) + x[i] = (std::min(wts[i], std::max(-wts[i], a_[i]*y[i] + b_[i])) - b_[i]) / a_[i]; + } +}; + +typedef double RealT; + +int main(int argc, char *argv[]) { + + Teuchos::GlobalMPISession mpiSession(&argc, &argv); + + // This little trick lets us print to std::cout only if a + // (dummy) command-line argument is provided. + int iprint = argc - 1; + ROL::Ptr outStream; + ROL::nullstream bhs; // outputs nothing + if (iprint > 0) + outStream = ROL::makePtrFromRef(std::cout); + else + outStream = ROL::makePtrFromRef(bhs); + + int errorFlag = 0; + + try { + RealT tol = 1e2*std::sqrt(ROL::ROL_EPSILON()); + + ROL::ParameterList list; + list.sublist("General").set("Output Level",iprint); + list.sublist("Step").set("Type","iPiano"); + list.sublist("Status Test").set("Gradient Tolerance",1e-7); + list.sublist("Status Test").set("Constraint Tolerance",1e-8); + list.sublist("Status Test").set("Step Tolerance",1e-12); + list.sublist("Status Test").set("Iteration Limit", 10000); + + int dim = 5; + ROL::Ptr> sol, wts, y; + ROL::Ptr> sobj; + ROL::Ptr> nobj; + ROL::Ptr> algo; + std::vector data; + RealT err(0); + + *outStream << std::endl << "Random Diagonal LASSO Test Problem" << std::endl << std::endl; + ROL::Ptr> wtsP = ROL::makePtr>(dim); + ROL::Ptr> yP = ROL::makePtr>(dim); + wts = ROL::makePtr>(wtsP); + y = ROL::makePtr>(yP); + sol = ROL::makePtr>(dim); + wts->randomize(static_cast(0),static_cast(1)); + y->randomize(static_cast(-5),static_cast(5)); + sol->zero(); + + nobj = ROL::makePtr>(wts,y); + sobj = ROL::makePtr>(dim); + + // Check derivatives of smooth function + ROL::Ptr> xd = sol->clone(); + xd->randomize(-1.0,1.0); + ROL::Ptr> yd = sol->clone(); + yd->randomize(-1.0,1.0); + ROL::Ptr> zd = sol->clone(); + zd->randomize(-1.0,1.0); + sobj->checkGradient(*xd,*yd,true,*outStream); + sobj->checkHessVec(*xd,*yd,true,*outStream); + sobj->checkHessSym(*xd,*yd,*zd,true,*outStream); + + algo = ROL::makePtr>(list); + algo->run(*sol,*sobj,*nobj,*outStream); + + std::vector xstar(dim); + sobj->getSolution(xstar, *wtsP, *yP); + data = *ROL::staticPtrCast>(sol)->getVector(); + *outStream << " Result: "; + for (int i = 0; i < dim; ++i) { + *outStream << " x" << i+1 << " = " << data[i]; + err = std::max(err,std::abs(data[i]-xstar[i])); + } + *outStream << std::endl; + *outStream << " Truth: "; + for (int i = 0; i < dim; ++i) { + *outStream << " x" << i+1 << " = " << xstar[i]; + } + *outStream << std::endl; + *outStream << " Max-Error = " << err << std::endl; + errorFlag += (err > tol ? 1 : 0); + } + catch (std::logic_error& err) { + *outStream << err.what() << "\n"; + errorFlag = -1000; + }; // end try + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return 0; +} From d2894a5f89928b3b595208f4a1efcd7952390e58 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Fri, 23 Dec 2022 17:07:17 -0700 Subject: [PATCH 23/65] Reused PG step to evaluate gnorm, reducing the number of proxs. --- .../algorithm/TypeP/ROL_TypeP_QuasiNewtonAlgorithm_Def.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_QuasiNewtonAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_QuasiNewtonAlgorithm_Def.hpp index 977a8ee07f08..13ea9e5fb1db 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_QuasiNewtonAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_QuasiNewtonAlgorithm_Def.hpp @@ -120,7 +120,6 @@ void QuasiNewtonAlgorithm::initialize(Vector &x, pgstep(*state_->iterateVec,*state_->stepVec,nobj,x,dg,t0_,tol); state_->gnorm = state_->stepVec->norm() / t0_; state_->snorm = ROL_INF(); - state_->iterateVec->set(x); } template @@ -144,10 +143,11 @@ void QuasiNewtonAlgorithm::run( Vector &x, if (verbosity_ > 0) writeOutput(outStream,true); // Compute steepest descent step + xs->set(*state_->iterateVec); + state_->iterateVec->set(x); while (status_->check(*state_)) { // Compute step qobj->setAnchor(x,*state_->gradientVec); - pgstep(*xs,*s,nobj,x,*gp,one,tol); gtol = std::max(sp_tol_min_,std::min(sp_tol1_,sp_tol2_*state_->gnorm)); list_.sublist("Status Test").set("Gradient Tolerance",gtol); if (algoName_ == "Line Search") algo = makePtr>(list_); From c75c7bcac779053d1ae0187e6586bba563943781 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Fri, 23 Dec 2022 17:10:53 -0700 Subject: [PATCH 24/65] Added quasi-Newton TypeP algorithm to factory. --- .../rol/src/algorithm/TypeP/ROL_TypeP_AlgorithmFactory.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_AlgorithmFactory.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_AlgorithmFactory.hpp index 5a0c17652e48..4451af1fe0cf 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_AlgorithmFactory.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_AlgorithmFactory.hpp @@ -47,6 +47,7 @@ #include "ROL_TypeP_ProxGradientAlgorithm.hpp" #include "ROL_TypeP_SpectralGradientAlgorithm.hpp" #include "ROL_TypeP_iPianoAlgorithm.hpp" +#include "ROL_TypeP_QuasiNewtonAlgorithm.hpp" #include "ROL_Types.hpp" namespace ROL { @@ -58,11 +59,13 @@ namespace TypeP { \arg ALGORITHM_P_PROXIMALGRADIENT describe \arg ALGORITHM_P_SPECTRALGRADIENT describe \arg ALGORITHM_P_IPIANO describe + \arg ALGORITHM_P_QUASINEWTON describe */ enum EAlgorithmP{ ALGORITHM_P_PROXIMALGRADIENT = 0, ALGORITHM_P_SPECTRALGRADIENT, ALGORITHM_P_IPIANO, + ALGORITHM_P_QUASINEWTON, ALGORITHM_P_LAST }; @@ -72,6 +75,7 @@ inline std::string EAlgorithmPToString(EAlgorithmP alg) { case ALGORITHM_P_PROXIMALGRADIENT: retString = "Proximal Gradient"; break; case ALGORITHM_P_SPECTRALGRADIENT: retString = "Spectral Gradient"; break; case ALGORITHM_P_IPIANO: retString = "iPiano"; break; + case ALGORITHM_P_QUASINEWTON: retString = "Quasi-Newton"; break; case ALGORITHM_P_LAST: retString = "Last Type (Dummy)"; break; default: retString = "INVALID EAlgorithmP"; } @@ -87,6 +91,7 @@ inline int isValidAlgorithmP(EAlgorithmP alg){ return( (alg == ALGORITHM_P_PROXIMALGRADIENT) || (alg == ALGORITHM_P_SPECTRALGRADIENT) || (alg == ALGORITHM_P_IPIANO) || + (alg == ALGORITHM_P_QUASINEWTON) || (alg == ALGORITHM_P_LAST) ); } @@ -128,6 +133,7 @@ inline Ptr> AlgorithmFactory(ParameterList &parlist) { case ALGORITHM_P_PROXIMALGRADIENT: return makePtr>(parlist); case ALGORITHM_P_SPECTRALGRADIENT: return makePtr>(parlist); case ALGORITHM_P_IPIANO: return makePtr>(parlist); + case ALGORITHM_P_QUASINEWTON: return makePtr>(parlist); default: return nullPtr; } } From c41428d458fbbe067673b319018a0941dd3484d5 Mon Sep 17 00:00:00 2001 From: Bobby Date: Fri, 23 Dec 2022 17:28:34 -0700 Subject: [PATCH 25/65] bad tr alg --- .../algorithm/TypeP/ROL_TypeP_Algorithm.hpp | 5 + .../TypeP/ROL_TypeP_Algorithm_Def.hpp | 24 +- .../TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp | 252 ++++ .../ROL_TypeP_TrustRegionAlgorithm_Def.hpp | 1092 +++++++++++++++++ .../rol/test/algorithm/TypeP/CMakeLists.txt | 10 + packages/rol/test/algorithm/TypeP/test_04.cpp | 185 +++ 6 files changed, 1562 insertions(+), 6 deletions(-) create mode 100644 packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp create mode 100644 packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp create mode 100644 packages/rol/test/algorithm/TypeP/test_04.cpp diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm.hpp index 3384540ae7ad..e030820a6957 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm.hpp @@ -101,6 +101,11 @@ class Algorithm { Real t, // t = prox parameter Real &tol) const; + /*Real optimalityCriterion(const Vector &x, + const Vector &g, + Vector &primal, + std::ostream &outStream = std::cout) const; +*/ public: virtual ~Algorithm() {} diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm_Def.hpp index 86f97130d81c..51bcfae761d4 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm_Def.hpp @@ -77,12 +77,12 @@ void Algorithm::initialize(const Vector &x, const Vector &g) { } template -void Algorithm::pgstep(Vector &pgiter, - Vector &pgstep, - Objective &nobj, - const Vector &x, - const Vector &dg, - Real t, +void Algorithm::pgstep(Vector &pgiter, //solution of proximal operator + Vector &pgstep, //proximal step pgiter - x + Objective &nobj, //nonsmooth objective function + const Vector &x, //anchor vector + const Vector &dg, //direction + Real t, //Moreau Envelop constant Real &tol) const { pgstep.set(x); pgstep.axpy(-t,dg); @@ -92,6 +92,18 @@ void Algorithm::pgstep(Vector &pgiter, pgstep.axpy(static_cast(-1),x); } +/*template +Real Algorithm::optimalityCriterion( Vector &pgiter, + Vector &pgstep, + Objective &nobj, + const Vector &x, + const Vector &g, + Real t, + Real &tol) const { + pgstep(pgiter, *pgstep, nobj, x, g, t, tol) + return pgstep.norm()/t; +}*/ + template void Algorithm::setStatusTest(const Ptr> &status, bool combineStatus) { diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp new file mode 100644 index 000000000000..b1361d2b42f7 --- /dev/null +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp @@ -0,0 +1,252 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +#ifndef ROL_TYPEP_TRUSTREGIONALGORITHM_HPP +#define ROL_TYPEP_TRUSTREGIONALGORITHM_HPP + +#include "ROL_TypeP_Algorithm.hpp" +#include "ROL_TrustRegionModel_U.hpp" +#include "ROL_TrustRegionUtilities.hpp" + +/** \class ROL::TypeP::TrustRegionAlgorithm + \brief Provides an interface to run the trust-region algorithm. +*/ + +namespace ROL { +namespace TypeP { + +template +class TrustRegionAlgorithm : public TypeP::Algorithm { +private: + Ptr> model_; ///< Container for trust-region model + + // TRUST REGION PARAMETERS + Real delMax_; ///< Maximum trust-region radius (default: ROL_INF) + Real eta0_; ///< Step acceptance threshold (default: 0.05) + Real eta1_; ///< Radius decrease threshold (default: 0.05) + Real eta2_; ///< Radius increase threshold (default: 0.9) + Real gamma0_; ///< Radius decrease rate (negative rho) (default: 0.0625) + Real gamma1_; ///< Radius decrease rate (positive rho) (default: 0.25) + Real gamma2_; ///< Radius increase rate (default: 2.5) + Real TRsafe_; ///< Safeguard size for numerically evaluating ratio (default: 1e2) + Real eps_; ///< Safeguard for numerically evaluating ratio + bool interpRad_; ///< Interpolate the trust-region radius if ratio is negative (default: false) + + // ITERATION FLAGS/INFORMATION + TRUtils::ETRFlag TRflag_; ///< Trust-region exit flag + int SPflag_; ///< Subproblem solver termination flag + int SPiter_; ///< Subproblem solver iteration count + + // SECANT INFORMATION + ESecant esec_; ///< Secant type (default: Limited-Memory BFGS) + bool useSecantPrecond_; ///< Flag to use secant as a preconditioner (default: false) + bool useSecantHessVec_; ///< Flag to use secant as Hessian (default: false) + + // TRUNCATED CG INFORMATION + Real tol1_; ///< Absolute tolerance for truncated CG (default: 1e-4) + Real tol2_; ///< Relative tolerance for truncated CG (default: 1e-2) + int maxit_; ///< Maximum number of CG iterations (default: 25) + + // ALGORITHM SPECIFIC PARAMETERS + bool useNM_; + int storageNM_; + Real mu0_; ///< Sufficient decrease parameter (default: 1e-2) + Real spexp_; ///< Relative tolerance exponent for subproblem solve (default: 1, range: [1,2]) + int redlim_; ///< Maximum number of Cauchy point reduction steps (default: 10) + int explim_; ///< Maximum number of Cauchy point expansion steps (default: 10) + Real alpha_; ///< Initial Cauchy point step length (default: 1.0) + bool normAlpha_; ///< Normalize initial Cauchy point step length (default: false) + Real interpf_; ///< Backtracking rate for Cauchy point computation (default: 1e-1) + Real extrapf_; ///< Extrapolation rate for Cauchy point computation (default: 1e1) + Real qtol_; ///< Relative tolerance for computed decrease in Cauchy point computation (default: 1-8) + Real lambdaMin_; + Real lambdaMax_; + Real gamma_; + int maxSize_; + bool useMin_; + bool useNMSP_; + bool useSimpleSPG_; + + // Inexactness Parameters + std::vector useInexact_; + Real scale0_; + Real scale1_; + Real scale_; + Real omega_; + Real force_; + int updateIter_; + Real forceFactor_; + + bool initProx_; + Real t0_; + + mutable int nhess_; ///< Number of Hessian applications + unsigned verbosity_; ///< Output level (default: 0) + bool writeHeader_; ///< Flag to write header at every iteration + + using TypeP::Algorithm::state_; + using TypeP::Algorithm::status_; + using TypeP::Algorithm::pgstep; + + void initialize(Vector &x, + const Vector &g, + Objective &sobj, + Objective &nobj, + Vector &px, + Vector &dg, + std::ostream &outStream = std::cout); + +public: + TrustRegionAlgorithm(ParameterList &list, const Ptr> &secant = nullPtr); + + using TypeP::Algorithm::run; + void run( Vector &x, + const Vector &g, + Objective &sobj, + Objective &nobj, + std::ostream &outStream = std::cout) override; + + void writeHeader( std::ostream& os ) const override; + + void writeName( std::ostream& os ) const override; + + void writeOutput( std::ostream& os, bool write_header = false ) const override; + +private: + void initialize(Vector &x, + const Vector &g, + Real ftol, + Objective &sobj, + Objective &nobj, + std::ostream &outStream = std::cout); + + Real computeValue(Real inTol, + Real &outTol, + Real pRed, + Real &fold, + int iter, + const Vector &x, + const Vector &xold, + Objective &sobj, + Objective &nobj); + + Real computeGradient(const Vector &x, + Vector &g, + Vector &pwa, + Real del, + Objective &sobj, + Objective &nobj, + std::ostream &outStream = std::cout) const; + + // Compute the projected step s = P(x + alpha*w) - x + // Returns the norm of the projected step s + // s -- The projected step upon return + // w -- The direction vector w (unchanged) + // x -- The anchor vector x (unchanged) + // alpha -- The step size (unchanged) + // Real dgpstep(Vector &s, const Vector &w, + // const Vector &x, const Real alpha, + // std::ostream &outStream = std::cout) const; + + // Compute Cauchy point, i.e., the minimizer of q(P(x - alpha*g)-x) + // subject to the trust region constraint ||P(x - alpha*g)-x|| <= del + // s -- The Cauchy step upon return: Primal optimization space vector + // alpha -- The step length for the Cauchy point upon return + // x -- The anchor vector x (unchanged): Primal optimization space vector + // g -- The (dual) gradient vector g (unchanged): Primal optimization space vector + // del -- The trust region radius (unchanged) + // model -- Trust region model + // dwa -- Dual working array, stores Hessian applied to step + // dwa1 -- Dual working array + Real dcauchy(Vector &s, + Real &alpha, Real &q, + const Vector &x, + const Vector &g, + const Real del, + TrustRegionModel_U &model, + Vector &dwa, + Vector &dwa1, + std::ostream &outStream = std::cout); + + void dpsg_simple(Vector &y, + Real &q, Vector &gmod, + const Vector &x, + Real del, + TrustRegionModel_U &model, + Vector &pwa, + Vector &pwa1, + Vector &dwa, + std::ostream &outStream = std::cout); + + void dpsg(Vector &y, + Real &q, Vector &gmod, + const Vector &x, + Real del, + TrustRegionModel_U &model, + Vector &ymin, + Vector &pwa, + Vector &pwa1, + Vector &pwa2, + Vector &pwa3, + Vector &pwa4, + Vector &pwa5, + Vector &dwa, + std::ostream &outStream = std::cout); + + void dproj(Vector &x, + const Vector &x0, + Real del, + Vector &y0, + Vector &y1, + Vector &yc, + Vector &pwa, + std::ostream &outStream = std::cout) const; + +}; // class ROL::TypeP::TrustRegionAlgorithm + +} // namespace TypeP +} // namespace ROL + +#include "ROL_TypeP_TrustRegionAlgorithm_Def.hpp" + +#endif diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp new file mode 100644 index 000000000000..e0c7beda10ad --- /dev/null +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp @@ -0,0 +1,1092 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +#ifndef ROL_TYPEP_TRUSTREGIONALGORITHM_DEF_HPP +#define ROL_TYPEP_TRUSTREGIONALGORITHM_DEF_HPP + +#include + +namespace ROL { +namespace TypeP { + +template +TrustRegionAlgorithm::TrustRegionAlgorithm(ParameterList &list, + const Ptr> &secant) { + // Set status test + status_->reset(); + status_->add(makePtr>(list)); + + ParameterList &trlist = list.sublist("Step").sublist("Trust Region"); + // Trust-Region Parameters + state_->searchSize = trlist.get("Initial Radius", -1.0); + delMax_ = trlist.get("Maximum Radius", ROL_INF()); + eta0_ = trlist.get("Step Acceptance Threshold", 0.05); + eta1_ = trlist.get("Radius Shrinking Threshold", 0.05); + eta2_ = trlist.get("Radius Growing Threshold", 0.9); + gamma0_ = trlist.get("Radius Shrinking Rate (Negative rho)", 0.0625); + gamma1_ = trlist.get("Radius Shrinking Rate (Positive rho)", 0.25); + gamma2_ = trlist.get("Radius Growing Rate", 2.5); + TRsafe_ = trlist.get("Safeguard Size", 100.0); + eps_ = TRsafe_*ROL_EPSILON(); + interpRad_ = trlist.get("Use Radius Interpolation", false); + verbosity_ = trlist.sublist("General").get("Output Level", 0); + initProx_ = trlist.get("Apply Prox to Initial Guess", false); //change here? + // Nonmonotone Parameters + storageNM_ = trlist.get("Nonmonotone Storage Size", 0); + useNM_ = (storageNM_ <= 0 ? false : true); + // Algorithm-Specific Parameters + ROL::ParameterList &lmlist = trlist.sublist("TRN"); + mu0_ = lmlist.get("Sufficient Decrease Parameter", 1e-2); + spexp_ = lmlist.get("Relative Tolerance Exponent", 1.0); + spexp_ = std::max(static_cast(1),std::min(spexp_,static_cast(2))); + redlim_ = lmlist.sublist("Cauchy Point").get("Maximum Number of Reduction Steps", 10); + explim_ = lmlist.sublist("Cauchy Point").get("Maximum Number of Expansion Steps", 10); + alpha_ = lmlist.sublist("Cauchy Point").get("Initial Step Size", 1.0); + normAlpha_ = lmlist.sublist("Cauchy Point").get("Normalize Initial Step Size", false); + interpf_ = lmlist.sublist("Cauchy Point").get("Reduction Rate", 0.1); + extrapf_ = lmlist.sublist("Cauchy Point").get("Expansion Rate", 10.0); + qtol_ = lmlist.sublist("Cauchy Point").get("Decrease Tolerance", 1e-8); + // Subsolver (spectral projected gradient) parameters + lambdaMin_ = lmlist.sublist("Solver").get("Minimum Spectral Step Size", 1e-8); + lambdaMax_ = lmlist.sublist("Solver").get("Maximum Spectral Step Size", 1e8); + gamma_ = lmlist.sublist("Solver").get("Sufficient Decrease Tolerance", 1e-4); + maxSize_ = lmlist.sublist("Solver").get("Maximum Storage Size", 10); + maxit_ = lmlist.sublist("Solver").get("Iteration Limit", 25); + tol1_ = lmlist.sublist("Solver").get("Absolute Tolerance", 1e-4); + tol2_ = lmlist.sublist("Solver").get("Relative Tolerance", 1e-2); + useMin_ = lmlist.sublist("Solver").get("Use Smallest Model Iterate", true); + useNMSP_ = lmlist.sublist("Solver").get("Use Nonmonotone Search", false); + useSimpleSPG_ = !lmlist.sublist("Solver").get("Compute Cauchy Point", true); + t0_ = list.sublist("Status Test").get("Proximal Gradient Parameter", 1.0); //change here? + // Inexactness Information + ParameterList &glist = list.sublist("General"); + useInexact_.clear(); + useInexact_.push_back(glist.get("Inexact Objective Function", false)); + useInexact_.push_back(glist.get("Inexact Gradient", false)); + useInexact_.push_back(glist.get("Inexact Hessian-Times-A-Vector", false)); + // Trust-Region Inexactness Parameters + ParameterList &ilist = trlist.sublist("Inexact").sublist("Gradient"); + scale0_ = ilist.get("Tolerance Scaling", static_cast(0.1)); + scale1_ = ilist.get("Relative Tolerance", static_cast(2)); + // Inexact Function Evaluation Information + ParameterList &vlist = trlist.sublist("Inexact").sublist("Value"); + scale_ = vlist.get("Tolerance Scaling", static_cast(1.e-1)); + omega_ = vlist.get("Exponent", static_cast(0.9)); + force_ = vlist.get("Forcing Sequence Initial Value", static_cast(1.0)); + updateIter_ = vlist.get("Forcing Sequence Update Frequency", static_cast(10)); + forceFactor_ = vlist.get("Forcing Sequence Reduction Factor", static_cast(0.1)); + // Output Parameters + verbosity_ = list.sublist("General").get("Output Level",0); + writeHeader_ = verbosity_ > 2; + // Secant Information + useSecantPrecond_ = list.sublist("General").sublist("Secant").get("Use as Preconditioner", false); + useSecantHessVec_ = list.sublist("General").sublist("Secant").get("Use as Hessian", false); + ESecantMode mode = SECANTMODE_BOTH; + if (useSecantPrecond_ && !useSecantHessVec_) mode = SECANTMODE_INVERSE; + else if (useSecantHessVec_ && !useSecantPrecond_) mode = SECANTMODE_FORWARD; + // Initialize trust region model + model_ = makePtr>(list,secant,mode); + if (secant == nullPtr) { + esec_ = StringToESecant(list.sublist("General").sublist("Secant").get("Type","Limited-Memory BFGS")); + } +} + +template +void TrustRegionAlgorithm::initialize(Vector &x, + const Vector &g, + Real ftol, + Objective &sobj, + Objective &nobj, + Vector &px, + Vector &dg, + std::ostream &outStream) { + //const Real one(1); + // Initialize data + TypeP::Algorithm::initialize(x,g); + nhess_ = 0; + // Update approximate gradient and approximate objective function. + if (initProx_){ + nobj.prox(*state_->iterateVec, x, t0_, ftol); state_->nprox++; + x.set(*state_->iterateVec); + } + sobj.update(x,UpdateType::Initial,state_->iter); + state_->svalue = sobj.value(x,ftol); state_->nsval++; + nobj.update(x, UpdateType::Initial,state_->iter); + state_->nvalue = nobj.value(x,ftol); state_->nnval++; + state_->value = state_->svalue + state_->nvalue; + //obj.gradient(*state_->gradientVec,x,ftol);//make sure below sets dg to dual gradient + state_->gnorm = computeGradient(x,*state_->gradientVec,px,dg,*state_->stepVec,state_->searchSize,sobj,nobj,outStream); + state_->ngrad++; + //dg.set(state_->gradientVect->dual()); + //pgstep(px, *state_->stepVec, nobj, x, dg, t0_, ftol); + //state_->gnorm = state_->stepVec->norm()/t0_; + state_->snorm = ROL_INF(); + // Normalize initial CP step length + if (normAlpha_) alpha_ /= state_->gradientVec->norm();//change here? + // Compute initial trust region radius if desired. + if ( state_->searchSize <= static_cast(0) ) + state_->searchSize = state_->gradientVec->norm(); +} + +template +Real TrustRegionAlgorithm::computeValue(Real inTol, + Real &outTol, + Real pRed, + Real &fold, + int iter, + const Vector &x, + const Vector &xold, + Objective &sobj) { + outTol = std::sqrt(ROL_EPSILON()); + if ( useInexact_[0] ) { + if (!(iter%updateIter_) && (iter!=0)) force_ *= forceFactor_; + const Real one(1); + Real eta = static_cast(0.999)*std::min(eta1_,one-eta2_); + outTol = scale_*std::pow(eta*std::min(pRed,force_),one/omega_); + if (inTol > outTol) { + fold = sobj.value(xold,outTol); + state_->nsval++; + } + } + // Evaluate objective function at new iterate + sobj.update(x,UpdateType::Trial); + Real fval = sobj.value(x,outTol); + state_->nsval++; + return fval; +} + +template +Real TrustRegionAlgorithm::computeGradient(const Vector &x, + Vector &g, + Vector &px, + Vector &dg, + Vector &step, + Real del, + Objective &sobj, + Objective &nobj, + std::ostream &outStream) const { + Real gnorm(0); + if ( useInexact_[1] ) { + const Real one(1); + Real gtol1 = scale0_*del; + Real gtol0 = gtol1 + one; + while ( gtol0 > gtol1 ) { + obj.gradient(g,x,gtol1); + state_->ngrad++; + //gnorm = TypeP::Algorithm::optimalityCriterion(x,g,pwa,outStream); + //[grad, gerr] = problem.obj_smooth.gradient(x, gtol); cnt.ngrad = cnt.ngrad + 1; + dg.set(state_->g->dual()); + pgstep(px, step, nobj, x, dg, one, gtol) // change gtol? one or ocScale? + state_->nprox++; + gnorm = step->norm() / one; + + gtol0 = gtol1; + gtol1 = scale0_*std::min(gnorm,del); + } + } + else { + Real gtol = std::sqrt(ROL_EPSILON()); + obj.gradient(g,x,gtol); + state_->ngrad++; + //gnorm = TypeP::Algorithm::optimalityCriterion(x,g,pwa,outStream); + pgstep(px, step, nobj, x, dg, one, gtol); + state_->nprox++; + gnorm = step->norm() / one; + } + return gnorm; +} + +template +void TrustRegionAlgorithm::run(Vector &x, + const Vector &g, + Objective &sobj, + Objective &nobj, + std::ostream &outStream ) { + const Real zero(0), one(1); + //Real tol0 = std::sqrt(ROL_EPSILON()); + Real inTol = static_cast(0.1)*ROL_OVERFLOW(), outTol(inTol); + Real strial(0), ntrial(0), Ftrial(0), pRed(0), rho(1), q(0); + // Initialize trust-region data + std::vector output; + initialize(x,g,inTol,sobj,nobj, px, dg, outStream); + Ptr> gmod = g.clone(); + Ptr> px = x.clone(); + Ptr> dg = g.clone(); + Ptr> pwa1 = x.clone(), pwa2 = x.clone(); + Ptr> pwa3 = x.clone(), pwa4 = x.clone(); + Ptr> pwa5 = x.clone(), pwa6 = x.clone(); + Ptr> pwa7 = x.clone(); + Ptr> dwa1 = g.clone(), dwa2 = g.clone(); + // Initialize nonmonotone data + Real rhoNM(0), sigmac(0), sigmar(0); + Real fr(state_->value), fc(state_->value), fmin(state_->value); + TRUtils::ETRFlag TRflagNM; + int L(0); + + // Output + if (verbosity_ > 0) writeOutput(outStream,true); + + while (status_->check(*state_)) { + // Build trust-region model + model_->setData(sobj,*state_->iterateVec,*state_->gradientVec);//should only be sobj? + + /**** SOLVE TRUST-REGION SUBPROBLEM ****/ + q = state_->sval + state_->nval;//q is mold + gmod->set(*state_->gradientVec); + if (useSimpleSPG_) + dpsg_simple(x,q,pRed,*gmod,*state_->iterateVec,state_->searchSize,*model_,nobj, + *pwa1,*pwa2,*dwa1,outStream);//probably nobj? + else { + // Compute Cauchy point (TRON notation: x = x[1]) + dcauchy(*state_->stepVec,alpha_,q,pRed,*state_->iterateVec,//add pred, q is mold + state_->gradientVec->dual(),state_->searchSize, + *model_,*dwa1,*dwa2,outStream); // Solve 1D optimization problem for alpha + x.plus(*state_->stepVec); // Set x = x[0] + alpha*g + + // Model gradient at s = x[1] - x[0] + gmod->plus(*dwa1); // hessVec from Cauchy point computation + + // Apply SPG starting from the Cauchy point + dpsg(x,q,pRed,*gmod,*state_->iterateVec,state_->searchSize,*model_,nobj, + *pwa1,*pwa2,*pwa3,*pwa4,*pwa5,*pwa6,*pwa7,*dwa1,outStream);//probably nobj + } + + // Update storage and compute predicted reduction + //pRed = -q; // now updated in dcauchy/dspg + state_->stepVec->set(x); state_->stepVec->axpy(-one,*state_->iterateVec); + state_->snorm = state_->stepVec->norm(); + + // Compute trial objective value + strial = computeValue(inTol,outTol,pRed,state_->svalue,state_->iter,x,*state_->iterateVec,sobj,nobj); + nobj.update(*state_->iterateVec, UpdateType::Trial); + ntrial = nobj.value(*state_->iteratevec,tol); + state_->nsval++; + state_->nnval++; + + // Compute ratio of acutal and predicted reduction + TRflag_ = TRUtils::SUCCESS; + TRUtils::analyzeRatio(rho,TRflag_,state_->value,Ftrial,pRed,eps_,outStream,verbosity_>1); + /*if (useNM_) { + TRUtils::analyzeRatio(rhoNM,TRflagNM,fr,Ftrial,pRed+sigmar,eps_,outStream,verbosity_>1); + TRflag_ = (rho < rhoNM ? TRflagNM : TRflag_); + rho = (rho < rhoNM ? rhoNM : rho ); + }*/ + + // Update algorithm state + state_->iter++; + // Accept/reject step and update trust region radius + if ((rho < eta0_ && TRflag_ == TRUtils::SUCCESS) || (TRflag_ >= 2)) { // Step Rejected + x.set(*state_->iterateVec); + sobj.update(x,UpdateType::Revert,state_->iter); + nobj.update(x,UpdateType::Revert,state_->iter); + if (interpRad_ && (rho < zero && TRflag_ != TRUtils::TRNAN)) { //what is this? + // Negative reduction, interpolate to find new trust-region radius + state_->searchSize = TRUtils::interpolateRadius(*state_->gradientVec,*state_->stepVec, + state_->snorm,pRed,state_->value,ftrial,state_->searchSize,gamma0_,gamma1_,eta2_, + outStream,verbosity_>1); + } + else { // Shrink trust-region radius + state_->searchSize = gamma1_*std::min(state_->snorm,state_->searchSize); + } + } + else if ((rho >= eta0_ && TRflag_ != TRUtils::NPOSPREDNEG) + || (TRflag_ == TRUtils::POSPREDNEG)) { // Step Accepted + state_->value = strial + ntrial; + state_->svalue = strial; + state_->nvalue = ntrial; + sobj.update(x,UpdateType::Accept,state_->iter); + nobj.update(x,UpdateType::Accept,state_->iter); + inTol = outTol; + /*if (useNM_) { + sigmac += pRed; sigmar += pRed; + if (ftrial < fmin) { fmin = ftrial; fc = fmin; sigmac = zero; L = 0; } + else { + L++; + if (ftrial > fc) { fc = ftrial; sigmac = zero; } + if (L == storageNM_) { fr = fc; sigmar = sigmac; } + } + }*/ + // Increase trust-region radius + if (rho >= eta2_) state_->searchSize = std::min(gamma2_*state_->searchSize, delMax_); + // Compute gradient at new iterate + dwa1->set(*state_->gradientVec); + //state_->gnorm = computeGradient(x,*state_->gradientVec,px,dg,*state_->stepVec,state_->searchSize,sobj,nobj,outStream); + state_->gnorm = computeGradient(x,*state_->gradientVec,px,dg,*pwa1,state_->searchSize,sobj,nobj,outStream); + state_->ngrad++; + state_->iterateVec->set(x); + // Update secant information in trust-region model + model_->update(x,*state_->stepVec,*dwa1,*state_->gradientVec, + state_->snorm,state_->iter); + } + + // Update Output + if (verbosity_ > 0) writeOutput(outStream,writeHeader_); + } + if (verbosity_ > 0) TypeP::Algorithm::writeExitStatus(outStream); +} + +/*template +Real TrustRegionNonsmoothAlgorithm::dgpstep(Vector &s, const Vector &w, + const Vector &x, const Real alpha, + std::ostream &outStream) const { + s.set(x); s.axpy(alpha,w); + proj_->project(s,outStream); state_->nproj++; + s.axpy(static_cast(-1),x); + return s.norm(); +}*/ + +template +Real TrustRegionAlgorithm::dcauchy(Vector &s, + Real &alpha, + Real &mval, + Real &pRed, + const Vector &x, + const Vector &g, + Vector &px, + const Real del, + TrustRegionModel_U &model, + Objective, nobj, + Vector &dwa, + Vector &dwa1, + std::ostream &outStream) { + const Real half(0.5); + // const Real zero(0); // Unused + Real tol = std::sqrt(ROL_EPSILON()); + bool interp = false; + Real gs(0), snorm(0), phiold(0), phinew(0), mold(mval), Qk(0); + // Compute s = P(x[0] - alpha g[0]) + //snorm = dgpstep(s,g,x,-alpha,outStream); + dwa1.set(g->dual()); //already the dual + pgstep(px, *s, nobj, x, dwa1, alpha, tol); + snorm = s->norm(); //correct? + if (snorm > del) { + interp = true; + } + else { + model.hessVec(dwa,s,x,tol); nhess_++;//should rewrite dwa? + gs = s.dot(g); + phinew = nobj.value(px, tol); + //q = half * s.dot(dwa.dual()) + gs; + mval = half * s.apply(dwa) + gs + phinew; + Qk = gs + phinew - phiold; + interp = (mval > mold + mu0_*Qk);//what is this? + } + // Either increase or decrease alpha to find approximate Cauchy point + int cnt = 0; + if (interp) { + bool search = true; + while (search) { + alpha *= interpf_; + //snorm = dgpstep(s,g,x,-alpha,outStream); + pgstep(px, *s, nobj, x, dwa1, alpha, tol); + snorm = s->norm(); + if (snorm <= del || ) { + model.hessVec(dwa,s,x,tol); nhess_++; + gs = s.dot(g); + //q = half * s.dot(dwa.dual()) + gs; + phinew = nobj.value(px, tol); + mval = half * s.apply(dwa) + gs + phinew; + Qk = gs + phinew - phiold; + search = (mval > mold + mu0_*Qk) && (cnt < redlim_); + } + mold = mval; + cnt++; + } + } + else { + bool search = true; + Real alphas = alpha; + Real mvals = mval; + dwa1.set(dwa); + while (search) { + alpha *= extrapf_; + //snorm = dgpstep(s,g,x,-alpha,outStream); + pgstep(px, *s, nobj, x, dg, alpha, tol); + if (snorm <= del && cnt < explim_) { + model.hessVec(dwa,s,x,tol); nhess_++; + gs = s.dot(g); + phinew = nobj.value(px, tol); + //q = half * s.dot(dwa.dual()) + gs; + mval = half * s.apply(dwa) + gs + phinew; + Qk = gs + phinew - phiold + if (mval <= mold + mu0_*Qk && std::abs(mval-mvals) > qtol_*std::abs(mvals)) { + dwa1.set(dwa); + search = true; + alphas = alpha; + mvals = mval; + } + else { + mval = mvals; + dwa.set(dwa1); + search = false; + } + } + else { + search = false; + } + cnt++; + } + alpha = alphas; + //snorm = dgpstep(s,g,x,-alpha,outStream); + pgstep(px, *s, nobj, x, dg, alpha, tol); + snorm = s->norm(); + } + pRed = mval - mold; + if (verbosity_ > 1) { + outStream << " Cauchy point" << std::endl; + outStream << " Step length (alpha): " << alpha << std::endl; + outStream << " Step length (alpha*g): " << snorm << std::endl; + outStream << " Model decrease (pRed): " << pRed << std::endl; + if (!interp) { + outStream << " Number of extrapolation steps: " << cnt << std::endl; + } + } + return snorm; +} + +template +void TrustRegionAlgorithm::dpsg_simple(Vector &y, //x + Real &mval, //mval (formerly q) + Real &pRed, //predicted reduction + Vector &gmod, // state_->gradientVec + const Vector &x, //iterateVect + Vector &px, // px + Vector &dg, // gradient dual? + Real del, + TrustRegionModel_U &model, + Objective nobj, + Vector &pwa, + Vector &pwa1, + Vector &dwa, + std::ostream &outStream) { + // Use SPG to approximately solve TR subproblem: + // min 1/2 + subject to y\in C, ||y|| \le del + // + // Inpute: + // y = Primal vector + // x = Current iterate + // g = Current gradient + const Real half(0.5), one(1), safeguard(1e2*ROL_EPSILON()); + Real tol(std::sqrt(ROL_EPSILON())); + Real alpha(1), alphaMax(1), s0s0(0), ss0(0), sHs(0), lambdaTmp(1), snorm(0), mold(mval); + Real phinew(0), phiold(0); + pwa1.zero(); + + // Set y = x + y.set(x); + + // Compute initial step + Real coeff = one/gmod.norm(); + Real lambda = std::max(lambdaMin_,std::min(coeff,lambdaMax_)); + pgstep(px, pwa, nobj, y, gmod.dual(), alpha, tol); // pass pwa by reference? *pwa? + //pwa.set(y); pwa.axpy(-lambda,gmod.dual()); // pwa = x - lambda gmod.dual() + //proj_->project(pwa,outStream); state_->nproj++; // pwa = P(x - lambda gmod.dual()) + //pwa.axpy(-one,y); // pwa = P(x - lambda gmod.dual()) - x = step + Real gs = gmod.apply(pwa); // gs = + Real ss = pwa.dot(pwa); // Norm squared of step + Real gnorm = std::sqrt(ss); + + // Compute initial projected gradient norm + const Real gtol = std::min(tol1_,tol2_*gnorm); + + if (verbosity_ > 1) + outStream << " Spectral Projected Gradient" << std::endl; + + SPiter_ = 0; + while (SPiter_ < maxit_) { + SPiter_++; + + // Evaluate model Hessian + model.hessVec(dwa,pwa,x,tol); nhess_++; // dwa = H step + sHs = dwa.apply(pwa); // sHs = + + // Perform line search + alphaMax = 1; + if (gnorm >= del-safeguard) { // Trust-region constraint is violated + ss0 = pwa1.dot(pwa); + alphaMax = std::min(one, (-ss0 + std::sqrt(ss0*ss0 - ss*(s0s0-del*del)))/ss); + } + if (sHs <= safeguard) + alpha = alphaMax; + else + alpha = std::min(alphaMax, -gs/sHs); + + // Update model quantities + y.axpy(alpha,pwa); // New iterate + phiold = nobj.value(x, tol); + phinew = nobj.value(y, tol); + mval += alpha * (gs + half * alpha * sHs) - phiold + phinew; // Update model value - is this correct? + gmod.axpy(alpha,dwa); // Update model gradient + + pRed = mold - mnew; + + // Check trust-region constraint violation + pwa1.set(y); pwa1.axpy(-one,x); + s0s0 = pwa1.dot(pwa1); + snorm = std::sqrt(s0s0); + + if (verbosity_ > 1) { + outStream << std::endl; + outStream << " Iterate: " << SPiter_ << std::endl; + outStream << " Spectral step length (lambda): " << lambda << std::endl; + outStream << " Step length (alpha): " << alpha << std::endl; + outStream << " Model decrease (pRed): " << pRed << std::endl; + outStream << " Optimality criterion: " << gnorm << std::endl; + outStream << " Step norm: " << snorm << std::endl; + outStream << std::endl; + } + + if (snorm >= del - safeguard) { SPflag_ = 2; break; } + + // Compute new spectral step + lambdaTmp = (sHs <= safeguard ? one/gmod.norm() : ss/sHs); + lambda = std::max(lambdaMin_,std::min(lambdaTmp,lambdaMax_)); + + pgstep(px, pwa, nobj, y, gmod.dual(), alpha, tol); // pass pwa by reference? *pwa? + //pwa.set(y); pwa.axpy(-lambda,gmod.dual()); + //proj_->project(pwa,outStream); state_->nproj++; + //pwa.axpy(-one,y); + gs = gmod.apply(pwa); + ss = pwa.dot(pwa); + gnorm = std::sqrt(ss); + + if (gnorm <= gtol) { SPflag_ = 0; break; } + } + SPflag_ = (SPiter_==maxit_) ? 1 : SPflag_; +} + +template +void TrustRegionAlgorithm::dpsg(Vector &y, + Real &sval, + Real &nval, + Real &pRed, + Vector &gmod, + Vector &px, + Vector &dg, + const Vector &x, + Real del, + TrustRegionModel_U &model, + Vector &ymin, + Vector &pwa, + Vector &pwa1, + Vector &pwa2, + Vector &pwa3, + Vector &pwa4, + Vector &pwa5, + Vector &dwa, + std::ostream &outStream) { + // Use SPG to approximately solve TR subproblem: + // min 1/2 + subject to y\in C, ||y|| \le del + // + // Inpute: + // y = Cauchy step + // x = Current iterate + // g = Current gradient + const Real zero(0), half(0.5), one(1), two(2); //, eps(std::sqrt(ROL_EPSILON())); + Real tol(std::sqrt(ROL_EPSILON())); + Real alpha(1), sHs(0), alphaTmp(1), mmax(0), mval_min(0), lambdaTmp(1); + Real mold(sval+nval); + std::deque mqueue; mqueue.push_back(mold); + + if (useNMSP_ && useMin_) { mval_min = mval; ymin.set(y); } + + // Compute initial projected gradient norm + pwa1.set(gmod.dual()); + pwa.set(y); pwa.axpy(-one,pwa1); + dproj(pwa,x,del,nobj,pwa2,pwa3,pwa4,pwa5,outStream); + pwa.axpy(-one,y); + Real gnorm = pwa.norm(); + const Real gtol = std::min(tol1_,tol2_*gnorm); + + // Compute initial step + Real coeff = one/gmod.norm(); + Real lambda = std::max(lambdaMin_,std::min(coeff,lambdaMax_)); + pwa.set(y); pwa.axpy(-lambda,pwa1); // pwa = y - lambda gmod.dual() + dproj(pwa,x,nobj,del,pwa2,pwa3,pwa4,pwa5,outStream); // pwa = P(y - lambda gmod.dual()) + nobj.update(pwa, UpdateType::Trial); + Real ntrial = nobj.value(pwa, tol); + pwa.axpy(-one,y); // pwa = P(y - lambda gmod.dual()) - y = step + Real gs = gmod.apply(pwa); // gs = + Real Qk = gs - nval + ntrial; + Real ss = pwa.dot(pwa); // Norm squared of step + + if (verbosity_ > 1) + outStream << " Spectral Projected Gradient" << std::endl; + + SPiter_ = 0; + while (SPiter_ < maxit_) { + SPiter_++; + + // Evaluate model Hessian + model.hessVec(dwa,pwa,x,tol); nhess_++; // dwa = H step + sHs = dwa.apply(pwa); // sHs = + + // Perform line search + if (useNMSP_) { // Nonmonotone + mmax = *std::max_element(mqueue.begin(),mqueue.end()); + alphaTmp = (-(Qk - gamma_*gs) + std::sqrt(std::pow((Qk - gamma_*gs),two)-two*sHs*(sval+nval-mmax)))/sHs; //come back to this + } + else { // Exact + alphaTmp = -Qk/sHs; + } + alpha = (sHs > zero ? std::min(one,std::max(zero,alphaTmp)) : one); + + // Update model quantities + sval += alpha * (gs + half * alpha * sHs); // Update smooth model value + gmod.axpy(alpha,dwa); // Update model gradient + y.axpy(alpha,pwa); // New iterate + + nobj.update(y, UpdateType::Accept); + nval = nobj.value(y, tol); + + // Update nonmonotone line search information + if (useNMSP_) { + if (static_cast(mqueue.size())==maxSize_) mqueue.pop_front(); + mqueue.push_back(sval+nval); + if (useMin_ && sval+nval <= qmin) { qmin = sval+nval; ymin.set(y); } + } + + // Compute projected gradient norm + pwa1.set(gmod.dual()); + pwa.set(y); pwa.axpy(-one,pwa1); + dproj(pwa,x,del,nobj, pwa2,pwa3,pwa4,pwa5,outStream); + pwa.axpy(-one,y); + gnorm = pwa.norm(); + pRed = sval+nval - mold; + + if (verbosity_ > 1) { + outStream << std::endl; + outStream << " Iterate: " << SPiter_ << std::endl; + outStream << " Spectral step length (lambda): " << lambda << std::endl; + outStream << " Step length (alpha): " << alpha << std::endl; + outStream << " Model decrease (pRed): " << pRed << std::endl; + outStream << " Optimality criterion: " << gnorm << std::endl; + outStream << std::endl; + } + if (gnorm < gtol) break; + + // Compute new spectral step + //lambda = (sHs<=eps ? lambdaMax_ : std::max(lambdaMin_,std::min(ss/sHs,lambdaMax_))); + lambdaTmp = (sHs == 0 ? coeff : ss/sHs); + lambda = std::max(lambdaMin_,std::min(lambdaTmp,lambdaMax_)); + pwa.set(y); pwa.axpy(-lambda,pwa1); + dproj(pwa,x,del,nobj,pwa2,pwa3,pwa4,pwa5,outStream); + pwa.axpy(-one,y); + gs = gmod.apply(pwa); + ss = pwa.dot(pwa); + } + if (useNMSP_ && useMin_) { q = qmin; y.set(ymin); } + SPflag_ = (SPiter_==maxit_) ? 1 : 0; +} + +template +void TrustRegionAlgorithm::dproj(Vector &x, + const Vector &x0, + Real del, + Objective &nobj, + Vector &y0, + Vector &y1, + Vector &yc, + Vector &pwa, + std::ostream &outStream) const { + // Solve ||P(t*x0 + (1-t)*(x-x0))-x0|| = del using Brent's method + const Real zero(0), half(0.5), one(1), two(2), three(3); + const Real eps(ROL_EPSILON()), tol0(1e1*eps), fudge(1.0-1e-2*sqrt(eps)); + Real f0(0), f1(0), fc(0), t0(0), t1(1), tc(0), d1(1), d2(1), tol(1); + Real p(0), q(0), r(0), s(0), m(0); + int cnt(state_->nproj); + nobj.prox(y1, x, one, tol); state_->nprox++; + pwa.set(y1); pwa.axpy(-one,x0); + f1 = pwa.norm(); + if (f1 <= del) { + x.set(y1); + return; + } + y0.set(x0); + tc = t0; fc = f0; yc.set(y0); + d1 = t1-t0; d2 = d1; + int code = 0; + while (true) { + if (std::abs(fc-del) < std::abs(f1-del)) { + t0 = t1; t1 = tc; tc = t0; + f0 = f1; f1 = fc; fc = f0; + y0.set(y1); y1.set(yc); yc.set(y0); + } + tol = two*eps*std::abs(t1) + half*tol0; + m = half*(tc - t1); + if (std::abs(m) <= tol) { code = 1; break; } + if ((f1 >= fudge*del && f1 <= del)) break; + if (std::abs(d1) < tol || std::abs(f0-del) <= std::abs(f1-del)) { + d1 = m; d2 = d1; + } + else { + s = (f1-del)/(f0-del); + if (t0 == tc) { + p = two*m*s; + q = one-s; + } + else { + q = (f0-del)/(fc-del); + r = (f1-del)/(fc-del); + p = s*(two*m*q*(q-r)-(t1-t0)*(r-one)); + q = (q-one)*(r-one)*(s-one); + } + if (p > zero) q = -q; + else p = -p; + s = d1; + d1 = d2; + if (two*p < three*m*q-std::abs(tol*q) && p < std::abs(half*s*q)) { + d2 = p/q; + } + else { + d1 = m; d2 = d1; + } + } + t0 = t1; f0 = f1; y0.set(y1); + if (std::abs(d2) > tol) t1 += d2; + else if (m > zero) t1 += tol; + else t1 -= tol; + pwa.set(x); pwa.scale(t1); pwa.axpy(one-t1,x0); + nobj.prox(y1, pwa, t1, tol); + state_->nprox++; + pwa.set(y1); pwa.axpy(-one,x0); + f1 = pwa.norm(); + if ((f1 > del && fc > del) || (f1 <= del && fc <= del)) { + tc = t0; fc = f0; yc.set(y0); + d1 = t1-t0; d2 = d1; + } + } + if (code==1 && f1>del) x.set(yc); + else x.set(y1); + if (verbosity_ > 1) { + outStream << std::endl; + outStream << " Trust-Region Subproblem Proximity Operator" << std::endl; + outStream << " Number of proxes: " << state_->nproj-cnt << std::endl; + if (code == 1 && f1 > del) { + outStream << " Transformed Multiplier: " << tc << std::endl; + outStream << " Dual Residual: " << fc-del << std::endl; + } + else { + outStream << " Transformed Multiplier: " << t1 << std::endl; + outStream << " Dual Residual: " << f1-del << std::endl; + } + outStream << " Exit Code: " << code << std::endl; + outStream << std::endl; + } +} + +// BRACKETING AND BRENTS FOR UNTRANSFORMED MULTIPLIER +//template +//void TrustRegionSPGAlgorithm::dproj(Vector &x, +// const Vector &x0, +// Real del, +// Vector &y0, +// Vector &y1, +// Vector &yc, +// Vector &pwa, +// std::ostream &outStream) const { +// // Solve ||P(t*x0 + (1-t)*(x-x0))-x0|| = del using Brent's method +// const Real zero(0), half(0.5), one(1), two(2), three(3); +// const Real eps(ROL_EPSILON()), tol0(1e1*eps), fudge(1.0-1e-2*sqrt(eps)); +// Real f0(0), f1(0), fc(0), u0(0), u1(0), uc(0), t0(1), t1(0), tc(0), d1(1), d2(1), tol(1); +// Real p(0), q(0), r(0), s(0), m(0); +// int cnt(state_->nproj); +// y0.set(x); +// proj_->project(y0,outStream); state_->nproj++; +// pwa.set(y0); pwa.axpy(-one,x0); +// f0 = pwa.norm(); +// if (f0 <= del) { +// x.set(y0); +// return; +// } +// +// // Bracketing +// t1 = static_cast(1e-1); +// f1 = one+del; +// while (f1 >= del) { +// t1 *= static_cast(5e-2); +// y1.set(x); y1.scale(t1); y1.axpy(one-t1,x0); +// proj_->project(y1,outStream); state_->nproj++; +// pwa.set(y1); pwa.axpy(-one,x0); +// f1 = pwa.norm(); +// } +// u1 = (one-t1)/t1; +// +// // Brents +// uc = u0; tc = t0; fc = f0; yc.set(y0); +// d1 = u1-u0; d2 = d1; +// int code = 0; +// while (true) { +// if (std::abs(fc-del) < std::abs(f1-del)) { +// u0 = u1; u1 = uc; uc = u0; +// t0 = t1; t1 = tc; tc = t0; +// f0 = f1; f1 = fc; fc = f0; +// y0.set(y1); y1.set(yc); yc.set(y0); +// } +// tol = two*eps*abs(u1) + half*tol0; +// m = half*(uc - u1); +// if (std::abs(m) <= tol) { code = 1; break; } +// if ((f1 >= fudge*del && f1 <= del)) break; +// if (std::abs(d1) < tol || std::abs(f0-del) <= std::abs(f1-del)) { +// d1 = m; d2 = d1; +// } +// else { +// s = (f1-del)/(f0-del); +// if (u0 == uc) { +// p = two*m*s; +// q = one-s; +// } +// else { +// q = (f0-del)/(fc-del); +// r = (f1-del)/(fc-del); +// p = s*(two*m*q*(q-r)-(u1-u0)*(r-one)); +// q = (q-one)*(r-one)*(s-one); +// } +// if (p > zero) q = -q; +// else p = -p; +// s = d1; +// d1 = d2; +// if (two*p < three*m*q-std::abs(tol*q) && p < std::abs(half*s*q)) { +// d2 = p/q; +// } +// else { +// d1 = m; d2 = d1; +// } +// } +// u0 = u1; t0 = t1; f0 = f1; y0.set(y1); +// if (std::abs(d2) > tol) u1 += d2; +// else if (m > zero) u1 += tol; +// else u1 -= tol; +// t1 = one/(one+u1); +// y1.set(x); y1.scale(t1); y1.axpy(one-t1,x0); +// proj_->project(y1,outStream); state_->nproj++; +// pwa.set(y1); pwa.axpy(-one,x0); +// f1 = pwa.norm(); +// if ((f1 > del && fc > del) || (f1 <= del && fc <= del)) { +// uc = u0; tc = t0; fc = f0; yc.set(y0); +// d1 = u1-u0; d2 = d1; +// } +// } +// if (code==1 && f1>del) x.set(yc); +// else x.set(y1); +// if (verbosity_ > 1) { +// outStream << std::endl; +// outStream << " Trust-Region Subproblem Projection" << std::endl; +// outStream << " Number of polyhedral projections: " << state_->nproj-cnt << std::endl; +// if (code == 1 && f1 > del) { +// outStream << " Multiplier: " << uc << std::endl; +// outStream << " Transformed Multiplier: " << tc << std::endl; +// outStream << " Dual Residual: " << fc-del << std::endl; +// } +// else { +// outStream << " Multiplier: " << u1 << std::endl; +// outStream << " Transformed Multiplier: " << t1 << std::endl; +// outStream << " Dual Residual: " << f1-del << std::endl; +// } +// outStream << " Exit Code: " << code << std::endl; +// outStream << std::endl; +// } +//} + +// RIDDERS' METHOD FOR TRUST-REGION PROJECTION +//template +//void TrustRegionSPGAlgorithm::dproj(Vector &x, +// const Vector &x0, +// Real del, +// Vector &y, +// Vector &y1, +// Vector &yc, +// Vector &p, +// std::ostream &outStream) const { +// // Solve ||P(t*x0 + (1-t)*(x-x0))-x0|| = del using Ridder's method +// const Real half(0.5), one(1), tol(1e1*ROL_EPSILON()); +// const Real fudge(1.0-1e-2*std::sqrt(ROL_EPSILON())); +// Real e0(0), e1(0), e2(0), e(0), a0(0), a1(0.5), a2(1), a(0); +// int cnt(state_->nproj); +// y.set(x); +// proj_->project(y,outStream); state_->nproj++; +// p.set(y); p.axpy(-one,x0); +// e2 = p.norm(); +// if (e2 <= del) { +// x.set(y); +// return; +// } +// bool code = 1; +// while (a2-a0 > tol) { +// a1 = half*(a0+a2); +// y.set(x); y.scale(a1); y.axpy(one-a1,x0); +// proj_->project(y,outStream); state_->nproj++; +// p.set(y); p.axpy(-one,x0); +// e1 = p.norm(); +// if (e1 >= fudge*del && e1 <= del) break; +// a = a1-(a1-a0)*(e1-del)/std::sqrt((e1-del)*(e1-del)-(e0-del)*(e2-del)); +// y.set(x); y.scale(a); y.axpy(one-a,x0); +// proj_->project(y,outStream); state_->nproj++; +// p.set(y); p.axpy(-one,x0); +// e = p.norm(); +// if (e < fudge*del) { +// if (e1 < fudge*del) { e0 = (a < a1 ? e1 : e); a0 = (a < a1 ? a1 : a); } +// else { e0 = e; a0 = a; e2 = e1; a2 = a1; }; +// } +// else if (e > del) { +// if (e1 < fudge*del) { e0 = e1; a0 = a1; e2 = e; a2 = a; } +// else { e2 = (a < a1 ? e : e1); a2 = (a < a1 ? a : a1); } +// } +// else { +// code = 0; +// break; // Exit if fudge*del <= snorm <= del +// } +// } +// x.set(y); +// if (verbosity_ > 1) { +// outStream << std::endl; +// outStream << " Trust-Region Subproblem Projection" << std::endl; +// outStream << " Number of polyhedral projections: " << state_->nproj-cnt << std::endl; +// outStream << " Transformed Multiplier: " << a1 << std::endl; +// outStream << " Dual Residual: " << e1-del << std::endl; +// outStream << " Exit Code: " << code << std::endl; +// outStream << std::endl; +// } +//} + +template +void TrustRegionAlgorithm::writeHeader( std::ostream& os ) const { + std::stringstream hist; + if (verbosity_ > 1) { + hist << std::string(114,'-') << std::endl; + hist << " SPG trust-region method status output definitions" << std::endl << std::endl; + hist << " iter - Number of iterates (steps taken)" << std::endl; + hist << " value - Objective function value" << std::endl; + hist << " gnorm - Norm of the gradient" << std::endl; + hist << " snorm - Norm of the step (update to optimization vector)" << std::endl; + hist << " delta - Trust-Region radius" << std::endl; + hist << " #sval - Number of times the smooth objective function was evaluated" << std::endl; + hist << " #nval - Number of times the nonsmooth objective function was evaluated" << std::endl; + hist << " #grad - Number of times the gradient was computed" << std::endl; + hist << " #hess - Number of times the Hessian was applied" << std::endl; + hist << " #prox - Number of times the proximal operator was computed" << std::endl; + hist << std::endl; + hist << " tr_flag - Trust-Region flag" << std::endl; + for( int flag = TRUtils::SUCCESS; flag != TRUtils::UNDEFINED; ++flag ) { + hist << " " << NumberToString(flag) << " - " + << TRUtils::ETRFlagToString(static_cast(flag)) << std::endl; + } + hist << std::endl; + hist << " iterSPG - Number of Spectral Projected Gradient iterations" << std::endl << std::endl; + hist << " flagSPG - Trust-Region Spectral Projected Gradient flag" << std::endl; + hist << " 0 - Converged" << std::endl; + hist << " 1 - Iteration Limit Exceeded" << std::endl; + hist << std::string(114,'-') << std::endl; + } + hist << " "; + hist << std::setw(6) << std::left << "iter"; + hist << std::setw(15) << std::left << "value"; + hist << std::setw(15) << std::left << "gnorm"; + hist << std::setw(15) << std::left << "snorm"; + hist << std::setw(15) << std::left << "delta"; + hist << std::setw(10) << std::left << "#sval"; + hist << std::setw(10) << std::left << "#nval"; + hist << std::setw(10) << std::left << "#grad"; + hist << std::setw(10) << std::left << "#hess"; + hist << std::setw(10) << std::left << "#prox"; + hist << std::setw(10) << std::left << "tr_flag"; + hist << std::setw(10) << std::left << "iterSPG"; + hist << std::setw(10) << std::left << "flagSPG"; + hist << std::endl; + os << hist.str(); +} + +template +void TrustRegionAlgorithm::writeName( std::ostream& os ) const { + std::stringstream hist; + hist << std::endl << "SPG Trust-Region Method (Type P)" << std::endl; + os << hist.str(); +} + +template +void TrustRegionAlgorithm::writeOutput( std::ostream& os, bool write_header ) const { + std::stringstream hist; + hist << std::scientific << std::setprecision(6); + if ( state_->iter == 0 ) writeName(os); + if ( write_header ) writeHeader(os); + if ( state_->iter == 0 ) { + hist << " "; + hist << std::setw(6) << std::left << state_->iter; + hist << std::setw(15) << std::left << state_->value; + hist << std::setw(15) << std::left << state_->gnorm; + hist << std::setw(15) << std::left << "---"; + hist << std::setw(15) << std::left << state_->searchSize; + hist << std::setw(10) << std::left << state_->nsval; + hist << std::setw(10) << std::left << state_->nnval; + hist << std::setw(10) << std::left << state_->ngrad; + hist << std::setw(10) << std::left << nhess_; + hist << std::setw(10) << std::left << state_->nprox; + hist << std::setw(10) << std::left << "---"; + hist << std::setw(10) << std::left << "---"; + hist << std::setw(10) << std::left << "---"; + hist << std::endl; + } + else { + hist << " "; + hist << std::setw(6) << std::left << state_->iter; + hist << std::setw(15) << std::left << state_->value; + hist << std::setw(15) << std::left << state_->gnorm; + hist << std::setw(15) << std::left << state_->snorm; + hist << std::setw(15) << std::left << state_->searchSize; + hist << std::setw(10) << std::left << state_->nsval; + hist << std::setw(10) << std::left << state_->nnval; + hist << std::setw(10) << std::left << state_->ngrad; + hist << std::setw(10) << std::left << nhess_; + hist << std::setw(10) << std::left << state_->nprox; + hist << std::setw(10) << std::left << TRflag_; + hist << std::setw(10) << std::left << SPiter_; + hist << std::setw(10) << std::left << SPflag_; + hist << std::endl; + } + os << hist.str(); +} + +} // namespace TypeP +} // namespace ROL + +#endif diff --git a/packages/rol/test/algorithm/TypeP/CMakeLists.txt b/packages/rol/test/algorithm/TypeP/CMakeLists.txt index 973289b4b084..f75e280f8510 100644 --- a/packages/rol/test/algorithm/TypeP/CMakeLists.txt +++ b/packages/rol/test/algorithm/TypeP/CMakeLists.txt @@ -26,6 +26,16 @@ TRIBITS_ADD_EXECUTABLE_AND_TEST( ADD_DIR_TO_NAME ) +TRIBITS_ADD_EXECUTABLE_AND_TEST( + TrustRegion + SOURCES test_04.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + TRIBITS_COPY_FILES_TO_BINARY_DIR( TypePTestDataCopy diff --git a/packages/rol/test/algorithm/TypeP/test_04.cpp b/packages/rol/test/algorithm/TypeP/test_04.cpp new file mode 100644 index 000000000000..21fd979fdb25 --- /dev/null +++ b/packages/rol/test/algorithm/TypeP/test_04.cpp @@ -0,0 +1,185 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +/*! \file test_03.cpp + \brief Validate iPiano algorithm. +*/ + +#include "ROL_TypeP_TrustRegionAlgorithm.hpp" +#include "ROL_StdObjective.hpp" +#include "ROL_l1Objective.hpp" +#include "ROL_Stream.hpp" +#include "Teuchos_GlobalMPISession.hpp" + +template +class QuadraticTypeP_Test01 : public ROL::StdObjective { +private: + int dim_; + std::vector a_, b_; + +public: + QuadraticTypeP_Test01(int dim) : dim_(dim) { + a_.resize(dim); + b_.resize(dim); + for (int i = 0; i < dim; ++i) { + a_[i] = static_cast(5)*static_cast(rand())/static_cast(RAND_MAX); + b_[i] = static_cast(20)*static_cast(rand())/static_cast(RAND_MAX) - static_cast(10); + } + } + + Real value(const std::vector &x, Real &tol) { + Real val(0); + for (int i = 0; i < dim_; ++i) + val += static_cast(0.5)*a_[i]*x[i]*x[i] + b_[i]*x[i]; + return val; + } + + void gradient(std::vector &g, const std::vector &x, Real &tol) { + for (int i = 0; i < dim_; ++i) + g[i] = a_[i]*x[i] + b_[i]; + } + + void hessVec(std::vector &hv, const std::vector &v, const std::vector &x, Real &tol) { + for (int i = 0; i < dim_; ++i) + hv[i] = a_[i]*v[i]; + } + + void getSolution(std::vector &x, const std::vector &wts, const std::vector &y) const { + for (int i = 0; i < dim_; ++i) + x[i] = (std::min(wts[i], std::max(-wts[i], a_[i]*y[i] + b_[i])) - b_[i]) / a_[i]; + } +}; + +typedef double RealT; + +int main(int argc, char *argv[]) { + + Teuchos::GlobalMPISession mpiSession(&argc, &argv); + + // This little trick lets us print to std::cout only if a + // (dummy) command-line argument is provided. + int iprint = argc - 1; + ROL::Ptr outStream; + ROL::nullstream bhs; // outputs nothing + if (iprint > 0) + outStream = ROL::makePtrFromRef(std::cout); + else + outStream = ROL::makePtrFromRef(bhs); + + int errorFlag = 0; + + try { + RealT tol = 1e2*std::sqrt(ROL::ROL_EPSILON()); + + ROL::ParameterList list; + list.sublist("General").set("Output Level",iprint); + list.sublist("Step").set("Type","iPiano"); + list.sublist("Status Test").set("Gradient Tolerance",1e-7); + list.sublist("Status Test").set("Constraint Tolerance",1e-8); + list.sublist("Status Test").set("Step Tolerance",1e-12); + list.sublist("Status Test").set("Iteration Limit", 10000); + + int dim = 5; + ROL::Ptr> sol, wts, y; + ROL::Ptr> sobj; + ROL::Ptr> nobj; + ROL::Ptr> algo; + std::vector data; + RealT err(0); + + *outStream << std::endl << "Random Diagonal LASSO Test Problem" << std::endl << std::endl; + ROL::Ptr> wtsP = ROL::makePtr>(dim); + ROL::Ptr> yP = ROL::makePtr>(dim); + wts = ROL::makePtr>(wtsP); + y = ROL::makePtr>(yP); + sol = ROL::makePtr>(dim); + wts->randomize(static_cast(0),static_cast(1)); + y->randomize(static_cast(-5),static_cast(5)); + sol->zero(); + + nobj = ROL::makePtr>(wts,y); + sobj = ROL::makePtr>(dim); + + // Check derivatives of smooth function + ROL::Ptr> xd = sol->clone(); + xd->randomize(-1.0,1.0); + ROL::Ptr> yd = sol->clone(); + yd->randomize(-1.0,1.0); + ROL::Ptr> zd = sol->clone(); + zd->randomize(-1.0,1.0); + sobj->checkGradient(*xd,*yd,true,*outStream); + sobj->checkHessVec(*xd,*yd,true,*outStream); + sobj->checkHessSym(*xd,*yd,*zd,true,*outStream); + + algo = ROL::makePtr>(list); + algo->run(*sol,*sobj,*nobj,*outStream); + + std::vector xstar(dim); + sobj->getSolution(xstar, *wtsP, *yP); + data = *ROL::staticPtrCast>(sol)->getVector(); + *outStream << " Result: "; + for (int i = 0; i < dim; ++i) { + *outStream << " x" << i+1 << " = " << data[i]; + err = std::max(err,std::abs(data[i]-xstar[i])); + } + *outStream << std::endl; + *outStream << " Truth: "; + for (int i = 0; i < dim; ++i) { + *outStream << " x" << i+1 << " = " << xstar[i]; + } + *outStream << std::endl; + *outStream << " Max-Error = " << err << std::endl; + errorFlag += (err > tol ? 1 : 0); + } + catch (std::logic_error& err) { + *outStream << err.what() << "\n"; + errorFlag = -1000; + }; // end try + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return 0; +} From 33cbd8a769b69f5cb48d1cae69722722bf735fb6 Mon Sep 17 00:00:00 2001 From: gvonwin Date: Thu, 29 Dec 2022 18:01:11 -0700 Subject: [PATCH 26/65] Added ROL::ChainRuleObjective which creates an objective composed from an f(y) with y = g(x), where f is a ROL::Objective and g is a ROL::Constraint that defines the map and its derivatives. Also added a test to verify ChainRuleObjective's methods --- .../objective/ROL_ChainRuleObjective.hpp | 165 ++++++++++++++++ packages/rol/test/function/CMakeLists.txt | 10 +- packages/rol/test/function/test_18.cpp | 179 ++++++++++++++++++ 3 files changed, 353 insertions(+), 1 deletion(-) create mode 100644 packages/rol/src/function/objective/ROL_ChainRuleObjective.hpp create mode 100644 packages/rol/test/function/test_18.cpp diff --git a/packages/rol/src/function/objective/ROL_ChainRuleObjective.hpp b/packages/rol/src/function/objective/ROL_ChainRuleObjective.hpp new file mode 100644 index 000000000000..bd66d8ac38f6 --- /dev/null +++ b/packages/rol/src/function/objective/ROL_ChainRuleObjective.hpp @@ -0,0 +1,165 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +#ifndef ROL_CHAIN_RULE_OBJECTIVE_HPP +#define ROL_CHAIN_RULE_OBJECTIVE_HPP + +#include "ROL_Objective.hpp" +#include "ROL_Constraint.hpp" + +/** @ingroup func_group + \class ROL::ChainRuleObjective + \brief Defines an objective of the form f(g(x)) where + + \f$g:\mathcal{X}\to\mathcal{Y}\f$ and \f$f:\mathcal{Y}\to\mathbb{R}\f$ + + It is assumed that both $f$ and $g$ are twice differentiable and that + the mapping performed by \f$g\f$ is implemented by a ROL::Constraint, + while a ROL::Objective implements the mapping performed by \f$f\f$. + +--- +*/ + + +namespace ROL { + +template +class ChainRuleObjective : public ROL::Objective { +public: + + /** \brief Constructor + @param[in] obj is the objective function that performs the mapping \f$f:\mathcal{Y}\to\mathbb{R}\f$ + @param[in] con is the constraint function that performs the mapping \f$g:\mathcal{X}\to\mathbb{Y}\f$ + @param[in] x is an optimization space vector (\f$x\in\mathcal{X}\f$) provided for allocating memory for intermediate computations + @param[in] is a constraint space dual vector (\f$l\in\mathcal{Y}^\ast\f$) provided for allocating memory for intermediate computations + */ + ChainRuleObjective( const Ptr>& obj, + const Ptr>& con, + const Vector& x, + const Vector& l ) + : obj_(obj), con_(con), g_(l.clone()), y_(l.dual().clone()), Jv_(l.dual().clone()), + HJv_(l.clone()), JtHJv_(x.dual().clone()), tol_(0) {} + + virtual ~ChainRuleObjective() = default; + + /** \brief Update objective function. + + This function updates the objective function at new iterations. + @param[in] x is the new iterate. + @param[in] type is the type of update requested. + @param[in] iter is the outer algorithm iterations count. + */ + virtual void update( const Vector &x, UpdateType type, int iter = -1 ) { + con_->update(x,type,iter); + con_->value(*y_,x,tol_); + obj_->update(*y_,type,iter); + } + + /** \brief Update objective function. + + This function updates the objective function at new iterations. + @param[in] x is the new iterate. + @param[in] flag is true if the iterate has changed. + @param[in] iter is the outer algorithm iterations count. + */ + virtual void update( const Vector &x, bool flag = true, int iter = -1 ) { + con_->update(x,flag,iter); + con_->value(*y_,x,tol_); + obj_->update(*y_,flag,iter); + } + + /** \brief Compute value. + + This function returns the objective function value. + @param[in] x is the current iterate. + @param[in] tol is a tolerance for inexact objective function computation. + */ + virtual Real value( const Vector &x, Real &tol ) { + con_->value(*y_,x,tol); + return obj_->value(*y_,tol); + } + + /** \brief Compute gradient. + + This function returns the objective function gradient. + @param[out] g is the gradient. + @param[in] x is the current iterate. + @param[in] tol is a tolerance for inexact objective function computation. + + */ + virtual void gradient( Vector &g, const Vector &x, Real &tol ) { + con_->value(*y_,x,tol); + obj_->gradient(*g_,*y_,tol); + con_->applyAdjointJacobian(g,*g_,x,tol); + } + + /** \brief Apply Hessian approximation to vector. + + This function applies the Hessian of the objective function to the vector \f$v\f$. + @param[out] hv is the the action of the Hessian on \f$v\f$. + @param[in] v is the direction vector. + @param[in] x is the current iterate. + @param[in] tol is a tolerance for inexact objective function computation. + */ + virtual void hessVec( Vector &hv, const Vector &v, const Vector &x, Real &tol ) { + con_->value(*y_,x,tol); + obj_->gradient(*g_,*y_,tol); + con_->applyJacobian(*Jv_,v,x,tol); + obj_->hessVec(*HJv_,*Jv_,*y_,tol); + con_->applyAdjointJacobian(*JtHJv_,*HJv_,x,tol); + con_->applyAdjointHessian(hv,*g_,v,x,tol); + hv.plus(*JtHJv_); + } + +private: + + const Ptr> obj_; + const Ptr> con_; + Ptr> g_, y_, Jv_, HJv_, JtHJv_; + Real tol_; + +}; // class ChainRuleObjective + +} // namespace ROL + +#endif // ROL_CHAIN_RULE_OBJECTIVE_HPP diff --git a/packages/rol/test/function/CMakeLists.txt b/packages/rol/test/function/CMakeLists.txt index 6ad2c6035b23..22aa23c105df 100644 --- a/packages/rol/test/function/CMakeLists.txt +++ b/packages/rol/test/function/CMakeLists.txt @@ -147,10 +147,18 @@ TRIBITS_ADD_EXECUTABLE_AND_TEST( ADD_DIR_TO_NAME ) +TRIBITS_ADD_EXECUTABLE_AND_TEST( + ChainRuleObjectiveCheck + SOURCES test_18.cpp + ARGS PrintItAll + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + TRIBITS_COPY_FILES_TO_BINARY_DIR( BinaryConstraintDataCopy SOURCE_FILES binary_constraint.xml SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" DEST_DIR "${CMAKE_CURRENT_BINARY_DIR}" - ) \ No newline at end of file + ) diff --git a/packages/rol/test/function/test_18.cpp b/packages/rol/test/function/test_18.cpp new file mode 100644 index 000000000000..ad54d38333f9 --- /dev/null +++ b/packages/rol/test/function/test_18.cpp @@ -0,0 +1,179 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +/*! \file test_18.cpp + \brief Test ChainRuleObjective class + + Compose the objective \f$f(y)\f$ where \f$y = g(x)\f$ with + + \f[ + y_1 &= g_1(x) &= x_1^2 + x_2^2 + x_3^2 + x_4^2 + x_5^2 - 10 \\ + y_2 &= g_2(x) &= x_2*x_3 - 5*x_4*x_5 \\ + y_3 &= g_3(x) &= x_1^3 + x_2^3 + 1 + \f] + + and + + \f[ + f(\mathbf{y}) = \mathbf{y}^\top\mathbf{y} + + \frac{1}{4}(\mathbf{k}^\top \mathbf{y})^2 + + \frac{1}{16}(\mathbf{k}^\top \mathbf{y})^4 + \f] + Where \f$\mathbf{k}=(1,\cdots,n)\f$ +*/ + +#include "ROL_RandomVector.hpp" +#include "ROL_StdVector.hpp" +#include "ROL_ChainRuleObjective.hpp" + +#include "ROL_Stream.hpp" +#include "Teuchos_GlobalMPISession.hpp" + +#include "ROL_SimpleEqConstrained.hpp" +#include "ROL_Zakharov.hpp" + + +int main(int argc, char *argv[]) { + + using RealT = double; + using VectorT = ROL::StdVector; + using ObjectiveT = ROL::ZOO::Objective_Zakharov; + using ConstraintT = ROL::ZOO::EqualityConstraint_SimpleEqConstrained; + + Teuchos::GlobalMPISession mpiSession(&argc, &argv); + + // This little trick lets us print to std::cout only if a (dummy) command-line argument is provided. + int iprint = argc - 1; + ROL::Ptr outStream; + ROL::nullstream bhs; // outputs nothing + if (iprint > 0) + outStream = ROL::makePtrFromRef(std::cout); + else + outStream = ROL::makePtrFromRef(bhs); + + // Save the format state of the original std::cout. + ROL::nullstream oldFormatState; + oldFormatState.copyfmt(std::cout); + +// RealT errtol = std::sqrt(ROL::ROL_THRESHOLD()); + + int errorFlag = 0; + + // *** Test body. + + try { + + uint x_dim = 5; // Constraint domain space dimension + uint y_dim = 3; // Constraint range space dimension and objective domain space dimension + + + // Make a Zakharov objective function f(y) + auto k_ptr = ROL::makePtr(y_dim); + auto& k = *k_ptr; + k[0] = 1; + k[1] = 2; + k[2] = 3; + + auto x = VectorT(x_dim); + auto l = VectorT(y_dim); + + auto obj_ptr = ROL::makePtr(k_ptr); + auto con_ptr = ROL::makePtr(); + + VectorT v(x_dim), g(x_dim), hv(x_dim), u(x_dim); + + auto obj = ROL::ChainRuleObjective(obj_ptr,con_ptr,x,l); + + ROL::RandomizeVector(x); + ROL::RandomizeVector(v); + ROL::RandomizeVector(u); + + RealT tol = std::sqrt(ROL::ROL_EPSILON()); + + auto result_1 = obj.checkGradient(x,v,true,*outStream,7,4); + + bool gradient_passed = false; + + for( auto& row : result_1 ) { + if(row[3] < tol) { + gradient_passed = true; + break; + } + } + + errorFlag += (!gradient_passed); + + auto result_2 = obj.checkHessVec(x,hv,v,true,*outStream,7,4); + + bool hessVec_passed = false; + + for( auto& row : result_2 ) { + if(row[3] < tol) { + hessVec_passed = true; + break; + } + } + + errorFlag += (!hessVec_passed) << 1; + + auto result_3 = obj.checkHessSym(x,hv,v,u,true,*outStream); + auto hessSym_passed = (result_3[2] < tol); + + errorFlag += (!hessSym_passed) << 2; + + } + catch (std::logic_error& err) { + *outStream << err.what() << "\n"; + errorFlag = -1000; + }; // end try + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return 0; + + +} + From 70b9abbc99ebb7a386b20ecd895cc32d44dec88f Mon Sep 17 00:00:00 2001 From: Bobby Date: Wed, 4 Jan 2023 14:01:13 -0700 Subject: [PATCH 27/65] spg still not working --- .../TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp | 36 ++- .../ROL_TypeP_TrustRegionAlgorithm_Def.hpp | 248 +++++++++--------- packages/rol/test/algorithm/TypeP/test_04.cpp | 8 +- 3 files changed, 160 insertions(+), 132 deletions(-) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp index b1361d2b42f7..0428274309c6 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp @@ -130,6 +130,7 @@ class TrustRegionAlgorithm : public TypeP::Algorithm { void initialize(Vector &x, const Vector &g, + Real ftol, Objective &sobj, Objective &nobj, Vector &px, @@ -153,12 +154,14 @@ class TrustRegionAlgorithm : public TypeP::Algorithm { void writeOutput( std::ostream& os, bool write_header = false ) const override; private: - void initialize(Vector &x, + /*void initialize(Vector &x, const Vector &g, Real ftol, Objective &sobj, Objective &nobj, - std::ostream &outStream = std::cout); + Vector &px, + Vector &dg, + std::ostream &outStream = std::cout);*/ Real computeValue(Real inTol, Real &outTol, @@ -167,11 +170,12 @@ class TrustRegionAlgorithm : public TypeP::Algorithm { int iter, const Vector &x, const Vector &xold, - Objective &sobj, - Objective &nobj); + Objective &obj); Real computeGradient(const Vector &x, Vector &g, + Vector &px, + Vector &dg, Vector &pwa, Real del, Objective &sobj, @@ -199,30 +203,47 @@ class TrustRegionAlgorithm : public TypeP::Algorithm { // dwa -- Dual working array, stores Hessian applied to step // dwa1 -- Dual working array Real dcauchy(Vector &s, - Real &alpha, Real &q, + Real &alpha, + Real &sval, + Real &nval, + Real &pRed, const Vector &x, const Vector &g, + Vector &px, const Real del, TrustRegionModel_U &model, + Objective &nobj, Vector &dwa, Vector &dwa1, std::ostream &outStream = std::cout); void dpsg_simple(Vector &y, - Real &q, Vector &gmod, + Real &sval, + Real &nval, + Real &pRed, + Vector &gmod, const Vector &x, + Vector &px, + Vector &dg, Real del, TrustRegionModel_U &model, + Objective &nobj, Vector &pwa, Vector &pwa1, Vector &dwa, std::ostream &outStream = std::cout); void dpsg(Vector &y, - Real &q, Vector &gmod, + Real &sval, + Real &nval, + Real &pRed, + Vector &gmod, + Vector &px, + Vector &dg, const Vector &x, Real del, TrustRegionModel_U &model, + Objective &nobj, Vector &ymin, Vector &pwa, Vector &pwa1, @@ -236,6 +257,7 @@ class TrustRegionAlgorithm : public TypeP::Algorithm { void dproj(Vector &x, const Vector &x0, Real del, + Objective &nobj, Vector &y0, Vector &y1, Vector &yc, diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp index e0c7beda10ad..c28cfe799bbe 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp @@ -69,7 +69,7 @@ TrustRegionAlgorithm::TrustRegionAlgorithm(ParameterList &list, TRsafe_ = trlist.get("Safeguard Size", 100.0); eps_ = TRsafe_*ROL_EPSILON(); interpRad_ = trlist.get("Use Radius Interpolation", false); - verbosity_ = trlist.sublist("General").get("Output Level", 0); + verbosity_ = trlist.sublist("General").get("Output Level", 0); initProx_ = trlist.get("Apply Prox to Initial Guess", false); //change here? // Nonmonotone Parameters storageNM_ = trlist.get("Nonmonotone Storage Size", 0); @@ -133,32 +133,30 @@ TrustRegionAlgorithm::TrustRegionAlgorithm(ParameterList &list, template void TrustRegionAlgorithm::initialize(Vector &x, - const Vector &g, - Real ftol, - Objective &sobj, - Objective &nobj, - Vector &px, - Vector &dg, - std::ostream &outStream) { - //const Real one(1); + const Vector &g, + Real ftol, + Objective &sobj, + Objective &nobj, + Vector &px, + Vector &dg, + std::ostream &outStream) { + const Real one(1); // Initialize data TypeP::Algorithm::initialize(x,g); nhess_ = 0; // Update approximate gradient and approximate objective function. if (initProx_){ - nobj.prox(*state_->iterateVec, x, t0_, ftol); state_->nprox++; - x.set(*state_->iterateVec); + nobj.prox(*state_->iterateVec,x,t0_, ftol); state_->nprox++; + x.set(*state_->iterateVec); } sobj.update(x,UpdateType::Initial,state_->iter); state_->svalue = sobj.value(x,ftol); state_->nsval++; nobj.update(x, UpdateType::Initial,state_->iter); state_->nvalue = nobj.value(x,ftol); state_->nnval++; state_->value = state_->svalue + state_->nvalue; - //obj.gradient(*state_->gradientVec,x,ftol);//make sure below sets dg to dual gradient state_->gnorm = computeGradient(x,*state_->gradientVec,px,dg,*state_->stepVec,state_->searchSize,sobj,nobj,outStream); state_->ngrad++; - //dg.set(state_->gradientVect->dual()); - //pgstep(px, *state_->stepVec, nobj, x, dg, t0_, ftol); + //state_->gnorm = state_->stepVec->norm()/t0_; state_->snorm = ROL_INF(); // Normalize initial CP step length @@ -206,19 +204,18 @@ Real TrustRegionAlgorithm::computeGradient(const Vector &x, Objective &nobj, std::ostream &outStream) const { Real gnorm(0); - if ( useInexact_[1] ) { - const Real one(1); + const Real one(1); + if ( useInexact_[1] ) { Real gtol1 = scale0_*del; Real gtol0 = gtol1 + one; while ( gtol0 > gtol1 ) { - obj.gradient(g,x,gtol1); + sobj.gradient(g,x,gtol1);//px otherwise nothing would change? state_->ngrad++; //gnorm = TypeP::Algorithm::optimalityCriterion(x,g,pwa,outStream); - //[grad, gerr] = problem.obj_smooth.gradient(x, gtol); cnt.ngrad = cnt.ngrad + 1; - dg.set(state_->g->dual()); - pgstep(px, step, nobj, x, dg, one, gtol) // change gtol? one or ocScale? + dg.set(g.dual()); + pgstep(px, step, nobj, x, dg, t0_, gtol1); // change gtol? one or ocScale? state_->nprox++; - gnorm = step->norm() / one; + gnorm = step.norm() / t0_; gtol0 = gtol1; gtol1 = scale0_*std::min(gnorm,del); @@ -226,12 +223,13 @@ Real TrustRegionAlgorithm::computeGradient(const Vector &x, } else { Real gtol = std::sqrt(ROL_EPSILON()); - obj.gradient(g,x,gtol); + sobj.gradient(g,x,gtol); state_->ngrad++; + dg.set(g.dual()); //gnorm = TypeP::Algorithm::optimalityCriterion(x,g,pwa,outStream); - pgstep(px, step, nobj, x, dg, one, gtol); + pgstep(px, step, nobj, x, dg, t0_, gtol); state_->nprox++; - gnorm = step->norm() / one; + gnorm = step.norm() / t0_; } return gnorm; } @@ -245,14 +243,16 @@ void TrustRegionAlgorithm::run(Vector &x, const Real zero(0), one(1); //Real tol0 = std::sqrt(ROL_EPSILON()); Real inTol = static_cast(0.1)*ROL_OVERFLOW(), outTol(inTol); - Real strial(0), ntrial(0), Ftrial(0), pRed(0), rho(1), q(0); + Real strial(0), ntrial(0), Ftrial(0), pRed(0), rho(1); // Initialize trust-region data std::vector output; - initialize(x,g,inTol,sobj,nobj, px, dg, outStream); Ptr> gmod = g.clone(); Ptr> px = x.clone(); - Ptr> dg = g.clone(); - Ptr> pwa1 = x.clone(), pwa2 = x.clone(); + Ptr> dg = x.clone(); + // Initialize Algorithm + initialize(x,g,inTol,sobj,nobj, *px, *dg, outStream); + // Initialize storage vectors + Ptr> pwa1 = x.clone(), pwa2 = x.clone(); Ptr> pwa3 = x.clone(), pwa4 = x.clone(); Ptr> pwa5 = x.clone(), pwa6 = x.clone(); Ptr> pwa7 = x.clone(); @@ -262,33 +262,31 @@ void TrustRegionAlgorithm::run(Vector &x, Real fr(state_->value), fc(state_->value), fmin(state_->value); TRUtils::ETRFlag TRflagNM; int L(0); - // Output if (verbosity_ > 0) writeOutput(outStream,true); while (status_->check(*state_)) { // Build trust-region model - model_->setData(sobj,*state_->iterateVec,*state_->gradientVec);//should only be sobj? + model_->setData(sobj,*state_->iterateVec,*state_->gradientVec); /**** SOLVE TRUST-REGION SUBPROBLEM ****/ - q = state_->sval + state_->nval;//q is mold + //q = state_->svalue + state_->nvalue;//q is no longer used gmod->set(*state_->gradientVec); if (useSimpleSPG_) - dpsg_simple(x,q,pRed,*gmod,*state_->iterateVec,state_->searchSize,*model_,nobj, - *pwa1,*pwa2,*dwa1,outStream);//probably nobj? + dpsg_simple(x,state_->svalue, state_->nvalue,pRed,*gmod,*state_->iterateVec,*px, *dg, state_->searchSize,*model_,nobj, + *pwa1,*pwa2,*dwa1,outStream); else { // Compute Cauchy point (TRON notation: x = x[1]) - dcauchy(*state_->stepVec,alpha_,q,pRed,*state_->iterateVec,//add pred, q is mold - state_->gradientVec->dual(),state_->searchSize, - *model_,*dwa1,*dwa2,outStream); // Solve 1D optimization problem for alpha + Real sval = state_->svalue, nval = state_->nvalue; + dcauchy(*state_->stepVec,alpha_, sval, nval, pRed, *state_->iterateVec,//add pred, q is mold + *dg, *px, state_->searchSize, + *model_, nobj, *dwa1, *dwa2, outStream); // Solve 1D optimization problem for alpha x.plus(*state_->stepVec); // Set x = x[0] + alpha*g - // Model gradient at s = x[1] - x[0] gmod->plus(*dwa1); // hessVec from Cauchy point computation - // Apply SPG starting from the Cauchy point - dpsg(x,q,pRed,*gmod,*state_->iterateVec,state_->searchSize,*model_,nobj, - *pwa1,*pwa2,*pwa3,*pwa4,*pwa5,*pwa6,*pwa7,*dwa1,outStream);//probably nobj + // Apply SPG starting from the Cauchy point->change input + dpsg(x,sval,nval,pRed,*gmod,*px, *dg,*state_->iterateVec,state_->searchSize,*model_,nobj,*pwa1,*pwa2,*pwa3,*pwa4,*pwa5,*pwa6,*pwa7,*dwa1,outStream);//probably nobj } // Update storage and compute predicted reduction @@ -297,20 +295,21 @@ void TrustRegionAlgorithm::run(Vector &x, state_->snorm = state_->stepVec->norm(); // Compute trial objective value - strial = computeValue(inTol,outTol,pRed,state_->svalue,state_->iter,x,*state_->iterateVec,sobj,nobj); - nobj.update(*state_->iterateVec, UpdateType::Trial); - ntrial = nobj.value(*state_->iteratevec,tol); + strial = computeValue(inTol,outTol,pRed,state_->svalue,state_->iter,x,*state_->iterateVec,sobj); + nobj.update(x, UpdateType::Trial); + ntrial = nobj.value(x,outTol); + Ftrial = strial + ntrial; state_->nsval++; state_->nnval++; // Compute ratio of acutal and predicted reduction TRflag_ = TRUtils::SUCCESS; TRUtils::analyzeRatio(rho,TRflag_,state_->value,Ftrial,pRed,eps_,outStream,verbosity_>1); - /*if (useNM_) { + if (useNM_) { TRUtils::analyzeRatio(rhoNM,TRflagNM,fr,Ftrial,pRed+sigmar,eps_,outStream,verbosity_>1); TRflag_ = (rho < rhoNM ? TRflagNM : TRflag_); rho = (rho < rhoNM ? rhoNM : rho ); - }*/ + } // Update algorithm state state_->iter++; @@ -319,10 +318,10 @@ void TrustRegionAlgorithm::run(Vector &x, x.set(*state_->iterateVec); sobj.update(x,UpdateType::Revert,state_->iter); nobj.update(x,UpdateType::Revert,state_->iter); - if (interpRad_ && (rho < zero && TRflag_ != TRUtils::TRNAN)) { //what is this? + if (interpRad_ && (rho < zero && TRflag_ != TRUtils::TRNAN)) { // Negative reduction, interpolate to find new trust-region radius state_->searchSize = TRUtils::interpolateRadius(*state_->gradientVec,*state_->stepVec, - state_->snorm,pRed,state_->value,ftrial,state_->searchSize,gamma0_,gamma1_,eta2_, + state_->snorm,pRed,state_->value,Ftrial,state_->searchSize,gamma0_,gamma1_,eta2_, outStream,verbosity_>1); } else { // Shrink trust-region radius @@ -331,27 +330,26 @@ void TrustRegionAlgorithm::run(Vector &x, } else if ((rho >= eta0_ && TRflag_ != TRUtils::NPOSPREDNEG) || (TRflag_ == TRUtils::POSPREDNEG)) { // Step Accepted - state_->value = strial + ntrial; + state_->value = Ftrial; state_->svalue = strial; state_->nvalue = ntrial; sobj.update(x,UpdateType::Accept,state_->iter); nobj.update(x,UpdateType::Accept,state_->iter); inTol = outTol; - /*if (useNM_) { + if (useNM_) { sigmac += pRed; sigmar += pRed; - if (ftrial < fmin) { fmin = ftrial; fc = fmin; sigmac = zero; L = 0; } + if (Ftrial < fmin) { fmin = Ftrial; fc = fmin; sigmac = zero; L = 0; } else { L++; - if (ftrial > fc) { fc = ftrial; sigmac = zero; } + if (Ftrial > fc) { fc = Ftrial; sigmac = zero; } if (L == storageNM_) { fr = fc; sigmar = sigmac; } } - }*/ + } // Increase trust-region radius if (rho >= eta2_) state_->searchSize = std::min(gamma2_*state_->searchSize, delMax_); // Compute gradient at new iterate dwa1->set(*state_->gradientVec); - //state_->gnorm = computeGradient(x,*state_->gradientVec,px,dg,*state_->stepVec,state_->searchSize,sobj,nobj,outStream); - state_->gnorm = computeGradient(x,*state_->gradientVec,px,dg,*pwa1,state_->searchSize,sobj,nobj,outStream); + state_->gnorm = computeGradient(x,*state_->gradientVec,*px,*dg,*pwa1,state_->searchSize,sobj,nobj,outStream); state_->ngrad++; state_->iterateVec->set(x); // Update secant information in trust-region model @@ -374,18 +372,18 @@ Real TrustRegionNonsmoothAlgorithm::dgpstep(Vector &s, const Vector< s.axpy(static_cast(-1),x); return s.norm(); }*/ - template Real TrustRegionAlgorithm::dcauchy(Vector &s, Real &alpha, - Real &mval, + Real &sval, + Real &nval, Real &pRed, const Vector &x, const Vector &g, Vector &px, const Real del, TrustRegionModel_U &model, - Objective, nobj, + Objective &nobj, Vector &dwa, Vector &dwa1, std::ostream &outStream) { @@ -393,70 +391,76 @@ Real TrustRegionAlgorithm::dcauchy(Vector &s, // const Real zero(0); // Unused Real tol = std::sqrt(ROL_EPSILON()); bool interp = false; - Real gs(0), snorm(0), phiold(0), phinew(0), mold(mval), Qk(0); + Real gs(0), snorm(0), nold(nval), mold(sval+nval), mnew(mold), sold(sval), Qk(0); // Compute s = P(x[0] - alpha g[0]) //snorm = dgpstep(s,g,x,-alpha,outStream); - dwa1.set(g->dual()); //already the dual - pgstep(px, *s, nobj, x, dwa1, alpha, tol); - snorm = s->norm(); //correct? + pgstep(px, s, nobj, x, g, alpha, tol); + snorm = s.norm(); if (snorm > del) { interp = true; } else { - model.hessVec(dwa,s,x,tol); nhess_++;//should rewrite dwa? + model.hessVec(dwa,s,x,tol); nhess_++; gs = s.dot(g); - phinew = nobj.value(px, tol); + nobj.update(px, UpdateType::Trial); + nval = nobj.value(px, tol); state_->nnval++; //q = half * s.dot(dwa.dual()) + gs; - mval = half * s.apply(dwa) + gs + phinew; - Qk = gs + phinew - phiold; - interp = (mval > mold + mu0_*Qk);//what is this? + sval = half * s.apply(dwa) + gs + sold; + mnew = nval + sval; + Qk = gs + nval - nold; + interp = (mnew > mold + mu0_*Qk); } // Either increase or decrease alpha to find approximate Cauchy point int cnt = 0; - if (interp) { + if (interp) {//decrease loop bool search = true; while (search) { - alpha *= interpf_; + alpha *= interpf_; //snorm = dgpstep(s,g,x,-alpha,outStream); - pgstep(px, *s, nobj, x, dwa1, alpha, tol); - snorm = s->norm(); - if (snorm <= del || ) { + pgstep(px, s, nobj, x, g, alpha, tol); + snorm = s.norm(); + if (snorm <= del) { model.hessVec(dwa,s,x,tol); nhess_++; gs = s.dot(g); //q = half * s.dot(dwa.dual()) + gs; - phinew = nobj.value(px, tol); - mval = half * s.apply(dwa) + gs + phinew; - Qk = gs + phinew - phiold; - search = (mval > mold + mu0_*Qk) && (cnt < redlim_); - } - mold = mval; + nobj.update(px, UpdateType::Trial); + nval = nobj.value(px, tol); state_->nnval++; + sval = half * s.apply(dwa) + gs + sold; + mnew = sval + nval; + Qk = gs + nval - nold; + search = ((mnew > mold + mu0_*Qk) && (cnt < redlim_)) ; + } cnt++; } } else { bool search = true; Real alphas = alpha; - Real mvals = mval; - dwa1.set(dwa); + Real mvals = mnew; + dwa1.set(dwa); while (search) { alpha *= extrapf_; //snorm = dgpstep(s,g,x,-alpha,outStream); - pgstep(px, *s, nobj, x, dg, alpha, tol); - if (snorm <= del && cnt < explim_) { + pgstep(px, s, nobj, x, g, alpha, tol); //dwa? + snorm = s.norm(); + printf("%f %f\n", snorm, del); + if (snorm <= del && cnt < explim_){// && mnew < mold + mu0_*Qk) { model.hessVec(dwa,s,x,tol); nhess_++; gs = s.dot(g); - phinew = nobj.value(px, tol); + nobj.update(px, UpdateType::Trial); + nval = nobj.value(px, tol); state_->nnval++; //q = half * s.dot(dwa.dual()) + gs; - mval = half * s.apply(dwa) + gs + phinew; - Qk = gs + phinew - phiold - if (mval <= mold + mu0_*Qk && std::abs(mval-mvals) > qtol_*std::abs(mvals)) { - dwa1.set(dwa); + sval = half * s.apply(dwa) + gs + sold; + Qk = gs + nval - nold; + mnew = sval+nval; + if (mnew <= mold + mu0_*Qk && std::abs(mnew-mvals) > qtol_*std::abs(mvals)) { + dwa1.set(dwa); search = true; alphas = alpha; - mvals = mval; + mvals = mnew; } else { - mval = mvals; + mnew = mvals; dwa.set(dwa1); search = false; } @@ -468,11 +472,11 @@ Real TrustRegionAlgorithm::dcauchy(Vector &s, } alpha = alphas; //snorm = dgpstep(s,g,x,-alpha,outStream); - pgstep(px, *s, nobj, x, dg, alpha, tol); - snorm = s->norm(); + pgstep(px, s, nobj, x, g, alpha, tol);//dwa? + snorm = s.norm(); } - pRed = mval - mold; - if (verbosity_ > 1) { + pRed = mold - mnew; + if (verbosity_ > 1) { outStream << " Cauchy point" << std::endl; outStream << " Step length (alpha): " << alpha << std::endl; outStream << " Step length (alpha*g): " << snorm << std::endl; @@ -486,19 +490,20 @@ Real TrustRegionAlgorithm::dcauchy(Vector &s, template void TrustRegionAlgorithm::dpsg_simple(Vector &y, //x - Real &mval, //mval (formerly q) - Real &pRed, //predicted reduction - Vector &gmod, // state_->gradientVec - const Vector &x, //iterateVect - Vector &px, // px - Vector &dg, // gradient dual? - Real del, - TrustRegionModel_U &model, - Objective nobj, - Vector &pwa, - Vector &pwa1, - Vector &dwa, - std::ostream &outStream) { + Real &sval, + Real &nval, + Real &pRed, //predicted reduction + Vector &gmod, // state_->gradientVec + const Vector &x, //iterateVect + Vector &px, // px + Vector &dg, // gradient dual? + Real del, + TrustRegionModel_U &model, + Objective &nobj, + Vector &pwa, + Vector &pwa1, + Vector &dwa, + std::ostream &outStream) { // Use SPG to approximately solve TR subproblem: // min 1/2 + subject to y\in C, ||y|| \le del // @@ -508,8 +513,7 @@ void TrustRegionAlgorithm::dpsg_simple(Vector &y, //x // g = Current gradient const Real half(0.5), one(1), safeguard(1e2*ROL_EPSILON()); Real tol(std::sqrt(ROL_EPSILON())); - Real alpha(1), alphaMax(1), s0s0(0), ss0(0), sHs(0), lambdaTmp(1), snorm(0), mold(mval); - Real phinew(0), phiold(0); + Real alpha(1), alphaMax(1), s0s0(0), ss0(0), sHs(0), lambdaTmp(1), snorm(0), mold(sval+nval), mnew(mold); pwa1.zero(); // Set y = x @@ -550,13 +554,13 @@ void TrustRegionAlgorithm::dpsg_simple(Vector &y, //x alpha = alphaMax; else alpha = std::min(alphaMax, -gs/sHs); - + // Update model quantities y.axpy(alpha,pwa); // New iterate - phiold = nobj.value(x, tol); - phinew = nobj.value(y, tol); - mval += alpha * (gs + half * alpha * sHs) - phiold + phinew; // Update model value - is this correct? - gmod.axpy(alpha,dwa); // Update model gradient + nval = nobj.value(y, tol); + sval += alpha * (gs + half * alpha * sHs); // Update model value - is this correct? + mnew = sval + nval; + gmod.axpy(alpha,dwa); // Update model gradient pRed = mold - mnew; @@ -606,7 +610,8 @@ void TrustRegionAlgorithm::dpsg(Vector &y, const Vector &x, Real del, TrustRegionModel_U &model, - Vector &ymin, + Objective &nobj, + Vector &ymin, Vector &pwa, Vector &pwa1, Vector &pwa2, @@ -625,10 +630,10 @@ void TrustRegionAlgorithm::dpsg(Vector &y, const Real zero(0), half(0.5), one(1), two(2); //, eps(std::sqrt(ROL_EPSILON())); Real tol(std::sqrt(ROL_EPSILON())); Real alpha(1), sHs(0), alphaTmp(1), mmax(0), mval_min(0), lambdaTmp(1); - Real mold(sval+nval); + Real mold(sval+nval), mval(mold); std::deque mqueue; mqueue.push_back(mold); - if (useNMSP_ && useMin_) { mval_min = mval; ymin.set(y); } + if (useNMSP_ && useMin_) { mval_min = sval+nval; ymin.set(y); } // Compute initial projected gradient norm pwa1.set(gmod.dual()); @@ -642,7 +647,7 @@ void TrustRegionAlgorithm::dpsg(Vector &y, Real coeff = one/gmod.norm(); Real lambda = std::max(lambdaMin_,std::min(coeff,lambdaMax_)); pwa.set(y); pwa.axpy(-lambda,pwa1); // pwa = y - lambda gmod.dual() - dproj(pwa,x,nobj,del,pwa2,pwa3,pwa4,pwa5,outStream); // pwa = P(y - lambda gmod.dual()) + dproj(pwa,x,del,nobj,pwa2,pwa3,pwa4,pwa5,outStream); // pwa = P(y - lambda gmod.dual()) nobj.update(pwa, UpdateType::Trial); Real ntrial = nobj.value(pwa, tol); pwa.axpy(-one,y); // pwa = P(y - lambda gmod.dual()) - y = step @@ -678,12 +683,13 @@ void TrustRegionAlgorithm::dpsg(Vector &y, nobj.update(y, UpdateType::Accept); nval = nobj.value(y, tol); + mval = nval + sval; // Update nonmonotone line search information if (useNMSP_) { if (static_cast(mqueue.size())==maxSize_) mqueue.pop_front(); mqueue.push_back(sval+nval); - if (useMin_ && sval+nval <= qmin) { qmin = sval+nval; ymin.set(y); } + if (useMin_ && mval <= mval_min) { mval_min = mval; ymin.set(y); } } // Compute projected gradient norm @@ -692,7 +698,7 @@ void TrustRegionAlgorithm::dpsg(Vector &y, dproj(pwa,x,del,nobj, pwa2,pwa3,pwa4,pwa5,outStream); pwa.axpy(-one,y); gnorm = pwa.norm(); - pRed = sval+nval - mold; + pRed = mval - mold; if (verbosity_ > 1) { outStream << std::endl; @@ -715,7 +721,7 @@ void TrustRegionAlgorithm::dpsg(Vector &y, gs = gmod.apply(pwa); ss = pwa.dot(pwa); } - if (useNMSP_ && useMin_) { q = qmin; y.set(ymin); } + if (useNMSP_ && useMin_) { mval = mval_min; y.set(ymin); } SPflag_ = (SPiter_==maxit_) ? 1 : 0; } @@ -734,7 +740,7 @@ void TrustRegionAlgorithm::dproj(Vector &x, const Real eps(ROL_EPSILON()), tol0(1e1*eps), fudge(1.0-1e-2*sqrt(eps)); Real f0(0), f1(0), fc(0), t0(0), t1(1), tc(0), d1(1), d2(1), tol(1); Real p(0), q(0), r(0), s(0), m(0); - int cnt(state_->nproj); + int cnt(state_->nprox); nobj.prox(y1, x, one, tol); state_->nprox++; pwa.set(y1); pwa.axpy(-one,x0); f1 = pwa.norm(); @@ -801,7 +807,7 @@ void TrustRegionAlgorithm::dproj(Vector &x, if (verbosity_ > 1) { outStream << std::endl; outStream << " Trust-Region Subproblem Proximity Operator" << std::endl; - outStream << " Number of proxes: " << state_->nproj-cnt << std::endl; + outStream << " Number of proxes: " << state_->nprox-cnt << std::endl; if (code == 1 && f1 > del) { outStream << " Transformed Multiplier: " << tc << std::endl; outStream << " Dual Residual: " << fc-del << std::endl; diff --git a/packages/rol/test/algorithm/TypeP/test_04.cpp b/packages/rol/test/algorithm/TypeP/test_04.cpp index 21fd979fdb25..9f3aeb00aec0 100644 --- a/packages/rol/test/algorithm/TypeP/test_04.cpp +++ b/packages/rol/test/algorithm/TypeP/test_04.cpp @@ -42,7 +42,7 @@ // @HEADER /*! \file test_03.cpp - \brief Validate iPiano algorithm. + \brief Validate Trust Region algorithm. */ #include "ROL_TypeP_TrustRegionAlgorithm.hpp" @@ -113,17 +113,17 @@ int main(int argc, char *argv[]) { ROL::ParameterList list; list.sublist("General").set("Output Level",iprint); - list.sublist("Step").set("Type","iPiano"); + list.sublist("Step").set("Type","Trust Region"); list.sublist("Status Test").set("Gradient Tolerance",1e-7); list.sublist("Status Test").set("Constraint Tolerance",1e-8); list.sublist("Status Test").set("Step Tolerance",1e-12); - list.sublist("Status Test").set("Iteration Limit", 10000); + list.sublist("Status Test").set("Iteration Limit", 1000); int dim = 5; ROL::Ptr> sol, wts, y; ROL::Ptr> sobj; ROL::Ptr> nobj; - ROL::Ptr> algo; + ROL::Ptr> algo; std::vector data; RealT err(0); From c997bf128bdf943d046f7fc7fadd995b32ca4b77 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Thu, 5 Jan 2023 04:57:05 -0700 Subject: [PATCH 28/65] Fixed TypeP Trust Region algorithm. Now SPG subproblem solver works. I haven't touched SPG_simple. Also, performed general clean up. --- .../algorithm/TypeP/ROL_TypeP_Algorithm.hpp | 5 - .../TypeP/ROL_TypeP_Algorithm_Def.hpp | 24 +- .../TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp | 137 +++--- .../ROL_TypeP_TrustRegionAlgorithm_Def.hpp | 451 +++++++++--------- 4 files changed, 285 insertions(+), 332 deletions(-) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm.hpp index e030820a6957..3384540ae7ad 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm.hpp @@ -101,11 +101,6 @@ class Algorithm { Real t, // t = prox parameter Real &tol) const; - /*Real optimalityCriterion(const Vector &x, - const Vector &g, - Vector &primal, - std::ostream &outStream = std::cout) const; -*/ public: virtual ~Algorithm() {} diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm_Def.hpp index 51bcfae761d4..86f97130d81c 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm_Def.hpp @@ -77,12 +77,12 @@ void Algorithm::initialize(const Vector &x, const Vector &g) { } template -void Algorithm::pgstep(Vector &pgiter, //solution of proximal operator - Vector &pgstep, //proximal step pgiter - x - Objective &nobj, //nonsmooth objective function - const Vector &x, //anchor vector - const Vector &dg, //direction - Real t, //Moreau Envelop constant +void Algorithm::pgstep(Vector &pgiter, + Vector &pgstep, + Objective &nobj, + const Vector &x, + const Vector &dg, + Real t, Real &tol) const { pgstep.set(x); pgstep.axpy(-t,dg); @@ -92,18 +92,6 @@ void Algorithm::pgstep(Vector &pgiter, //solution of proximal pgstep.axpy(static_cast(-1),x); } -/*template -Real Algorithm::optimalityCriterion( Vector &pgiter, - Vector &pgstep, - Objective &nobj, - const Vector &x, - const Vector &g, - Real t, - Real &tol) const { - pgstep(pgiter, *pgstep, nobj, x, g, t, tol) - return pgstep.norm()/t; -}*/ - template void Algorithm::setStatusTest(const Ptr> &status, bool combineStatus) { diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp index 0428274309c6..5463c377edb4 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp @@ -117,10 +117,10 @@ class TrustRegionAlgorithm : public TypeP::Algorithm { int updateIter_; Real forceFactor_; - bool initProx_; - Real t0_; + bool initProx_; + Real t0_; - mutable int nhess_; ///< Number of Hessian applications + mutable int nhess_; ///< Number of Hessian applications unsigned verbosity_; ///< Output level (default: 0) bool writeHeader_; ///< Flag to write header at every iteration @@ -128,14 +128,14 @@ class TrustRegionAlgorithm : public TypeP::Algorithm { using TypeP::Algorithm::status_; using TypeP::Algorithm::pgstep; - void initialize(Vector &x, - const Vector &g, - Real ftol, - Objective &sobj, - Objective &nobj, - Vector &px, - Vector &dg, - std::ostream &outStream = std::cout); + void initialize(Vector &x, + const Vector &g, + Real ftol, + Objective &sobj, + Objective &nobj, + Vector &px, + Vector &dg, + std::ostream &outStream = std::cout); public: TrustRegionAlgorithm(ParameterList &list, const Ptr> &secant = nullPtr); @@ -154,14 +154,6 @@ class TrustRegionAlgorithm : public TypeP::Algorithm { void writeOutput( std::ostream& os, bool write_header = false ) const override; private: - /*void initialize(Vector &x, - const Vector &g, - Real ftol, - Objective &sobj, - Objective &nobj, - Vector &px, - Vector &dg, - std::ostream &outStream = std::cout);*/ Real computeValue(Real inTol, Real &outTol, @@ -170,16 +162,16 @@ class TrustRegionAlgorithm : public TypeP::Algorithm { int iter, const Vector &x, const Vector &xold, - Objective &obj); + Objective &obj); Real computeGradient(const Vector &x, Vector &g, - Vector &px, - Vector &dg, + Vector &px, + Vector &dg, Vector &pwa, Real del, Objective &sobj, - Objective &nobj, + Objective &nobj, std::ostream &outStream = std::cout) const; // Compute the projected step s = P(x + alpha*w) - x @@ -202,67 +194,64 @@ class TrustRegionAlgorithm : public TypeP::Algorithm { // model -- Trust region model // dwa -- Dual working array, stores Hessian applied to step // dwa1 -- Dual working array - Real dcauchy(Vector &s, - Real &alpha, - Real &sval, - Real &nval, - Real &pRed, - const Vector &x, - const Vector &g, - Vector &px, - const Real del, - TrustRegionModel_U &model, - Objective &nobj, - Vector &dwa, - Vector &dwa1, - std::ostream &outStream = std::cout); + Real dcauchy(Vector &s, + Real &alpha, + Real &sval, + Real &nval, + const Vector &x, + const Vector &g, + Real del, + TrustRegionModel_U &model, + Objective &nobj, + Vector &px, + Vector &dwa, + Vector &dwa1, + std::ostream &outStream = std::cout); void dpsg_simple(Vector &y, - Real &sval, - Real &nval, - Real &pRed, - Vector &gmod, - const Vector &x, - Vector &px, - Vector &dg, + Real &sval, + Real &nval, + Real &pRed, + Vector &gmod, + const Vector &x, + Vector &px, + Vector &dg, Real del, - TrustRegionModel_U &model, - Objective &nobj, - Vector &pwa, + TrustRegionModel_U &model, + Objective &nobj, + Vector &pwa, Vector &pwa1, - Vector &dwa, - std::ostream &outStream = std::cout); + Vector &dwa, + std::ostream &outStream = std::cout); - void dpsg(Vector &y, - Real &sval, - Real &nval, - Real &pRed, - Vector &gmod, - Vector &px, - Vector &dg, - const Vector &x, + void dspg(Vector &y, + Real &sval, + Real &nval, + Vector &gmod, + const Vector &x, Real del, - TrustRegionModel_U &model, - Objective &nobj, - Vector &ymin, + TrustRegionModel_U &model, + Objective &nobj, + Vector &ymin, Vector &pwa, - Vector &pwa1, - Vector &pwa2, + Vector &pwa1, + Vector &pwa2, Vector &pwa3, - Vector &pwa4, - Vector &pwa5, + Vector &pwa4, + Vector &pwa5, Vector &dwa, - std::ostream &outStream = std::cout); + std::ostream &outStream = std::cout); - void dproj(Vector &x, - const Vector &x0, - Real del, - Objective &nobj, - Vector &y0, - Vector &y1, - Vector &yc, - Vector &pwa, - std::ostream &outStream = std::cout) const; + void dprox(Vector &x, + const Vector &x0, + Real t, + Real del, + Objective &nobj, + Vector &y0, + Vector &y1, + Vector &yc, + Vector &pwa, + std::ostream &outStream = std::cout) const; }; // class ROL::TypeP::TrustRegionAlgorithm diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp index c28cfe799bbe..1aa3a9613444 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp @@ -51,7 +51,7 @@ namespace TypeP { template TrustRegionAlgorithm::TrustRegionAlgorithm(ParameterList &list, - const Ptr> &secant) { + const Ptr> &secant) { // Set status test status_->reset(); status_->add(makePtr>(list)); @@ -69,8 +69,9 @@ TrustRegionAlgorithm::TrustRegionAlgorithm(ParameterList &list, TRsafe_ = trlist.get("Safeguard Size", 100.0); eps_ = TRsafe_*ROL_EPSILON(); interpRad_ = trlist.get("Use Radius Interpolation", false); - verbosity_ = trlist.sublist("General").get("Output Level", 0); - initProx_ = trlist.get("Apply Prox to Initial Guess", false); //change here? + verbosity_ = trlist.sublist("General").get("Output Level", 0); + initProx_ = trlist.get("Apply Prox to Initial Guess", false); + t0_ = list.sublist("Status Test").get("Proximal Gradient Parameter", 1.0); // Nonmonotone Parameters storageNM_ = trlist.get("Nonmonotone Storage Size", 0); useNM_ = (storageNM_ <= 0 ? false : true); @@ -97,8 +98,7 @@ TrustRegionAlgorithm::TrustRegionAlgorithm(ParameterList &list, useMin_ = lmlist.sublist("Solver").get("Use Smallest Model Iterate", true); useNMSP_ = lmlist.sublist("Solver").get("Use Nonmonotone Search", false); useSimpleSPG_ = !lmlist.sublist("Solver").get("Compute Cauchy Point", true); - t0_ = list.sublist("Status Test").get("Proximal Gradient Parameter", 1.0); //change here? - // Inexactness Information + // Inexactness Information ParameterList &glist = list.sublist("General"); useInexact_.clear(); useInexact_.push_back(glist.get("Inexact Objective Function", false)); @@ -137,44 +137,43 @@ void TrustRegionAlgorithm::initialize(Vector &x, Real ftol, Objective &sobj, Objective &nobj, - Vector &px, - Vector &dg, - std::ostream &outStream) { - const Real one(1); - // Initialize data + Vector &px, + Vector &dg, + std::ostream &outStream) { + // Initialize data TypeP::Algorithm::initialize(x,g); nhess_ = 0; // Update approximate gradient and approximate objective function. - if (initProx_){ - nobj.prox(*state_->iterateVec,x,t0_, ftol); state_->nprox++; + if (initProx_){ + nobj.prox(*state_->iterateVec,x,t0_, ftol); state_->nprox++; x.set(*state_->iterateVec); - } + } sobj.update(x,UpdateType::Initial,state_->iter); state_->svalue = sobj.value(x,ftol); state_->nsval++; nobj.update(x, UpdateType::Initial,state_->iter); - state_->nvalue = nobj.value(x,ftol); state_->nnval++; - state_->value = state_->svalue + state_->nvalue; + state_->nvalue = nobj.value(x,ftol); state_->nnval++; + state_->value = state_->svalue + state_->nvalue; state_->gnorm = computeGradient(x,*state_->gradientVec,px,dg,*state_->stepVec,state_->searchSize,sobj,nobj,outStream); - state_->ngrad++; - //state_->gnorm = state_->stepVec->norm()/t0_; state_->snorm = ROL_INF(); // Normalize initial CP step length if (normAlpha_) alpha_ /= state_->gradientVec->norm();//change here? // Compute initial trust region radius if desired. if ( state_->searchSize <= static_cast(0) ) state_->searchSize = state_->gradientVec->norm(); + SPiter_ = 0; + SPflag_ = 0; } template Real TrustRegionAlgorithm::computeValue(Real inTol, - Real &outTol, - Real pRed, - Real &fold, - int iter, - const Vector &x, - const Vector &xold, - Objective &sobj) { + Real &outTol, + Real pRed, + Real &fold, + int iter, + const Vector &x, + const Vector &xold, + Objective &sobj) { outTol = std::sqrt(ROL_EPSILON()); if ( useInexact_[0] ) { if (!(iter%updateIter_) && (iter!=0)) force_ *= forceFactor_; @@ -182,77 +181,68 @@ Real TrustRegionAlgorithm::computeValue(Real inTol, Real eta = static_cast(0.999)*std::min(eta1_,one-eta2_); outTol = scale_*std::pow(eta*std::min(pRed,force_),one/omega_); if (inTol > outTol) { - fold = sobj.value(xold,outTol); - state_->nsval++; - } + fold = sobj.value(xold,outTol); state_->nsval++; + } } // Evaluate objective function at new iterate sobj.update(x,UpdateType::Trial); - Real fval = sobj.value(x,outTol); - state_->nsval++; + Real fval = sobj.value(x,outTol); state_->nsval++; return fval; } template Real TrustRegionAlgorithm::computeGradient(const Vector &x, - Vector &g, - Vector &px, - Vector &dg, - Vector &step, - Real del, - Objective &sobj, - Objective &nobj, - std::ostream &outStream) const { + Vector &g, + Vector &px, + Vector &dg, + Vector &step, + Real del, + Objective &sobj, + Objective &nobj, + std::ostream &outStream) const { Real gnorm(0); - const Real one(1); - if ( useInexact_[1] ) { + if ( useInexact_[1] ) { + const Real one(1); Real gtol1 = scale0_*del; Real gtol0 = gtol1 + one; while ( gtol0 > gtol1 ) { - sobj.gradient(g,x,gtol1);//px otherwise nothing would change? - state_->ngrad++; - //gnorm = TypeP::Algorithm::optimalityCriterion(x,g,pwa,outStream); - dg.set(g.dual()); - pgstep(px, step, nobj, x, dg, t0_, gtol1); // change gtol? one or ocScale? - state_->nprox++; - gnorm = step.norm() / t0_; - + sobj.gradient(g,x,gtol1); state_->ngrad++; + dg.set(g.dual()); + pgstep(px, step, nobj, x, dg, t0_, gtol1); // change gtol? one or ocScale? + gnorm = step.norm() / t0_; gtol0 = gtol1; gtol1 = scale0_*std::min(gnorm,del); } } else { Real gtol = std::sqrt(ROL_EPSILON()); - sobj.gradient(g,x,gtol); - state_->ngrad++; - dg.set(g.dual()); - //gnorm = TypeP::Algorithm::optimalityCriterion(x,g,pwa,outStream); - pgstep(px, step, nobj, x, dg, t0_, gtol); - state_->nprox++; - gnorm = step.norm() / t0_; + sobj.gradient(g,x,gtol); state_->ngrad++; + dg.set(g.dual()); + pgstep(px, step, nobj, x, dg, t0_, gtol); + gnorm = step.norm() / t0_; } return gnorm; } template -void TrustRegionAlgorithm::run(Vector &x, - const Vector &g, - Objective &sobj, - Objective &nobj, - std::ostream &outStream ) { +void TrustRegionAlgorithm::run(Vector &x, + const Vector &g, + Objective &sobj, + Objective &nobj, + std::ostream &outStream ) { const Real zero(0), one(1); //Real tol0 = std::sqrt(ROL_EPSILON()); Real inTol = static_cast(0.1)*ROL_OVERFLOW(), outTol(inTol); - Real strial(0), ntrial(0), Ftrial(0), pRed(0), rho(1); + Real strial(0), ntrial(0), smodel(0), Ftrial(0), pRed(0), rho(1); // Initialize trust-region data std::vector output; Ptr> gmod = g.clone(); - Ptr> px = x.clone(); - Ptr> dg = x.clone(); + Ptr> px = x.clone(); + Ptr> dg = x.clone(); // Initialize Algorithm initialize(x,g,inTol,sobj,nobj, *px, *dg, outStream); // Initialize storage vectors - Ptr> pwa1 = x.clone(), pwa2 = x.clone(); + Ptr> pwa1 = x.clone(), pwa2 = x.clone(); Ptr> pwa3 = x.clone(), pwa4 = x.clone(); Ptr> pwa5 = x.clone(), pwa6 = x.clone(); Ptr> pwa7 = x.clone(); @@ -277,16 +267,20 @@ void TrustRegionAlgorithm::run(Vector &x, *pwa1,*pwa2,*dwa1,outStream); else { // Compute Cauchy point (TRON notation: x = x[1]) - Real sval = state_->svalue, nval = state_->nvalue; - dcauchy(*state_->stepVec,alpha_, sval, nval, pRed, *state_->iterateVec,//add pred, q is mold - *dg, *px, state_->searchSize, - *model_, nobj, *dwa1, *dwa2, outStream); // Solve 1D optimization problem for alpha + smodel = state_->svalue; + ntrial = state_->nvalue; + dcauchy(*state_->stepVec,alpha_, smodel, ntrial, + *state_->iterateVec, *dg, state_->searchSize, + *model_, nobj, *px, *dwa1, *dwa2, outStream); // Solve 1D optimization problem for alpha x.plus(*state_->stepVec); // Set x = x[0] + alpha*g // Model gradient at s = x[1] - x[0] gmod->plus(*dwa1); // hessVec from Cauchy point computation // Apply SPG starting from the Cauchy point->change input - dpsg(x,sval,nval,pRed,*gmod,*px, *dg,*state_->iterateVec,state_->searchSize,*model_,nobj,*pwa1,*pwa2,*pwa3,*pwa4,*pwa5,*pwa6,*pwa7,*dwa1,outStream);//probably nobj + dspg(x,smodel,ntrial,*gmod,*state_->iterateVec,state_->searchSize, + *model_,nobj,*pwa1,*pwa2,*pwa3,*pwa4,*pwa5,*pwa6,*pwa7,*dwa1, + outStream); + pRed = state_->value - (smodel+ntrial); } // Update storage and compute predicted reduction @@ -297,10 +291,8 @@ void TrustRegionAlgorithm::run(Vector &x, // Compute trial objective value strial = computeValue(inTol,outTol,pRed,state_->svalue,state_->iter,x,*state_->iterateVec,sobj); nobj.update(x, UpdateType::Trial); - ntrial = nobj.value(x,outTol); - Ftrial = strial + ntrial; - state_->nsval++; - state_->nnval++; + ntrial = nobj.value(x,outTol); state_->nnval++; + Ftrial = strial + ntrial; // Compute ratio of acutal and predicted reduction TRflag_ = TRUtils::SUCCESS; @@ -330,9 +322,9 @@ void TrustRegionAlgorithm::run(Vector &x, } else if ((rho >= eta0_ && TRflag_ != TRUtils::NPOSPREDNEG) || (TRflag_ == TRUtils::POSPREDNEG)) { // Step Accepted - state_->value = Ftrial; - state_->svalue = strial; - state_->nvalue = ntrial; + state_->value = Ftrial; + state_->svalue = strial; + state_->nvalue = ntrial; sobj.update(x,UpdateType::Accept,state_->iter); nobj.update(x,UpdateType::Accept,state_->iter); inTol = outTol; @@ -363,105 +355,90 @@ void TrustRegionAlgorithm::run(Vector &x, if (verbosity_ > 0) TypeP::Algorithm::writeExitStatus(outStream); } -/*template -Real TrustRegionNonsmoothAlgorithm::dgpstep(Vector &s, const Vector &w, - const Vector &x, const Real alpha, - std::ostream &outStream) const { - s.set(x); s.axpy(alpha,w); - proj_->project(s,outStream); state_->nproj++; - s.axpy(static_cast(-1),x); - return s.norm(); -}*/ template Real TrustRegionAlgorithm::dcauchy(Vector &s, - Real &alpha, - Real &sval, - Real &nval, - Real &pRed, - const Vector &x, - const Vector &g, - Vector &px, - const Real del, - TrustRegionModel_U &model, - Objective &nobj, - Vector &dwa, - Vector &dwa1, - std::ostream &outStream) { - const Real half(0.5); - // const Real zero(0); // Unused + Real &alpha, + Real &sval, + Real &nval, + const Vector &x, + const Vector &g, + const Real del, + TrustRegionModel_U &model, + Objective &nobj, + Vector &px, + Vector &dwa, + Vector &dwa1, + std::ostream &outStream) { + const Real half(0.5), sold(sval), nold(nval); Real tol = std::sqrt(ROL_EPSILON()); bool interp = false; - Real gs(0), snorm(0), nold(nval), mold(sval+nval), mnew(mold), sold(sval), Qk(0); - // Compute s = P(x[0] - alpha g[0]) - //snorm = dgpstep(s,g,x,-alpha,outStream); - pgstep(px, s, nobj, x, g, alpha, tol); - snorm = s.norm(); + Real gs(0), snorm(0), Qk(0), pRed(0); + // Compute s = P(x[0] - alpha g[0]) - x[0] + pgstep(px, s, nobj, x, g, alpha, tol); + snorm = s.norm(); if (snorm > del) { interp = true; } else { model.hessVec(dwa,s,x,tol); nhess_++; - gs = s.dot(g); nobj.update(px, UpdateType::Trial); - nval = nobj.value(px, tol); state_->nnval++; - //q = half * s.dot(dwa.dual()) + gs; - sval = half * s.apply(dwa) + gs + sold; - mnew = nval + sval; - Qk = gs + nval - nold; - interp = (mnew > mold + mu0_*Qk); + nval = nobj.value(px, tol); state_->nnval++; + gs = s.dot(g); + sval = sold + gs + half * s.apply(dwa); + pRed = (sold + nold) - (sval + nval); + Qk = gs + nval - nold; + interp = (pRed < -mu0_*Qk); } // Either increase or decrease alpha to find approximate Cauchy point int cnt = 0; if (interp) {//decrease loop bool search = true; while (search) { - alpha *= interpf_; - //snorm = dgpstep(s,g,x,-alpha,outStream); - pgstep(px, s, nobj, x, g, alpha, tol); - snorm = s.norm(); + alpha *= interpf_; + pgstep(px, s, nobj, x, g, alpha, tol); + snorm = s.norm(); if (snorm <= del) { model.hessVec(dwa,s,x,tol); nhess_++; - gs = s.dot(g); - //q = half * s.dot(dwa.dual()) + gs; nobj.update(px, UpdateType::Trial); - nval = nobj.value(px, tol); state_->nnval++; - sval = half * s.apply(dwa) + gs + sold; - mnew = sval + nval; - Qk = gs + nval - nold; - search = ((mnew > mold + mu0_*Qk) && (cnt < redlim_)) ; - } + nval = nobj.value(px, tol); state_->nnval++; + gs = s.dot(g); + sval = sold + gs + half * s.apply(dwa); + pRed = (sold + nold) - (sval + nval); + Qk = gs + nval - nold; + search = ((pRed < -mu0_*Qk) && (cnt < redlim_)) ; + } cnt++; } } else { bool search = true; Real alphas = alpha; - Real mvals = mnew; - dwa1.set(dwa); + Real mvals = pRed; + Real svals = sval; + dwa1.set(dwa); while (search) { alpha *= extrapf_; - //snorm = dgpstep(s,g,x,-alpha,outStream); - pgstep(px, s, nobj, x, g, alpha, tol); //dwa? - snorm = s.norm(); - printf("%f %f\n", snorm, del); + pgstep(px, s, nobj, x, g, alpha, tol); + snorm = s.norm(); if (snorm <= del && cnt < explim_){// && mnew < mold + mu0_*Qk) { model.hessVec(dwa,s,x,tol); nhess_++; - gs = s.dot(g); nobj.update(px, UpdateType::Trial); - nval = nobj.value(px, tol); state_->nnval++; - //q = half * s.dot(dwa.dual()) + gs; - sval = half * s.apply(dwa) + gs + sold; - Qk = gs + nval - nold; - mnew = sval+nval; - if (mnew <= mold + mu0_*Qk && std::abs(mnew-mvals) > qtol_*std::abs(mvals)) { - dwa1.set(dwa); - search = true; + nval = nobj.value(px, tol); state_->nnval++; + gs = s.dot(g); + sval = sold + gs + half * s.apply(dwa); + pRed = (sold + nold) - (sval + nval); + Qk = gs + nval - nold; + if (pRed >= -mu0_*Qk && std::abs(pRed-mvals) > qtol_*std::abs(mvals)) { + dwa1.set(dwa); alphas = alpha; - mvals = mnew; + mvals = pRed; + svals = sval; + search = true; } else { - mnew = mvals; dwa.set(dwa1); + pRed = mvals; + sval = svals; search = false; } } @@ -471,19 +448,16 @@ Real TrustRegionAlgorithm::dcauchy(Vector &s, cnt++; } alpha = alphas; - //snorm = dgpstep(s,g,x,-alpha,outStream); - pgstep(px, s, nobj, x, g, alpha, tol);//dwa? - snorm = s.norm(); + pgstep(px, s, nobj, x, g, alpha, tol); + snorm = s.norm(); } - pRed = mold - mnew; - if (verbosity_ > 1) { + if (verbosity_ > 1) { outStream << " Cauchy point" << std::endl; outStream << " Step length (alpha): " << alpha << std::endl; outStream << " Step length (alpha*g): " << snorm << std::endl; outStream << " Model decrease (pRed): " << pRed << std::endl; - if (!interp) { + if (!interp) outStream << " Number of extrapolation steps: " << cnt << std::endl; - } } return snorm; } @@ -600,60 +574,55 @@ void TrustRegionAlgorithm::dpsg_simple(Vector &y, //x } template -void TrustRegionAlgorithm::dpsg(Vector &y, - Real &sval, - Real &nval, - Real &pRed, - Vector &gmod, - Vector &px, - Vector &dg, - const Vector &x, - Real del, - TrustRegionModel_U &model, - Objective &nobj, - Vector &ymin, - Vector &pwa, - Vector &pwa1, - Vector &pwa2, - Vector &pwa3, - Vector &pwa4, - Vector &pwa5, - Vector &dwa, - std::ostream &outStream) { +void TrustRegionAlgorithm::dspg(Vector &y, + Real &sval, + Real &nval, + Vector &gmod, + const Vector &x, + Real del, + TrustRegionModel_U &model, + Objective &nobj, + Vector &ymin, + Vector &pwa, + Vector &pwa1, + Vector &pwa2, + Vector &pwa3, + Vector &pwa4, + Vector &pwa5, + Vector &dwa, + std::ostream &outStream) { // Use SPG to approximately solve TR subproblem: - // min 1/2 + subject to y\in C, ||y|| \le del + // min 1/2 + + phi(y) subject to ||y|| \le del // // Inpute: // y = Cauchy step // x = Current iterate // g = Current gradient - const Real zero(0), half(0.5), one(1), two(2); //, eps(std::sqrt(ROL_EPSILON())); + const Real half(0.5), one(1); + const Real mval(sval+nval); Real tol(std::sqrt(ROL_EPSILON())); - Real alpha(1), sHs(0), alphaTmp(1), mmax(0), mval_min(0), lambdaTmp(1); - Real mold(sval+nval), mval(mold); + Real mcomp(0), mval_min(0), sval_min(0), nval_min(0); + Real alpha(1), coeff(1), lambda(1), lambdaTmp(1); + Real snew(sval), nnew(nval), mnew(mval); + Real sold(sval), nold(nval), mold(mval); + Real sHs(0), ss(0), gs(0), Qk(0), gnorm(0); std::deque mqueue; mqueue.push_back(mold); - if (useNMSP_ && useMin_) { mval_min = sval+nval; ymin.set(y); } + if (useNMSP_ && useMin_) { + mval_min = mval; sval_min = sval; nval_min = nval; ymin.set(y); + } - // Compute initial projected gradient norm + // Compute initial proximal gradient norm pwa1.set(gmod.dual()); - pwa.set(y); pwa.axpy(-one,pwa1); - dproj(pwa,x,del,nobj,pwa2,pwa3,pwa4,pwa5,outStream); + pwa.set(y); pwa.axpy(-t0_,pwa1); + dprox(pwa,x,t0_,del,nobj,pwa2,pwa3,pwa4,pwa5,outStream); pwa.axpy(-one,y); - Real gnorm = pwa.norm(); + gnorm = pwa.norm() / t0_; const Real gtol = std::min(tol1_,tol2_*gnorm); - // Compute initial step - Real coeff = one/gmod.norm(); - Real lambda = std::max(lambdaMin_,std::min(coeff,lambdaMax_)); - pwa.set(y); pwa.axpy(-lambda,pwa1); // pwa = y - lambda gmod.dual() - dproj(pwa,x,del,nobj,pwa2,pwa3,pwa4,pwa5,outStream); // pwa = P(y - lambda gmod.dual()) - nobj.update(pwa, UpdateType::Trial); - Real ntrial = nobj.value(pwa, tol); - pwa.axpy(-one,y); // pwa = P(y - lambda gmod.dual()) - y = step - Real gs = gmod.apply(pwa); // gs = - Real Qk = gs - nval + ntrial; - Real ss = pwa.dot(pwa); // Norm squared of step + // Compute initial spectral step size + coeff = one / gmod.norm(); + lambda = std::max(lambdaMin_,std::min(coeff,lambdaMax_)); if (verbosity_ > 1) outStream << " Spectral Projected Gradient" << std::endl; @@ -662,86 +631,99 @@ void TrustRegionAlgorithm::dpsg(Vector &y, while (SPiter_ < maxit_) { SPiter_++; + // Compuate SPG step + alpha = one; + pwa.set(y); pwa.axpy(-lambda,pwa1); // pwa = y - lambda gmod.dual() + dprox(pwa,x,lambda,del,nobj,pwa2,pwa3,pwa4,pwa5,outStream); // pwa = P(y - lambda gmod.dual()) + pwa.axpy(-one,y); // pwa = P(y - lambda gmod.dual()) - y = step + pwa2.set(y); pwa2.plus(pwa); // pwa2 = P(y - lambda gmod.dual()) + ss = pwa.dot(pwa); // Norm squared of step + // Evaluate model Hessian model.hessVec(dwa,pwa,x,tol); nhess_++; // dwa = H step - sHs = dwa.apply(pwa); // sHs = + nobj.update(pwa2, UpdateType::Trial); + nnew = nobj.value(pwa2, tol); state_->nnval++; + sHs = dwa.apply(pwa); // sHs = + gs = gmod.apply(pwa); // gs = + snew = half * sHs + gs + sold; + mnew = snew + nnew; + Qk = gs + nnew - nold; // Perform line search - if (useNMSP_) { // Nonmonotone - mmax = *std::max_element(mqueue.begin(),mqueue.end()); - alphaTmp = (-(Qk - gamma_*gs) + std::sqrt(std::pow((Qk - gamma_*gs),two)-two*sHs*(sval+nval-mmax)))/sHs; //come back to this - } - else { // Exact - alphaTmp = -Qk/sHs; + mcomp = useNMSP_ ? *std::max_element(mqueue.begin(),mqueue.end()) : mold; + while( mnew > mcomp + mu0_*Qk) { + alpha *= interpf_; + pwa2.set(y); pwa2.axpy(alpha,pwa); + nobj.update(pwa2, UpdateType::Trial); + nnew = nobj.value(pwa2, tol); state_->nnval++; + snew = half * alpha * alpha * sHs + alpha * gs + sold; + mnew = nnew + snew; + Qk = alpha * gs + nnew - nold; } - alpha = (sHs > zero ? std::min(one,std::max(zero,alphaTmp)) : one); // Update model quantities - sval += alpha * (gs + half * alpha * sHs); // Update smooth model value - gmod.axpy(alpha,dwa); // Update model gradient - y.axpy(alpha,pwa); // New iterate - - nobj.update(y, UpdateType::Accept); - nval = nobj.value(y, tol); - mval = nval + sval; + y.set(pwa2); + sold = snew; + nold = nnew; + mold = mnew; + gmod.axpy(alpha,dwa); // Update model gradient + nobj.update(y, UpdateType::Accept); // Update nonmonotone line search information if (useNMSP_) { if (static_cast(mqueue.size())==maxSize_) mqueue.pop_front(); mqueue.push_back(sval+nval); - if (useMin_ && mval <= mval_min) { mval_min = mval; ymin.set(y); } + if (useMin_ && mval <= mval_min) { + mval_min = mval; sval_min = sval; nval_min = nval; ymin.set(y); + } } // Compute projected gradient norm pwa1.set(gmod.dual()); - pwa.set(y); pwa.axpy(-one,pwa1); - dproj(pwa,x,del,nobj, pwa2,pwa3,pwa4,pwa5,outStream); + pwa.set(y); pwa.axpy(-t0_,pwa1); + dprox(pwa,x,t0_,del,nobj,pwa2,pwa3,pwa4,pwa5,outStream); pwa.axpy(-one,y); - gnorm = pwa.norm(); - pRed = mval - mold; + gnorm = pwa.norm() / t0_; if (verbosity_ > 1) { outStream << std::endl; - outStream << " Iterate: " << SPiter_ << std::endl; - outStream << " Spectral step length (lambda): " << lambda << std::endl; - outStream << " Step length (alpha): " << alpha << std::endl; - outStream << " Model decrease (pRed): " << pRed << std::endl; - outStream << " Optimality criterion: " << gnorm << std::endl; + outStream << " Iterate: " << SPiter_ << std::endl; + outStream << " Spectral step length (lambda): " << lambda << std::endl; + outStream << " Step length (alpha): " << alpha << std::endl; + outStream << " Model decrease (pRed): " << mval-mold << std::endl; + outStream << " Optimality criterion: " << gnorm << std::endl; outStream << std::endl; } if (gnorm < gtol) break; // Compute new spectral step - //lambda = (sHs<=eps ? lambdaMax_ : std::max(lambdaMin_,std::min(ss/sHs,lambdaMax_))); - lambdaTmp = (sHs == 0 ? coeff : ss/sHs); - lambda = std::max(lambdaMin_,std::min(lambdaTmp,lambdaMax_)); - pwa.set(y); pwa.axpy(-lambda,pwa1); - dproj(pwa,x,del,nobj,pwa2,pwa3,pwa4,pwa5,outStream); - pwa.axpy(-one,y); - gs = gmod.apply(pwa); - ss = pwa.dot(pwa); + lambdaTmp = (sHs == 0 ? coeff : ss / sHs); + lambda = std::max(lambdaMin_, std::min(lambdaTmp, lambdaMax_)); + } + if (useNMSP_ && useMin_) { + sval = sval_min; nval = nval_min; y.set(ymin); } - if (useNMSP_ && useMin_) { mval = mval_min; y.set(ymin); } SPflag_ = (SPiter_==maxit_) ? 1 : 0; } template -void TrustRegionAlgorithm::dproj(Vector &x, - const Vector &x0, - Real del, - Objective &nobj, - Vector &y0, - Vector &y1, - Vector &yc, - Vector &pwa, - std::ostream &outStream) const { +void TrustRegionAlgorithm::dprox(Vector &x, + const Vector &x0, + Real t, + Real del, + Objective &nobj, + Vector &y0, + Vector &y1, + Vector &yc, + Vector &pwa, + std::ostream &outStream) const { // Solve ||P(t*x0 + (1-t)*(x-x0))-x0|| = del using Brent's method const Real zero(0), half(0.5), one(1), two(2), three(3); const Real eps(ROL_EPSILON()), tol0(1e1*eps), fudge(1.0-1e-2*sqrt(eps)); Real f0(0), f1(0), fc(0), t0(0), t1(1), tc(0), d1(1), d2(1), tol(1); Real p(0), q(0), r(0), s(0), m(0); int cnt(state_->nprox); - nobj.prox(y1, x, one, tol); state_->nprox++; + nobj.prox(y1, x, t, tol); state_->nprox++; pwa.set(y1); pwa.axpy(-one,x0); f1 = pwa.norm(); if (f1 <= del) { @@ -793,8 +775,7 @@ void TrustRegionAlgorithm::dproj(Vector &x, else if (m > zero) t1 += tol; else t1 -= tol; pwa.set(x); pwa.scale(t1); pwa.axpy(one-t1,x0); - nobj.prox(y1, pwa, t1, tol); - state_->nprox++; + nobj.prox(y1, pwa, t1*t, tol); state_->nprox++; pwa.set(y1); pwa.axpy(-one,x0); f1 = pwa.norm(); if ((f1 > del && fc > del) || (f1 <= del && fc <= del)) { @@ -823,7 +804,7 @@ void TrustRegionAlgorithm::dproj(Vector &x, // BRACKETING AND BRENTS FOR UNTRANSFORMED MULTIPLIER //template -//void TrustRegionSPGAlgorithm::dproj(Vector &x, +//void TrustRegionSPGAlgorithm::dprox(Vector &x, // const Vector &x0, // Real del, // Vector &y0, @@ -936,7 +917,7 @@ void TrustRegionAlgorithm::dproj(Vector &x, // RIDDERS' METHOD FOR TRUST-REGION PROJECTION //template -//void TrustRegionSPGAlgorithm::dproj(Vector &x, +//void TrustRegionSPGAlgorithm::dprox(Vector &x, // const Vector &x0, // Real del, // Vector &y, From d499bfc787e1364f739b0f99d34576213d23bb36 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Thu, 5 Jan 2023 04:59:15 -0700 Subject: [PATCH 29/65] Replaced indents with spaces. --- .../TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp index 1aa3a9613444..820b55ecf3e4 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp @@ -465,15 +465,15 @@ Real TrustRegionAlgorithm::dcauchy(Vector &s, template void TrustRegionAlgorithm::dpsg_simple(Vector &y, //x Real &sval, - Real &nval, - Real &pRed, //predicted reduction + Real &nval, + Real &pRed, //predicted reduction Vector &gmod, // state_->gradientVec const Vector &x, //iterateVect - Vector &px, // px - Vector &dg, // gradient dual? + Vector &px, // px + Vector &dg, // gradient dual? Real del, TrustRegionModel_U &model, - Objective &nobj, + Objective &nobj, Vector &pwa, Vector &pwa1, Vector &dwa, From 1674f37023bd831ae7de4f466fea431373ea92b0 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Thu, 5 Jan 2023 05:29:27 -0700 Subject: [PATCH 30/65] Both dspg and dspg_simple now work. This could still use some cleaning up. --- .../TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp | 5 +- .../ROL_TypeP_TrustRegionAlgorithm_Def.hpp | 85 ++++++++++--------- 2 files changed, 47 insertions(+), 43 deletions(-) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp index 5463c377edb4..56179f06615c 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp @@ -208,19 +208,18 @@ class TrustRegionAlgorithm : public TypeP::Algorithm { Vector &dwa1, std::ostream &outStream = std::cout); - void dpsg_simple(Vector &y, + void dspg_simple(Vector &y, Real &sval, Real &nval, Real &pRed, Vector &gmod, const Vector &x, - Vector &px, - Vector &dg, Real del, TrustRegionModel_U &model, Objective &nobj, Vector &pwa, Vector &pwa1, + Vector &pwa2, Vector &dwa, std::ostream &outStream = std::cout); diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp index 820b55ecf3e4..a825e09cae66 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp @@ -262,13 +262,14 @@ void TrustRegionAlgorithm::run(Vector &x, /**** SOLVE TRUST-REGION SUBPROBLEM ****/ //q = state_->svalue + state_->nvalue;//q is no longer used gmod->set(*state_->gradientVec); + smodel = state_->svalue; + ntrial = state_->nvalue; if (useSimpleSPG_) - dpsg_simple(x,state_->svalue, state_->nvalue,pRed,*gmod,*state_->iterateVec,*px, *dg, state_->searchSize,*model_,nobj, - *pwa1,*pwa2,*dwa1,outStream); + dspg_simple(x,smodel, ntrial, pRed, *gmod, *state_->iterateVec, + state_->searchSize, *model_, nobj, + *pwa1, *pwa2, *px, *dwa1, outStream); else { // Compute Cauchy point (TRON notation: x = x[1]) - smodel = state_->svalue; - ntrial = state_->nvalue; dcauchy(*state_->stepVec,alpha_, smodel, ntrial, *state_->iterateVec, *dg, state_->searchSize, *model_, nobj, *px, *dwa1, *dwa2, outStream); // Solve 1D optimization problem for alpha @@ -463,19 +464,18 @@ Real TrustRegionAlgorithm::dcauchy(Vector &s, } template -void TrustRegionAlgorithm::dpsg_simple(Vector &y, //x +void TrustRegionAlgorithm::dspg_simple(Vector &y, Real &sval, Real &nval, - Real &pRed, //predicted reduction - Vector &gmod, // state_->gradientVec - const Vector &x, //iterateVect - Vector &px, // px - Vector &dg, // gradient dual? + Real &pRed, + Vector &gmod, + const Vector &x, Real del, TrustRegionModel_U &model, Objective &nobj, Vector &pwa, Vector &pwa1, + Vector &pwa2, Vector &dwa, std::ostream &outStream) { // Use SPG to approximately solve TR subproblem: @@ -486,23 +486,23 @@ void TrustRegionAlgorithm::dpsg_simple(Vector &y, //x // x = Current iterate // g = Current gradient const Real half(0.5), one(1), safeguard(1e2*ROL_EPSILON()); + const Real mprev(sval+nval); Real tol(std::sqrt(ROL_EPSILON())); - Real alpha(1), alphaMax(1), s0s0(0), ss0(0), sHs(0), lambdaTmp(1), snorm(0), mold(sval+nval), mnew(mold); + Real coeff(1), alpha(1), alphaMax(1), lambda(1), lambdaTmp(1); + Real gs(0), ss(0), gnorm(0), s0s0(0), ss0(0), sHs(0), snorm(0), nold(nval); pwa1.zero(); // Set y = x y.set(x); // Compute initial step - Real coeff = one/gmod.norm(); - Real lambda = std::max(lambdaMin_,std::min(coeff,lambdaMax_)); - pgstep(px, pwa, nobj, y, gmod.dual(), alpha, tol); // pass pwa by reference? *pwa? - //pwa.set(y); pwa.axpy(-lambda,gmod.dual()); // pwa = x - lambda gmod.dual() - //proj_->project(pwa,outStream); state_->nproj++; // pwa = P(x - lambda gmod.dual()) - //pwa.axpy(-one,y); // pwa = P(x - lambda gmod.dual()) - x = step - Real gs = gmod.apply(pwa); // gs = - Real ss = pwa.dot(pwa); // Norm squared of step - Real gnorm = std::sqrt(ss); + coeff = one / gmod.norm(); + lambda = std::max(lambdaMin_,std::min(coeff,lambdaMax_)); + pgstep(pwa2, pwa, nobj, y, gmod.dual(), lambda, tol); + gs = gmod.apply(pwa); // gs = + ss = pwa.dot(pwa); // Norm squared of step + snorm = std::sqrt(ss); // norm(step) + gnorm = snorm / lambda; // norm(step) / lambda // Compute initial projected gradient norm const Real gtol = std::min(tol1_,tol2_*gnorm); @@ -518,25 +518,33 @@ void TrustRegionAlgorithm::dpsg_simple(Vector &y, //x model.hessVec(dwa,pwa,x,tol); nhess_++; // dwa = H step sHs = dwa.apply(pwa); // sHs = + // Evaluate nonsmooth term + nobj.update(pwa2,UpdateType::Trial); + nval = nobj.value(pwa2,tol); + // Perform line search alphaMax = 1; - if (gnorm >= del-safeguard) { // Trust-region constraint is violated + if (snorm >= del-safeguard) { // Trust-region constraint is violated ss0 = pwa1.dot(pwa); alphaMax = std::min(one, (-ss0 + std::sqrt(ss0*ss0 - ss*(s0s0-del*del)))/ss); } - if (sHs <= safeguard) - alpha = alphaMax; - else - alpha = std::min(alphaMax, -gs/sHs); + alpha = (sHs <= safeguard) ? alphaMax : std::min(alphaMax, -(gs + nval - nold)/sHs); // Update model quantities - y.axpy(alpha,pwa); // New iterate - nval = nobj.value(y, tol); - sval += alpha * (gs + half * alpha * sHs); // Update model value - is this correct? - mnew = sval + nval; - gmod.axpy(alpha,dwa); // Update model gradient - - pRed = mold - mnew; + if (alpha == one) { + y.set(pwa2); + sval += gs + half * sHs; + gmod.plus(dwa); + } + else { + y.axpy(alpha,pwa); // New iterate + nobj.update(y,UpdateType::Trial); + nval = nobj.value(y, tol); + sval += alpha * (gs + half * alpha * sHs); + gmod.axpy(alpha,dwa); + } + nold = nval; + pRed = mprev - (sval+nval); // Check trust-region constraint violation pwa1.set(y); pwa1.axpy(-one,x); @@ -558,15 +566,12 @@ void TrustRegionAlgorithm::dpsg_simple(Vector &y, //x // Compute new spectral step lambdaTmp = (sHs <= safeguard ? one/gmod.norm() : ss/sHs); - lambda = std::max(lambdaMin_,std::min(lambdaTmp,lambdaMax_)); + lambda = std::max(lambdaMin_,std::min(lambdaTmp,lambdaMax_)); - pgstep(px, pwa, nobj, y, gmod.dual(), alpha, tol); // pass pwa by reference? *pwa? - //pwa.set(y); pwa.axpy(-lambda,gmod.dual()); - //proj_->project(pwa,outStream); state_->nproj++; - //pwa.axpy(-one,y); - gs = gmod.apply(pwa); - ss = pwa.dot(pwa); - gnorm = std::sqrt(ss); + pgstep(pwa2, pwa, nobj, y, gmod.dual(), alpha, tol); // pass pwa by reference? *pwa? + gs = gmod.apply(pwa); + ss = pwa.dot(pwa); + gnorm = std::sqrt(ss) / lambda; if (gnorm <= gtol) { SPflag_ = 0; break; } } From 3a9a30db6b2b9529b72748a2a9d045cfd48cbda1 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Thu, 5 Jan 2023 14:11:53 -0700 Subject: [PATCH 31/65] Clean up of TypeP trust region and added to TypeP Factory. --- .../TypeP/ROL_TypeP_AlgorithmFactory.hpp | 8 +- .../ROL_TypeP_TrustRegionAlgorithm_Def.hpp | 204 ++---------------- 2 files changed, 22 insertions(+), 190 deletions(-) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_AlgorithmFactory.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_AlgorithmFactory.hpp index 4451af1fe0cf..bab3393341f3 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_AlgorithmFactory.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_AlgorithmFactory.hpp @@ -48,6 +48,7 @@ #include "ROL_TypeP_SpectralGradientAlgorithm.hpp" #include "ROL_TypeP_iPianoAlgorithm.hpp" #include "ROL_TypeP_QuasiNewtonAlgorithm.hpp" +#include "ROL_TypeP_TrustRegionAlgorithm.hpp" #include "ROL_Types.hpp" namespace ROL { @@ -60,12 +61,14 @@ namespace TypeP { \arg ALGORITHM_P_SPECTRALGRADIENT describe \arg ALGORITHM_P_IPIANO describe \arg ALGORITHM_P_QUASINEWTON describe + \arg ALGORITHM_P_TRUSTREGION describe */ enum EAlgorithmP{ ALGORITHM_P_PROXIMALGRADIENT = 0, ALGORITHM_P_SPECTRALGRADIENT, ALGORITHM_P_IPIANO, ALGORITHM_P_QUASINEWTON, + ALGORITHM_P_TRUSTREGION, ALGORITHM_P_LAST }; @@ -76,6 +79,7 @@ inline std::string EAlgorithmPToString(EAlgorithmP alg) { case ALGORITHM_P_SPECTRALGRADIENT: retString = "Spectral Gradient"; break; case ALGORITHM_P_IPIANO: retString = "iPiano"; break; case ALGORITHM_P_QUASINEWTON: retString = "Quasi-Newton"; break; + case ALGORITHM_P_TRUSTREGION: retString = "Trust Region"; break; case ALGORITHM_P_LAST: retString = "Last Type (Dummy)"; break; default: retString = "INVALID EAlgorithmP"; } @@ -92,6 +96,7 @@ inline int isValidAlgorithmP(EAlgorithmP alg){ (alg == ALGORITHM_P_SPECTRALGRADIENT) || (alg == ALGORITHM_P_IPIANO) || (alg == ALGORITHM_P_QUASINEWTON) || + (alg == ALGORITHM_P_TRUSTREGION) || (alg == ALGORITHM_P_LAST) ); } @@ -128,12 +133,13 @@ inline EAlgorithmP StringToEAlgorithmP(std::string s) { template inline Ptr> AlgorithmFactory(ParameterList &parlist) { - EAlgorithmP ealg = StringToEAlgorithmP(parlist.sublist("Step").get("Type","Spectral Gradient")); + EAlgorithmP ealg = StringToEAlgorithmP(parlist.sublist("Step").get("Type","Trust Region")); switch(ealg) { case ALGORITHM_P_PROXIMALGRADIENT: return makePtr>(parlist); case ALGORITHM_P_SPECTRALGRADIENT: return makePtr>(parlist); case ALGORITHM_P_IPIANO: return makePtr>(parlist); case ALGORITHM_P_QUASINEWTON: return makePtr>(parlist); + case ALGORITHM_P_TRUSTREGION: return makePtr>(parlist); default: return nullPtr; } } diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp index a825e09cae66..daff8eedb688 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp @@ -69,9 +69,9 @@ TrustRegionAlgorithm::TrustRegionAlgorithm(ParameterList &list, TRsafe_ = trlist.get("Safeguard Size", 100.0); eps_ = TRsafe_*ROL_EPSILON(); interpRad_ = trlist.get("Use Radius Interpolation", false); - verbosity_ = trlist.sublist("General").get("Output Level", 0); - initProx_ = trlist.get("Apply Prox to Initial Guess", false); - t0_ = list.sublist("Status Test").get("Proximal Gradient Parameter", 1.0); + verbosity_ = trlist.sublist("General").get("Output Level", 0); + initProx_ = trlist.get("Apply Prox to Initial Guess", false); + t0_ = list.sublist("Status Test").get("Proximal Gradient Parameter", 1.0); // Nonmonotone Parameters storageNM_ = trlist.get("Nonmonotone Storage Size", 0); useNM_ = (storageNM_ <= 0 ? false : true); @@ -88,16 +88,16 @@ TrustRegionAlgorithm::TrustRegionAlgorithm(ParameterList &list, extrapf_ = lmlist.sublist("Cauchy Point").get("Expansion Rate", 10.0); qtol_ = lmlist.sublist("Cauchy Point").get("Decrease Tolerance", 1e-8); // Subsolver (spectral projected gradient) parameters - lambdaMin_ = lmlist.sublist("Solver").get("Minimum Spectral Step Size", 1e-8); - lambdaMax_ = lmlist.sublist("Solver").get("Maximum Spectral Step Size", 1e8); - gamma_ = lmlist.sublist("Solver").get("Sufficient Decrease Tolerance", 1e-4); - maxSize_ = lmlist.sublist("Solver").get("Maximum Storage Size", 10); - maxit_ = lmlist.sublist("Solver").get("Iteration Limit", 25); - tol1_ = lmlist.sublist("Solver").get("Absolute Tolerance", 1e-4); - tol2_ = lmlist.sublist("Solver").get("Relative Tolerance", 1e-2); - useMin_ = lmlist.sublist("Solver").get("Use Smallest Model Iterate", true); - useNMSP_ = lmlist.sublist("Solver").get("Use Nonmonotone Search", false); - useSimpleSPG_ = !lmlist.sublist("Solver").get("Compute Cauchy Point", true); + lambdaMin_ = lmlist.sublist("Solver").get("Minimum Spectral Step Size", 1e-8); + lambdaMax_ = lmlist.sublist("Solver").get("Maximum Spectral Step Size", 1e8); + gamma_ = lmlist.sublist("Solver").get("Sufficient Decrease Tolerance", 1e-4); + maxSize_ = lmlist.sublist("Solver").get("Maximum Storage Size", 10); + maxit_ = lmlist.sublist("Solver").get("Iteration Limit", 25); + tol1_ = lmlist.sublist("Solver").get("Absolute Tolerance", 1e-4); + tol2_ = lmlist.sublist("Solver").get("Relative Tolerance", 1e-2); + useMin_ = lmlist.sublist("Solver").get("Use Smallest Model Iterate", true); + useNMSP_ = lmlist.sublist("Solver").get("Use Nonmonotone Search", false); + useSimpleSPG_ = !lmlist.sublist("Solver").get("Compute Cauchy Point", true); // Inexactness Information ParameterList &glist = list.sublist("General"); useInexact_.clear(); @@ -520,7 +520,7 @@ void TrustRegionAlgorithm::dspg_simple(Vector &y, // Evaluate nonsmooth term nobj.update(pwa2,UpdateType::Trial); - nval = nobj.value(pwa2,tol); + nval = nobj.value(pwa2,tol); // Perform line search alphaMax = 1; @@ -565,7 +565,7 @@ void TrustRegionAlgorithm::dspg_simple(Vector &y, if (snorm >= del - safeguard) { SPflag_ = 2; break; } // Compute new spectral step - lambdaTmp = (sHs <= safeguard ? one/gmod.norm() : ss/sHs); + lambdaTmp = (sHs <= safeguard) ? one/gmod.norm() : ss/sHs; lambda = std::max(lambdaMin_,std::min(lambdaTmp,lambdaMax_)); pgstep(pwa2, pwa, nobj, y, gmod.dual(), alpha, tol); // pass pwa by reference? *pwa? @@ -807,180 +807,6 @@ void TrustRegionAlgorithm::dprox(Vector &x, } } -// BRACKETING AND BRENTS FOR UNTRANSFORMED MULTIPLIER -//template -//void TrustRegionSPGAlgorithm::dprox(Vector &x, -// const Vector &x0, -// Real del, -// Vector &y0, -// Vector &y1, -// Vector &yc, -// Vector &pwa, -// std::ostream &outStream) const { -// // Solve ||P(t*x0 + (1-t)*(x-x0))-x0|| = del using Brent's method -// const Real zero(0), half(0.5), one(1), two(2), three(3); -// const Real eps(ROL_EPSILON()), tol0(1e1*eps), fudge(1.0-1e-2*sqrt(eps)); -// Real f0(0), f1(0), fc(0), u0(0), u1(0), uc(0), t0(1), t1(0), tc(0), d1(1), d2(1), tol(1); -// Real p(0), q(0), r(0), s(0), m(0); -// int cnt(state_->nproj); -// y0.set(x); -// proj_->project(y0,outStream); state_->nproj++; -// pwa.set(y0); pwa.axpy(-one,x0); -// f0 = pwa.norm(); -// if (f0 <= del) { -// x.set(y0); -// return; -// } -// -// // Bracketing -// t1 = static_cast(1e-1); -// f1 = one+del; -// while (f1 >= del) { -// t1 *= static_cast(5e-2); -// y1.set(x); y1.scale(t1); y1.axpy(one-t1,x0); -// proj_->project(y1,outStream); state_->nproj++; -// pwa.set(y1); pwa.axpy(-one,x0); -// f1 = pwa.norm(); -// } -// u1 = (one-t1)/t1; -// -// // Brents -// uc = u0; tc = t0; fc = f0; yc.set(y0); -// d1 = u1-u0; d2 = d1; -// int code = 0; -// while (true) { -// if (std::abs(fc-del) < std::abs(f1-del)) { -// u0 = u1; u1 = uc; uc = u0; -// t0 = t1; t1 = tc; tc = t0; -// f0 = f1; f1 = fc; fc = f0; -// y0.set(y1); y1.set(yc); yc.set(y0); -// } -// tol = two*eps*abs(u1) + half*tol0; -// m = half*(uc - u1); -// if (std::abs(m) <= tol) { code = 1; break; } -// if ((f1 >= fudge*del && f1 <= del)) break; -// if (std::abs(d1) < tol || std::abs(f0-del) <= std::abs(f1-del)) { -// d1 = m; d2 = d1; -// } -// else { -// s = (f1-del)/(f0-del); -// if (u0 == uc) { -// p = two*m*s; -// q = one-s; -// } -// else { -// q = (f0-del)/(fc-del); -// r = (f1-del)/(fc-del); -// p = s*(two*m*q*(q-r)-(u1-u0)*(r-one)); -// q = (q-one)*(r-one)*(s-one); -// } -// if (p > zero) q = -q; -// else p = -p; -// s = d1; -// d1 = d2; -// if (two*p < three*m*q-std::abs(tol*q) && p < std::abs(half*s*q)) { -// d2 = p/q; -// } -// else { -// d1 = m; d2 = d1; -// } -// } -// u0 = u1; t0 = t1; f0 = f1; y0.set(y1); -// if (std::abs(d2) > tol) u1 += d2; -// else if (m > zero) u1 += tol; -// else u1 -= tol; -// t1 = one/(one+u1); -// y1.set(x); y1.scale(t1); y1.axpy(one-t1,x0); -// proj_->project(y1,outStream); state_->nproj++; -// pwa.set(y1); pwa.axpy(-one,x0); -// f1 = pwa.norm(); -// if ((f1 > del && fc > del) || (f1 <= del && fc <= del)) { -// uc = u0; tc = t0; fc = f0; yc.set(y0); -// d1 = u1-u0; d2 = d1; -// } -// } -// if (code==1 && f1>del) x.set(yc); -// else x.set(y1); -// if (verbosity_ > 1) { -// outStream << std::endl; -// outStream << " Trust-Region Subproblem Projection" << std::endl; -// outStream << " Number of polyhedral projections: " << state_->nproj-cnt << std::endl; -// if (code == 1 && f1 > del) { -// outStream << " Multiplier: " << uc << std::endl; -// outStream << " Transformed Multiplier: " << tc << std::endl; -// outStream << " Dual Residual: " << fc-del << std::endl; -// } -// else { -// outStream << " Multiplier: " << u1 << std::endl; -// outStream << " Transformed Multiplier: " << t1 << std::endl; -// outStream << " Dual Residual: " << f1-del << std::endl; -// } -// outStream << " Exit Code: " << code << std::endl; -// outStream << std::endl; -// } -//} - -// RIDDERS' METHOD FOR TRUST-REGION PROJECTION -//template -//void TrustRegionSPGAlgorithm::dprox(Vector &x, -// const Vector &x0, -// Real del, -// Vector &y, -// Vector &y1, -// Vector &yc, -// Vector &p, -// std::ostream &outStream) const { -// // Solve ||P(t*x0 + (1-t)*(x-x0))-x0|| = del using Ridder's method -// const Real half(0.5), one(1), tol(1e1*ROL_EPSILON()); -// const Real fudge(1.0-1e-2*std::sqrt(ROL_EPSILON())); -// Real e0(0), e1(0), e2(0), e(0), a0(0), a1(0.5), a2(1), a(0); -// int cnt(state_->nproj); -// y.set(x); -// proj_->project(y,outStream); state_->nproj++; -// p.set(y); p.axpy(-one,x0); -// e2 = p.norm(); -// if (e2 <= del) { -// x.set(y); -// return; -// } -// bool code = 1; -// while (a2-a0 > tol) { -// a1 = half*(a0+a2); -// y.set(x); y.scale(a1); y.axpy(one-a1,x0); -// proj_->project(y,outStream); state_->nproj++; -// p.set(y); p.axpy(-one,x0); -// e1 = p.norm(); -// if (e1 >= fudge*del && e1 <= del) break; -// a = a1-(a1-a0)*(e1-del)/std::sqrt((e1-del)*(e1-del)-(e0-del)*(e2-del)); -// y.set(x); y.scale(a); y.axpy(one-a,x0); -// proj_->project(y,outStream); state_->nproj++; -// p.set(y); p.axpy(-one,x0); -// e = p.norm(); -// if (e < fudge*del) { -// if (e1 < fudge*del) { e0 = (a < a1 ? e1 : e); a0 = (a < a1 ? a1 : a); } -// else { e0 = e; a0 = a; e2 = e1; a2 = a1; }; -// } -// else if (e > del) { -// if (e1 < fudge*del) { e0 = e1; a0 = a1; e2 = e; a2 = a; } -// else { e2 = (a < a1 ? e : e1); a2 = (a < a1 ? a : a1); } -// } -// else { -// code = 0; -// break; // Exit if fudge*del <= snorm <= del -// } -// } -// x.set(y); -// if (verbosity_ > 1) { -// outStream << std::endl; -// outStream << " Trust-Region Subproblem Projection" << std::endl; -// outStream << " Number of polyhedral projections: " << state_->nproj-cnt << std::endl; -// outStream << " Transformed Multiplier: " << a1 << std::endl; -// outStream << " Dual Residual: " << e1-del << std::endl; -// outStream << " Exit Code: " << code << std::endl; -// outStream << std::endl; -// } -//} - template void TrustRegionAlgorithm::writeHeader( std::ostream& os ) const { std::stringstream hist; From 8480885138d50d8d29c9e4b4e4fb6d8cf8f897f9 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Thu, 5 Jan 2023 14:22:47 -0700 Subject: [PATCH 32/65] Removed uneccessary recomputation of nonsmooth objective value. --- .../algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp index daff8eedb688..3d2ac11c1d9a 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp @@ -291,8 +291,6 @@ void TrustRegionAlgorithm::run(Vector &x, // Compute trial objective value strial = computeValue(inTol,outTol,pRed,state_->svalue,state_->iter,x,*state_->iterateVec,sobj); - nobj.update(x, UpdateType::Trial); - ntrial = nobj.value(x,outTol); state_->nnval++; Ftrial = strial + ntrial; // Compute ratio of acutal and predicted reduction @@ -708,6 +706,9 @@ void TrustRegionAlgorithm::dspg(Vector &y, if (useNMSP_ && useMin_) { sval = sval_min; nval = nval_min; y.set(ymin); } + else { + sval = sold; nval = nold; + } SPflag_ = (SPiter_==maxit_) ? 1 : 0; } From 087252a1b1e96f4da951ee89ba2f2c4d16aa33b7 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Fri, 6 Jan 2023 16:19:15 -0700 Subject: [PATCH 33/65] Added a linesearch inexact proximal Newton method based on Josephy's Newton method for generalized equations and the Dontchev/Rockafellar analysis for inexact Newton. This method first computes a proximal gradient step and then improves upon the pg step by solving the problem min 1/2 + + f(x_k) + g(x), where f is a smooth objective function and g is a nonsmooth, convex objective function. If the computed step is not a descent direction, then the method defaults to the originally computed pg step. Also added a test for this method. --- .../ROL_TypeP_InexactNewtonAlgorithm.hpp | 168 +++++++++ .../ROL_TypeP_InexactNewtonAlgorithm_Def.hpp | 331 ++++++++++++++++++ .../rol/test/algorithm/TypeP/CMakeLists.txt | 10 +- packages/rol/test/algorithm/TypeP/test_06.cpp | 185 ++++++++++ 4 files changed, 693 insertions(+), 1 deletion(-) create mode 100644 packages/rol/src/algorithm/TypeP/ROL_TypeP_InexactNewtonAlgorithm.hpp create mode 100644 packages/rol/src/algorithm/TypeP/ROL_TypeP_InexactNewtonAlgorithm_Def.hpp create mode 100644 packages/rol/test/algorithm/TypeP/test_06.cpp diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_InexactNewtonAlgorithm.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_InexactNewtonAlgorithm.hpp new file mode 100644 index 000000000000..a4b546ae88c6 --- /dev/null +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_InexactNewtonAlgorithm.hpp @@ -0,0 +1,168 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +#ifndef ROL_TYPEP_INEXACTNEWTONALGORITHM_HPP +#define ROL_TYPEP_INEXACTNEWTONALGORITHM_HPP + +#include "ROL_TypeP_Algorithm.hpp" + +/** \class ROL::TypeP::InexactNewtonAlgorithm + \brief Provides an interface to run the inexact proximal Newton algorithm. +*/ + +namespace ROL { +namespace TypeP { + +template +class InexactNewtonAlgorithm : public TypeP::Algorithm { +private: + int t0_; + bool initProx_; + + int maxit_; ///< Maximum number of line search steps (default: 20) + Real rhodec_; ///< Backtracking rate (default: 0.5) + Real c1_; ///< Sufficient Decrease Parameter (default: 1e-4) + Real sigma1_; ///< Lower safeguard for quadratic line search (default: 0.1) + Real sigma2_; ///< Upper safeguard for quadratic line search (default: 0.9) + Real sp_tol1_; + Real sp_tol2_; + Real sp_exp_; + Real sp_tol_min_; + std::string algoName_; + + ParameterList list_; + + int ls_nfval_, spgIter_, nhess_; + int verbosity_; + bool writeHeader_; + + using TypeP::Algorithm::pgstep; + using TypeP::Algorithm::status_; + using TypeP::Algorithm::state_; + + class NewtonObj : public Objective { + private: + const Ptr> obj_; + const Ptr> x_; + const Ptr> g_; + Ptr> pwa_, dwa_, Hx_; + bool isHessApplied_; + int nhess_; + + public: + NewtonObj(const Ptr> &obj, const Vector &x, const Vector &g) + : obj_(obj), x_(x.clone()), g_(g.clone()), pwa_(x.clone()), + dwa_(g.clone()), Hx_(g.clone()), isHessApplied_(false), nhess_(0) {} + void update(const Vector &x, UpdateType type, int iter) { + isHessApplied_ = false; + } + Real value(const Vector &x, Real &tol) { + const Real half(0.5), one(1); + pwa_->set(x); pwa_->axpy(-one,*x_); + if (!isHessApplied_) { + obj_->hessVec(*Hx_,*pwa_,*x_,tol); nhess_++; + isHessApplied_ = true; + } + dwa_->set(*Hx_); + dwa_->scale(half); + dwa_->plus(*g_); + return dwa_->apply(*pwa_); + } + void gradient(Vector &g, const Vector &x, Real &tol) { + const Real one(1); + if (!isHessApplied_) { + pwa_->set(x); pwa_->axpy(-one,*x_); + obj_->hessVec(*Hx_,*pwa_,*x_,tol); nhess_++; + isHessApplied_ = true; + } + g.set(*Hx_); + g.plus(*g_); + } + void hessVec(Vector &hv, const Vector &v, const Vector &x, Real &tol) { + obj_->hessVec(hv,v,*x_,tol); nhess_++; + } + int numHessVec(bool reset = true) { + int nhess = nhess_; + if (reset) nhess_ = 0; + return nhess; + } + void setData(const Vector &x, const Vector &g) { + x_->set(x); + g_->set(g); + } + }; + + void initialize(Vector &x, + const Vector &g, + Objective &sobj, + Objective &nobj, + Vector &dg, + Vector &px, + std::ostream &outStream = std::cout); + +public: + + InexactNewtonAlgorithm(ParameterList &list); + + using TypeP::Algorithm::run; + + void run( Vector &x, + const Vector &g, + Objective &sobj, + Objective &nobj, + std::ostream &outStream = std::cout) override; + + void writeHeader( std::ostream& os ) const override; + + void writeName( std::ostream& os ) const override; + + void writeOutput( std::ostream &os, bool write_header = false ) const override; + +}; // class ROL::TypeP::InexactNewtonAlgorithm + +} // namespace TypeP +} // namespace ROL + +#include "ROL_TypeP_InexactNewtonAlgorithm_Def.hpp" + +#endif diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_InexactNewtonAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_InexactNewtonAlgorithm_Def.hpp new file mode 100644 index 000000000000..444969ca3ed1 --- /dev/null +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_InexactNewtonAlgorithm_Def.hpp @@ -0,0 +1,331 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +#ifndef ROL_TYPEP_QUASINEWTONALGORITHM_DEF_HPP +#define ROL_TYPEP_QUASINEWTONALGORITHM_DEF_HPP + +#include "ROL_TypeP_ProxGradientAlgorithm.hpp" +#include "ROL_TypeP_SpectralGradientAlgorithm.hpp" +#include "ROL_TypeP_iPianoAlgorithm.hpp" +#include "ROL_TypeP_TrustRegionAlgorithm.hpp" + +namespace ROL { +namespace TypeP { + +template +InexactNewtonAlgorithm::InexactNewtonAlgorithm(ParameterList &list) + : list_(list) { + // Set status test + status_->reset(); + status_->add(makePtr>(list)); + + // Parse parameter list + ParameterList &lslist = list.sublist("Step").sublist("Line Search"); + t0_ = list.sublist("Status Test").get("Gradient Scale" , 1.0); + initProx_ = lslist.get("Apply Prox to Initial Guess", false); + maxit_ = lslist.get("Function Evaluation Limit", 20); + c1_ = lslist.get("Sufficient Decrease Tolerance", 1e-4); + rhodec_ = lslist.sublist("Line-Search Method").get("Backtracking Rate", 0.5); + sigma1_ = lslist.sublist("PQN").get("Lower Step Size Safeguard", 0.1); + sigma2_ = lslist.sublist("PQN").get("Upper Step Size Safeguard", 0.9); + algoName_ = lslist.sublist("PQN").get("Subproblem Solver","Spectral Gradient"); + int sp_maxit = lslist.sublist("PQN").get("Subproblem Iteration Limit", 1000); + sp_tol1_ = lslist.sublist("PQN").get("Subproblem Absolute Tolerance", 1e-4); + sp_tol2_ = lslist.sublist("PQN").get("Subproblem Relative Tolerance", 1e-2); + sp_exp_ = lslist.sublist("PQN").get("Subproblem Tolerance Exponent", 1.0); + Real opt_tol = lslist.sublist("Status Test").get("Gradient Tolerance", 1e-8); + sp_tol_min_ = static_cast(1e-4)*opt_tol; + verbosity_ = list.sublist("General").get("Output Level", 0); + writeHeader_ = verbosity_ > 2; + + list_.sublist("Status Test").set("Iteration Limit", sp_maxit); + list_.sublist("General").set("Output Level", verbosity_>0 ? verbosity_-1 : 0); +} + + +template +void InexactNewtonAlgorithm::initialize(Vector &x, + const Vector &g, + Objective &sobj, + Objective &nobj, + Vector &dg, + Vector &px, + std::ostream &outStream) { + const Real one(1); + Real tol(std::sqrt(ROL_EPSILON())); + // Initialize data + TypeP::Algorithm::initialize(x,g); + // Update approximate gradient and approximate objective function. + Real ftol = std::sqrt(ROL_EPSILON()); + if (initProx_) { + state_->iterateVec->set(x); + nobj.prox(x,*state_->iterateVec,one,tol); state_->nprox++; + } + sobj.update(x,UpdateType::Initial,state_->iter); + nobj.update(x,UpdateType::Initial,state_->iter); + state_->svalue = sobj.value(x,ftol); state_->nsval++; + state_->nvalue = nobj.value(x,ftol); state_->nnval++; + state_->value = state_->svalue + state_->nvalue; + sobj.gradient(*state_->gradientVec,x,ftol); state_->ngrad++; + dg.set(state_->gradientVec->dual()); + pgstep(*state_->iterateVec,px,nobj,x,dg,t0_,tol); + state_->gnorm = px.norm() / t0_; + state_->snorm = ROL_INF(); + nhess_ = 0; +} + +template +void InexactNewtonAlgorithm::run( Vector &x, + const Vector &g, + Objective &sobj, + Objective &nobj, + std::ostream &outStream ) { + const Real half(0.5), one(1), eps(ROL_EPSILON()); + // Initialize trust-region data + Ptr> s = x.clone(), gp = x.clone(), xs = x.clone(), px = x.clone(); + initialize(x,g,sobj,nobj,*gp,*px,outStream); + Real strial(0), ntrial(0), ftrial(0), gs(0), Qk(0), rhoTmp(0); + Real tol(std::sqrt(ROL_EPSILON())), gtol(1); + + Ptr> algo; + Ptr qobj = makePtr(makePtrFromRef(sobj),x,g); + + // Output + if (verbosity_ > 0) writeOutput(outStream,true); + + // Compute steepest descent step + xs->set(*state_->iterateVec); + state_->iterateVec->set(x); + while (status_->check(*state_)) { + qobj->setData(x,*state_->gradientVec); + // Compute step + gtol = std::max(sp_tol_min_,std::min(sp_tol1_,sp_tol2_*std::pow(state_->gnorm,sp_exp_))); + list_.sublist("Status Test").set("Gradient Tolerance",gtol); + if (algoName_ == "Line Search") algo = makePtr>(list_); + else if (algoName_ == "iPiano") algo = makePtr>(list_); + else if (algoName_ == "Trust Region") algo = makePtr>(list_); + else algo = makePtr>(list_); + algo->run(*xs,*qobj,nobj,outStream); + s->set(*xs); s->axpy(-one,x); + spgIter_ = algo->getState()->iter; + nhess_ += qobj->numHessVec(); + state_->nprox += staticPtrCast>(algo->getState())->nprox; + + // Perform backtracking line search + state_->searchSize = one; + x.set(*state_->iterateVec); + x.axpy(state_->searchSize,*s); + sobj.update(x,UpdateType::Trial); + nobj.update(x,UpdateType::Trial); + strial = sobj.value(x,tol); + ntrial = nobj.value(x,tol); + ftrial = strial + ntrial; + ls_nfval_ = 1; + gs = state_->gradientVec->apply(*s); + Qk = gs + ntrial - state_->nvalue; + if (verbosity_ > 1) { + outStream << " In TypeP::InexactNewtonAlgorithm: Line Search" << std::endl; + outStream << " Step size: " << state_->searchSize << std::endl; + outStream << " Trial objective value: " << ftrial << std::endl; + outStream << " Computed reduction: " << state_->value-ftrial << std::endl; + outStream << " Dot product of gradient and step: " << gs << std::endl; + outStream << " Sufficient decrease bound: " << -Qk*c1_ << std::endl; + outStream << " Number of function evaluations: " << ls_nfval_ << std::endl; + } + if (Qk > -eps) { + s->set(*px); + x.set(*state_->iterateVec); + x.axpy(state_->searchSize,*s); + sobj.update(x,UpdateType::Trial); + nobj.update(x,UpdateType::Trial); + strial = sobj.value(x,tol); + ntrial = nobj.value(x,tol); + ftrial = strial + ntrial; + ls_nfval_++; + gs = state_->gradientVec->apply(*s); + Qk = gs + ntrial - state_->nvalue; + } + while ( ftrial > state_->value + c1_*Qk && ls_nfval_ < maxit_ ) { + rhoTmp = -half * Qk / (strial-state_->svalue-state_->searchSize*gs); + state_->searchSize = ((sigma1_ <= rhoTmp && rhoTmp <= sigma2_) ? rhoTmp : rhodec_) * state_->searchSize; + x.set(*state_->iterateVec); + x.axpy(state_->searchSize,*s); + sobj.update(x,UpdateType::Trial); + nobj.update(x,UpdateType::Trial); + strial = sobj.value(x,tol); + ntrial = nobj.value(x,tol); + ftrial = strial + ntrial; + Qk = state_->searchSize * gs + ntrial - state_->nvalue; + ls_nfval_++; + if (verbosity_ > 1) { + outStream << std::endl; + outStream << " Step size: " << state_->searchSize << std::endl; + outStream << " Trial objective value: " << ftrial << std::endl; + outStream << " Computed reduction: " << state_->value-ftrial << std::endl; + outStream << " Dot product of gradient and step: " << gs << std::endl; + outStream << " Sufficient decrease bound: " << -Qk*c1_ << std::endl; + outStream << " Number of function evaluations: " << ls_nfval_ << std::endl; + } + } + state_->nsval += ls_nfval_; + state_->nnval += ls_nfval_; + + // Compute norm of step + state_->stepVec->set(*s); + state_->stepVec->scale(state_->searchSize); + state_->snorm = state_->stepVec->norm(); + + // Update iterate + state_->iterateVec->set(x); + + // Compute new value and gradient + state_->iter++; + state_->value = ftrial; + state_->svalue = strial; + state_->nvalue = ntrial; + sobj.update(x,UpdateType::Accept,state_->iter); + nobj.update(x,UpdateType::Accept,state_->iter); + sobj.gradient(*state_->gradientVec,x,tol); state_->ngrad++; + gp->set(state_->gradientVec->dual()); + + // Compute projected gradient norm + pgstep(*xs,*px,nobj,x,*gp,t0_,tol); + state_->gnorm = s->norm() / t0_; + + // Update Output + if (verbosity_ > 0) writeOutput(outStream,writeHeader_); + } + if (verbosity_ > 0) TypeP::Algorithm::writeExitStatus(outStream); +} + +template +void InexactNewtonAlgorithm::writeHeader( std::ostream& os ) const { + std::stringstream hist; + if (verbosity_ > 1) { + hist << std::string(114,'-') << std::endl; + hist << "Line-Search Inexact Proximal Newton"; + hist << " status output definitions" << std::endl << std::endl; + hist << " iter - Number of iterates (steps taken)" << std::endl; + hist << " value - Objective function value" << std::endl; + hist << " gnorm - Norm of the gradient" << std::endl; + hist << " snorm - Norm of the step (update to optimization vector)" << std::endl; + hist << " alpha - Line search step length" << std::endl; + hist << " #sval - Cumulative number of times the smooth objective function was evaluated" << std::endl; + hist << " #nval - Cumulative number of times the nonsmooth objective function was evaluated" << std::endl; + hist << " #grad - Cumulative number of times the gradient was computed" << std::endl; + hist << " #hess - Cumulative number of times the Hessian was applied" << std::endl; + hist << " #prox - Cumulative number of times the projection was computed" << std::endl; + hist << " ls_#fval - Number of the times the objective function was evaluated during the line search" << std::endl; + hist << " sp_iter - Number iterations to compute quasi-Newton step" << std::endl; + hist << std::string(114,'-') << std::endl; + } + + hist << " "; + hist << std::setw(6) << std::left << "iter"; + hist << std::setw(15) << std::left << "value"; + hist << std::setw(15) << std::left << "gnorm"; + hist << std::setw(15) << std::left << "snorm"; + hist << std::setw(15) << std::left << "alpha"; + hist << std::setw(10) << std::left << "#sval"; + hist << std::setw(10) << std::left << "#nval"; + hist << std::setw(10) << std::left << "#grad"; + hist << std::setw(10) << std::left << "#hess"; + hist << std::setw(10) << std::left << "#prox"; + hist << std::setw(10) << std::left << "#ls_fval"; + hist << std::setw(10) << std::left << "sp_iter"; + hist << std::endl; + os << hist.str(); +} + +template +void InexactNewtonAlgorithm::writeName( std::ostream& os ) const { + std::stringstream hist; + hist << std::endl << "Line-Search Inexact Proximal Newton (Type P)" << std::endl; + os << hist.str(); +} + +template +void InexactNewtonAlgorithm::writeOutput( std::ostream& os, bool write_header ) const { + std::stringstream hist; + hist << std::scientific << std::setprecision(6); + if ( state_->iter == 0 ) writeName(os); + if ( write_header ) writeHeader(os); + if ( state_->iter == 0 ) { + hist << " "; + hist << std::setw(6) << std::left << state_->iter; + hist << std::setw(15) << std::left << state_->value; + hist << std::setw(15) << std::left << state_->gnorm; + hist << std::setw(15) << std::left << "---"; + hist << std::setw(15) << std::left << "---"; + hist << std::setw(10) << std::left << state_->nsval; + hist << std::setw(10) << std::left << state_->nnval; + hist << std::setw(10) << std::left << state_->ngrad; + hist << std::setw(10) << std::left << nhess_; + hist << std::setw(10) << std::left << state_->nprox; + hist << std::setw(10) << std::left << "---"; + hist << std::setw(10) << std::left << "---"; + hist << std::endl; + } + else { + hist << " "; + hist << std::setw(6) << std::left << state_->iter; + hist << std::setw(15) << std::left << state_->value; + hist << std::setw(15) << std::left << state_->gnorm; + hist << std::setw(15) << std::left << state_->snorm; + hist << std::setw(15) << std::left << state_->searchSize; + hist << std::setw(10) << std::left << state_->nsval; + hist << std::setw(10) << std::left << state_->nnval; + hist << std::setw(10) << std::left << state_->ngrad; + hist << std::setw(10) << std::left << nhess_; + hist << std::setw(10) << std::left << state_->nprox; + hist << std::setw(10) << std::left << ls_nfval_; + hist << std::setw(10) << std::left << spgIter_; + hist << std::endl; + } + os << hist.str(); +} + +} // namespace TypeP +} // namespace ROL + +#endif diff --git a/packages/rol/test/algorithm/TypeP/CMakeLists.txt b/packages/rol/test/algorithm/TypeP/CMakeLists.txt index 853bc3cff040..a1f308fb6e18 100644 --- a/packages/rol/test/algorithm/TypeP/CMakeLists.txt +++ b/packages/rol/test/algorithm/TypeP/CMakeLists.txt @@ -27,7 +27,7 @@ TRIBITS_ADD_EXECUTABLE_AND_TEST( ) TRIBITS_ADD_EXECUTABLE_AND_TEST( - TrustRegion + TrustRegion SOURCES test_04.cpp ARGS PrintItAll NUM_MPI_PROCS 1 @@ -44,6 +44,14 @@ TRIBITS_ADD_EXECUTABLE_AND_TEST( ADD_DIR_TO_NAME ) +TRIBITS_ADD_EXECUTABLE_AND_TEST( + InexactNewton + SOURCES test_06.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) TRIBITS_COPY_FILES_TO_BINARY_DIR( TypePTestDataCopy diff --git a/packages/rol/test/algorithm/TypeP/test_06.cpp b/packages/rol/test/algorithm/TypeP/test_06.cpp new file mode 100644 index 000000000000..bae92fe7e106 --- /dev/null +++ b/packages/rol/test/algorithm/TypeP/test_06.cpp @@ -0,0 +1,185 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +/*! \file test_06.cpp + \brief Validate inexact proximal Newton algorithm. +*/ + +#include "ROL_TypeP_InexactNewtonAlgorithm.hpp" +#include "ROL_StdObjective.hpp" +#include "ROL_l1Objective.hpp" +#include "ROL_Stream.hpp" +#include "Teuchos_GlobalMPISession.hpp" + +template +class QuadraticTypeP_Test01 : public ROL::StdObjective { +private: + int dim_; + std::vector a_, b_; + +public: + QuadraticTypeP_Test01(int dim) : dim_(dim) { + a_.resize(dim); + b_.resize(dim); + for (int i = 0; i < dim; ++i) { + a_[i] = static_cast(5)*static_cast(rand())/static_cast(RAND_MAX); + b_[i] = static_cast(20)*static_cast(rand())/static_cast(RAND_MAX) - static_cast(10); + } + } + + Real value(const std::vector &x, Real &tol) { + Real val(0); + for (int i = 0; i < dim_; ++i) + val += static_cast(0.5)*a_[i]*x[i]*x[i] + b_[i]*x[i]; + return val; + } + + void gradient(std::vector &g, const std::vector &x, Real &tol) { + for (int i = 0; i < dim_; ++i) + g[i] = a_[i]*x[i] + b_[i]; + } + + void hessVec(std::vector &hv, const std::vector &v, const std::vector &x, Real &tol) { + for (int i = 0; i < dim_; ++i) + hv[i] = a_[i]*v[i]; + } + + void getSolution(std::vector &x, const std::vector &wts, const std::vector &y) const { + for (int i = 0; i < dim_; ++i) + x[i] = (std::min(wts[i], std::max(-wts[i], a_[i]*y[i] + b_[i])) - b_[i]) / a_[i]; + } +}; + +typedef double RealT; + +int main(int argc, char *argv[]) { + + Teuchos::GlobalMPISession mpiSession(&argc, &argv); + + // This little trick lets us print to std::cout only if a + // (dummy) command-line argument is provided. + int iprint = argc - 1; + ROL::Ptr outStream; + ROL::nullstream bhs; // outputs nothing + if (iprint > 0) + outStream = ROL::makePtrFromRef(std::cout); + else + outStream = ROL::makePtrFromRef(bhs); + + int errorFlag = 0; + + try { + RealT tol = 1e2*std::sqrt(ROL::ROL_EPSILON()); + + ROL::ParameterList list; + list.sublist("General").set("Output Level",iprint); + list.sublist("Step").set("Type","iPiano"); + list.sublist("Status Test").set("Gradient Tolerance",1e-7); + list.sublist("Status Test").set("Constraint Tolerance",1e-8); + list.sublist("Status Test").set("Step Tolerance",1e-12); + list.sublist("Status Test").set("Iteration Limit", 100); + + int dim = 5; + ROL::Ptr> sol, wts, y; + ROL::Ptr> sobj; + ROL::Ptr> nobj; + ROL::Ptr> algo; + std::vector data; + RealT err(0); + + *outStream << std::endl << "Random Diagonal LASSO Test Problem" << std::endl << std::endl; + ROL::Ptr> wtsP = ROL::makePtr>(dim); + ROL::Ptr> yP = ROL::makePtr>(dim); + wts = ROL::makePtr>(wtsP); + y = ROL::makePtr>(yP); + sol = ROL::makePtr>(dim); + wts->randomize(static_cast(0),static_cast(1)); + y->randomize(static_cast(-5),static_cast(5)); + sol->zero(); + + nobj = ROL::makePtr>(wts,y); + sobj = ROL::makePtr>(dim); + + // Check derivatives of smooth function + ROL::Ptr> xd = sol->clone(); + xd->randomize(-1.0,1.0); + ROL::Ptr> yd = sol->clone(); + yd->randomize(-1.0,1.0); + ROL::Ptr> zd = sol->clone(); + zd->randomize(-1.0,1.0); + sobj->checkGradient(*xd,*yd,true,*outStream); + sobj->checkHessVec(*xd,*yd,true,*outStream); + sobj->checkHessSym(*xd,*yd,*zd,true,*outStream); + + algo = ROL::makePtr>(list); + algo->run(*sol,*sobj,*nobj,*outStream); + + std::vector xstar(dim); + sobj->getSolution(xstar, *wtsP, *yP); + data = *ROL::staticPtrCast>(sol)->getVector(); + *outStream << " Result: "; + for (int i = 0; i < dim; ++i) { + *outStream << " x" << i+1 << " = " << data[i]; + err = std::max(err,std::abs(data[i]-xstar[i])); + } + *outStream << std::endl; + *outStream << " Truth: "; + for (int i = 0; i < dim; ++i) { + *outStream << " x" << i+1 << " = " << xstar[i]; + } + *outStream << std::endl; + *outStream << " Max-Error = " << err << std::endl; + errorFlag += (err > tol ? 1 : 0); + } + catch (std::logic_error& err) { + *outStream << err.what() << "\n"; + errorFlag = -1000; + }; // end try + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return 0; +} From 52a37520c51c5392f62f4582ca7927b945bf32c2 Mon Sep 17 00:00:00 2001 From: Bobby Date: Fri, 6 Jan 2023 16:33:15 -0700 Subject: [PATCH 34/65] almost ncg --- .../TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp | 26 +- .../ROL_TypeP_TrustRegionAlgorithm_Def.hpp | 226 +++++++++++++++++- packages/rol/test/algorithm/TypeP/test_04.cpp | 2 +- 3 files changed, 239 insertions(+), 15 deletions(-) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp index 56179f06615c..54db405599fa 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp @@ -105,7 +105,10 @@ class TrustRegionAlgorithm : public TypeP::Algorithm { int maxSize_; bool useMin_; bool useNMSP_; - bool useSimpleSPG_; + Real algSelect_; + int ncgType_; + Real etaNCG_; + Real desPar_; // Inexactness Parameters std::vector useInexact_; @@ -208,7 +211,7 @@ class TrustRegionAlgorithm : public TypeP::Algorithm { Vector &dwa1, std::ostream &outStream = std::cout); - void dspg_simple(Vector &y, + void dspg2(Vector &y, Real &sval, Real &nval, Real &pRed, @@ -240,6 +243,25 @@ class TrustRegionAlgorithm : public TypeP::Algorithm { Vector &pwa5, Vector &dwa, std::ostream &outStream = std::cout); + + void dncg(Vector &y, + Real &sval, + Real &nval, + Vector &gmod, + const Vector &x, + Real del, + TrustRegionModel_U &model, + Objective &nobj, + Vector &px, + Vector &pwa, + Vector &pwa1, + Vector &pwa2, + Vector &pwa3, + Vector &pwa4, + Vector &pwa5, + Vector &dwa, + std::ostream &outStream = std::cout); + void dprox(Vector &x, const Vector &x0, diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp index a825e09cae66..70417c7cefe7 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp @@ -87,7 +87,7 @@ TrustRegionAlgorithm::TrustRegionAlgorithm(ParameterList &list, interpf_ = lmlist.sublist("Cauchy Point").get("Reduction Rate", 0.1); extrapf_ = lmlist.sublist("Cauchy Point").get("Expansion Rate", 10.0); qtol_ = lmlist.sublist("Cauchy Point").get("Decrease Tolerance", 1e-8); - // Subsolver (spectral projected gradient) parameters + // Subsolver (general) parameters lambdaMin_ = lmlist.sublist("Solver").get("Minimum Spectral Step Size", 1e-8); lambdaMax_ = lmlist.sublist("Solver").get("Maximum Spectral Step Size", 1e8); gamma_ = lmlist.sublist("Solver").get("Sufficient Decrease Tolerance", 1e-4); @@ -95,10 +95,15 @@ TrustRegionAlgorithm::TrustRegionAlgorithm(ParameterList &list, maxit_ = lmlist.sublist("Solver").get("Iteration Limit", 25); tol1_ = lmlist.sublist("Solver").get("Absolute Tolerance", 1e-4); tol2_ = lmlist.sublist("Solver").get("Relative Tolerance", 1e-2); - useMin_ = lmlist.sublist("Solver").get("Use Smallest Model Iterate", true); + // Subsolver (spectral projected gradient) parameters + useMin_ = lmlist.sublist("Solver").get("Use Smallest Model Iterate", true); useNMSP_ = lmlist.sublist("Solver").get("Use Nonmonotone Search", false); - useSimpleSPG_ = !lmlist.sublist("Solver").get("Compute Cauchy Point", true); - // Inexactness Information + algSelect_ = lmlist.sublist("Solver").get("Select Subproblem Solver", 3); + // Subsolver (nonlinear conjugate gradient) parameters) + ncgType_ = lmlist.sublist("Solver").get("Nonlinear CG Type", 1); + etaNCG_ = lmlist.sublist("Solver").get("Truncation Parameter for HZ CG", 1e-2); + desPar_ = lmlist.sublist("Solver").get("Descent parameter for Nonlinear CG", 0.2); + // Inexactness Information ParameterList &glist = list.sublist("General"); useInexact_.clear(); useInexact_.push_back(glist.get("Inexact Objective Function", false)); @@ -264,11 +269,7 @@ void TrustRegionAlgorithm::run(Vector &x, gmod->set(*state_->gradientVec); smodel = state_->svalue; ntrial = state_->nvalue; - if (useSimpleSPG_) - dspg_simple(x,smodel, ntrial, pRed, *gmod, *state_->iterateVec, - state_->searchSize, *model_, nobj, - *pwa1, *pwa2, *px, *dwa1, outStream); - else { + if (algSelect_==1){ // Compute Cauchy point (TRON notation: x = x[1]) dcauchy(*state_->stepVec,alpha_, smodel, ntrial, *state_->iterateVec, *dg, state_->searchSize, @@ -283,6 +284,18 @@ void TrustRegionAlgorithm::run(Vector &x, outStream); pRed = state_->value - (smodel+ntrial); } + else if (algSelect_==2) {// SPG2 + dspg2(x,smodel, ntrial, pRed, *gmod, *state_->iterateVec, + state_->searchSize, *model_, nobj, + *pwa1, *pwa2, *px, *dwa1, outStream); + } + else if (algSelect_==3){//NCG + dncg(x,smodel,ntrial,*gmod,*state_->iterateVec,state_->searchSize, + *model_,nobj,*px,*pwa2,*pwa3,*pwa4,*pwa5,*pwa6,*pwa7,*dwa1, + outStream);//doesn't output pRed + pRed = state_->value - (smodel+ntrial);//compute pRed here + + } // Update storage and compute predicted reduction //pRed = -q; // now updated in dcauchy/dspg @@ -295,7 +308,7 @@ void TrustRegionAlgorithm::run(Vector &x, ntrial = nobj.value(x,outTol); state_->nnval++; Ftrial = strial + ntrial; - // Compute ratio of acutal and predicted reduction + // Compute ratio of actual and predicted reduction TRflag_ = TRUtils::SUCCESS; TRUtils::analyzeRatio(rho,TRflag_,state_->value,Ftrial,pRed,eps_,outStream,verbosity_>1); if (useNM_) { @@ -464,7 +477,7 @@ Real TrustRegionAlgorithm::dcauchy(Vector &s, } template -void TrustRegionAlgorithm::dspg_simple(Vector &y, +void TrustRegionAlgorithm::dspg2(Vector &y, Real &sval, Real &nval, Real &pRed, @@ -523,7 +536,7 @@ void TrustRegionAlgorithm::dspg_simple(Vector &y, nval = nobj.value(pwa2,tol); // Perform line search - alphaMax = 1; + alphaMax = one; if (snorm >= del-safeguard) { // Trust-region constraint is violated ss0 = pwa1.dot(pwa); alphaMax = std::min(one, (-ss0 + std::sqrt(ss0*ss0 - ss*(s0s0-del*del)))/ss); @@ -807,6 +820,195 @@ void TrustRegionAlgorithm::dprox(Vector &x, } } +// NCG Subsolver +template +void TrustRegionAlgorithm::dncg(Vector &y,// x + Real &sval,//smodel + Real &nval, //ntrial + Vector &gmod, // gradient + const Vector &x,//iterateVec + Real del, + TrustRegionModel_U &model, + Objective &nobj, + Vector &px, + Vector &s, + Vector &dx, + Vector &pwa2, + Vector &pwa3, + Vector &dx0, + Vector &pwa5, + Vector &dwa, + std::ostream &outStream) { + // Use NCG to approximately solve TR subproblem: + // min 1/2 + + phi(y) subject to ||y|| \le del + // + // Inpute: + // y = Cauchy step + // x = Current iterate + // g = Current gradient + const Real half(0.5), one(1),zero(0); + const Real inf = ROL_INF(); + int NCGiter_(0); + Real mval(sval+nval); + Real tol(std::sqrt(ROL_EPSILON())), safeguard(tol); + Real hk(0),Qk(0), snorm(0), snorm0(0),gnorm(0),gnorm0(0),gnorm02(0),gnorm2(0), sHs(0), gs(0), ds(0), ss(0), nold(nval), sold(sval), mold(mval); + Real alphamax(1),sy(0),gg(0),eta_(0), alpha(alphamax), lambdaTmp(1), t0ncg(1); + Real beta(0), coeff(0); + bool reset(true); + + // Set y = x + y.set(x); + + // Compute initial step + coeff = t0_ / gmod.norm(); + t0ncg = std::max(lambdaMin_,std::min(coeff,lambdaMax_)); + pgstep(px, dx, nobj, y, gmod.dual(), t0ncg, tol);//solves from y, solution in px, step is pwa + s.set(dx); + gs = gmod.apply(s); // gs = + ss = s.dot(s); // Norm squared of step + snorm = std::sqrt(ss); // norm(step) + gnorm = snorm/t0_; // norm(step) / lambda + nval = nobj.value(px, tol); state_->nnval++; + + + // Compute initial projected gradient norm + const Real gtol = std::min(tol1_,tol2_*gnorm); + + if (verbosity_ > 1) + outStream << " Nonlinear Conjugate Gradient" << std::endl; + + NCGiter_ = 0; + while (NCGiter_ < maxit_) { + NCGiter_++; + snorm0 = snorm; + pwa3.set(y); + pwa3.axpy(one,s); + pwa3.axpy(-one,s); + snorm = pwa3.norm(); // y + s - x + alphamax = one; + + if (snorm >= (one - safeguard*del)){ + pwa3.set(y); + pwa3.axpy(-one,x);// here is y - x + ds = s.dot(pwa3); + ss = s.dot(s); + alphamax = std::min(one, (-ds + std::sqrt(ds*ds + ss*(del*del - snorm0*snorm0)))/ss); + } + + // Update quantities to evaluate quadratic model value and gradient + model.hessVec(dwa,s,x,tol); nhess_++; // dwa = H step + sHs = dwa.apply(s); // sHs = + if (sHs <= safeguard){ + alpha = alphamax; + } + else{ + alpha = std::min(alphamax, -(gs + nval - nold)/sHs); + } + + // Check compute alpha as the minimizer of an upper quadratic model + y.axpy(alpha, s); + gmod.axpy(alpha, dwa.dual()); // need dual here? + sold = sold + alpha*gs + half*alpha*alpha*sHs; + // Evaluate nonsmooth term + nobj.update(y,UpdateType::Trial); + nold = nobj.value(y,tol); state_->nnval++; + + // Check step size + pwa3.set(y);//temporary storage + pwa3.axpy(-one,x); + snorm = pwa3.norm(); + if (snorm>= (one-safeguard)*del){ + break; + } + + // Update spectral step length + if (sHs <= safeguard){ + lambdaTmp = t0_/gmod.norm(); + } + else { + lambdaTmp = s.dot(s); + } + + // Get steepest descent direction + dx0.set(dx); // solution of proximal step dx0. pwa2 = dx. pwa = s + gnorm0 = gnorm; + t0ncg = std::max(lambdaMin_, std::min(lambdaMax_, lambdaTmp)); + pgstep(px, dx, nobj, y, gmod.dual(), t0ncg, tol);//solves from y, solution in pwa2, step is pwa + gnorm = dx.norm(); + hk = gnorm/t0ncg; + + if (hk <= gtol){ + break; + } + gnorm2 = gnorm*gnorm; + gnorm02 = gnorm0*gnorm0; + //use pwa5 for dx - dx0 storage + pwa5.set(dx); + pwa5.axpy(-one, dx0); + if (ncgType_ == 0) {// FR + beta = gnorm2/gnorm02; + } + else if (ncgType_ == 1) {// PR+ + beta = std::max(zero, pwa5.dot(dx)/gnorm02); + } + else if (ncgType_ == 2) {// HZ + sy = s.dot(pwa5); + gg = dx.dot(dx0); + eta_ = -one/(s.norm()*std::min(etaNCG_, gnorm0)); + beta = std::max(eta_, (gnorm2 - gg - 2*s.dot(dx)*(gnorm2 - 2*gg+gnorm02)/sy)/sy); + } + else if (ncgType_ == 3){ // HS+ + beta = std::max(zero, -pwa5.dot(dx)/s.dot(pwa5)); + } + else if (ncgType_ == 4){// DY + + beta = std::max(zero, gnorm2/s.dot(pwa5)); + } + else if (ncgType_ == 5){//FRPR + beta = std::min(gnorm2, std::max(gnorm2, pwa5.dot(dx)))/gnorm02; + } + else{ //DYHS + beta = std::max(zero, std::min(-pwa5.dot(dx), gnorm2)/s.dot(pwa5)); + } + + reset = true; + + if (beta != zero && betannval++; //is this right? + Qk = gs + nval - nold; + if (Qk <= -(one - desPar_)*gnorm2/t0ncg){ + s.set(pwa5);//s = s0 + reset = false; + } + } + if (reset){// you don't take the NCG step + beta = zero; + s.set(dx); + nval = nobj.value(px,tol); state_->nnval++; + gs = gmod.dot(s); + } + + + if (verbosity_ > 1) { + outStream << std::endl; + outStream << " Iterate: " << SPiter_ << std::endl; + outStream << " Spectral step length (lambda): " << t0ncg << std::endl; + outStream << " Step length (alpha): " << alpha << std::endl; + outStream << " Model decrease (pRed): " << mval-mold << std::endl; + outStream << " Optimality criterion: " << gnorm << std::endl; + outStream << std::endl; + } + if (gnorm < gtol) break; + + } + s.set(y); + s.axpy(-one,x); + nval = nold; +} // BRACKETING AND BRENTS FOR UNTRANSFORMED MULTIPLIER //template //void TrustRegionSPGAlgorithm::dprox(Vector &x, diff --git a/packages/rol/test/algorithm/TypeP/test_04.cpp b/packages/rol/test/algorithm/TypeP/test_04.cpp index 9f3aeb00aec0..d4b278100d32 100644 --- a/packages/rol/test/algorithm/TypeP/test_04.cpp +++ b/packages/rol/test/algorithm/TypeP/test_04.cpp @@ -118,7 +118,7 @@ int main(int argc, char *argv[]) { list.sublist("Status Test").set("Constraint Tolerance",1e-8); list.sublist("Status Test").set("Step Tolerance",1e-12); list.sublist("Status Test").set("Iteration Limit", 1000); - + list.sublist("Step").sublist("Trust Region").sublist("Solver").set("Select Subproblem Solver", 3); int dim = 5; ROL::Ptr> sol, wts, y; ROL::Ptr> sobj; From 3accd1f7ddae13779c2a75482a1357975f3f342c Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Fri, 6 Jan 2023 16:33:56 -0700 Subject: [PATCH 35/65] Updated the algorithm factory. --- .../TypeB/ROL_TypeB_AlgorithmFactory.hpp | 2 +- .../TypeP/ROL_TypeP_AlgorithmFactory.hpp | 40 +++++++++++-------- .../ROL_TypeP_InexactNewtonAlgorithm_Def.hpp | 14 +++---- 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/packages/rol/src/algorithm/TypeB/ROL_TypeB_AlgorithmFactory.hpp b/packages/rol/src/algorithm/TypeB/ROL_TypeB_AlgorithmFactory.hpp index 968ace139f9f..e387734cfcab 100644 --- a/packages/rol/src/algorithm/TypeB/ROL_TypeB_AlgorithmFactory.hpp +++ b/packages/rol/src/algorithm/TypeB/ROL_TypeB_AlgorithmFactory.hpp @@ -152,7 +152,7 @@ inline Ptr> AlgorithmFactory(ParameterList &parlist) { = parlist.sublist("Step").sublist("Line Search").sublist("Descent Method").get("Type","Newton-Krylov"); if (desc=="Newton-Krylov" || desc=="Newton") return makePtr>(parlist); - else if (desc=="Quasi-Newton Method") { + else if (desc=="Quasi-Newton Method" || desc=="Quasi-Newton") { std::string method = parlist.sublist("Step").sublist("Line Search").sublist("Quasi-Newton").get("Method","L-Secant-B"); if (method == "L-Secant-B") diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_AlgorithmFactory.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_AlgorithmFactory.hpp index bab3393341f3..4d46667ba333 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_AlgorithmFactory.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_AlgorithmFactory.hpp @@ -49,6 +49,7 @@ #include "ROL_TypeP_iPianoAlgorithm.hpp" #include "ROL_TypeP_QuasiNewtonAlgorithm.hpp" #include "ROL_TypeP_TrustRegionAlgorithm.hpp" +#include "ROL_TypeP_InexactNewtonAlgorithm.hpp" #include "ROL_Types.hpp" namespace ROL { @@ -57,29 +58,26 @@ namespace TypeP { /** \enum ROL::EAlgorithmP \brief Enumeration of bound constrained algorithm types. - \arg ALGORITHM_P_PROXIMALGRADIENT describe + \arg ALGORITHM_P_LINESEARCH describe + \arg ALGORITHM_P_TRUSTREGION describe \arg ALGORITHM_P_SPECTRALGRADIENT describe \arg ALGORITHM_P_IPIANO describe - \arg ALGORITHM_P_QUASINEWTON describe - \arg ALGORITHM_P_TRUSTREGION describe */ enum EAlgorithmP{ - ALGORITHM_P_PROXIMALGRADIENT = 0, + ALGORITHM_P_LINESEARCH = 0, + ALGORITHM_P_TRUSTREGION, ALGORITHM_P_SPECTRALGRADIENT, ALGORITHM_P_IPIANO, - ALGORITHM_P_QUASINEWTON, - ALGORITHM_P_TRUSTREGION, ALGORITHM_P_LAST }; inline std::string EAlgorithmPToString(EAlgorithmP alg) { std::string retString; switch(alg) { - case ALGORITHM_P_PROXIMALGRADIENT: retString = "Proximal Gradient"; break; + case ALGORITHM_P_LINESEARCH: retString = "Line Search"; break; + case ALGORITHM_P_TRUSTREGION: retString = "Trust Region"; break; case ALGORITHM_P_SPECTRALGRADIENT: retString = "Spectral Gradient"; break; case ALGORITHM_P_IPIANO: retString = "iPiano"; break; - case ALGORITHM_P_QUASINEWTON: retString = "Quasi-Newton"; break; - case ALGORITHM_P_TRUSTREGION: retString = "Trust Region"; break; case ALGORITHM_P_LAST: retString = "Last Type (Dummy)"; break; default: retString = "INVALID EAlgorithmP"; } @@ -92,11 +90,10 @@ inline std::string EAlgorithmPToString(EAlgorithmP alg) { \return 1 if the argument is a valid AlgorithmP; 0 otherwise. */ inline int isValidAlgorithmP(EAlgorithmP alg){ - return( (alg == ALGORITHM_P_PROXIMALGRADIENT) || + return( (alg == ALGORITHM_P_LINESEARCH) || + (alg == ALGORITHM_P_TRUSTREGION) || (alg == ALGORITHM_P_SPECTRALGRADIENT) || (alg == ALGORITHM_P_IPIANO) || - (alg == ALGORITHM_P_QUASINEWTON) || - (alg == ALGORITHM_P_TRUSTREGION) || (alg == ALGORITHM_P_LAST) ); } @@ -123,23 +120,32 @@ inline EAlgorithmP operator--(EAlgorithmP &type, int) { inline EAlgorithmP StringToEAlgorithmP(std::string s) { s = removeStringFormat(s); - for ( EAlgorithmP alg = ALGORITHM_P_PROXIMALGRADIENT; alg < ALGORITHM_P_LAST; alg++ ) { + for ( EAlgorithmP alg = ALGORITHM_P_LINESEARCH; alg < ALGORITHM_P_LAST; alg++ ) { if ( !s.compare(removeStringFormat(EAlgorithmPToString(alg))) ) { return alg; } } - return ALGORITHM_P_SPECTRALGRADIENT; + return ALGORITHM_P_TRUSTREGION; } template inline Ptr> AlgorithmFactory(ParameterList &parlist) { EAlgorithmP ealg = StringToEAlgorithmP(parlist.sublist("Step").get("Type","Trust Region")); switch(ealg) { - case ALGORITHM_P_PROXIMALGRADIENT: return makePtr>(parlist); + case ALGORITHM_P_LINESEARCH: + { + std::string desc + = parlist.sublist("Step").sublist("Line Search").sublist("Descent Method").get("Type","Newton-Krylov"); + if (desc=="Newton-Krylov" || desc=="Newton") + return makePtr>(parlist); + else if (desc=="Quasi-Newton Method" || desc = "Quasi-Newton") + return makePtr>(parlist); + else + return makePtr>(parlist); + } + case ALGORITHM_P_TRUSTREGION: return makePtr>(parlist); case ALGORITHM_P_SPECTRALGRADIENT: return makePtr>(parlist); case ALGORITHM_P_IPIANO: return makePtr>(parlist); - case ALGORITHM_P_QUASINEWTON: return makePtr>(parlist); - case ALGORITHM_P_TRUSTREGION: return makePtr>(parlist); default: return nullPtr; } } diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_InexactNewtonAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_InexactNewtonAlgorithm_Def.hpp index 444969ca3ed1..862e0971c32b 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_InexactNewtonAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_InexactNewtonAlgorithm_Def.hpp @@ -66,13 +66,13 @@ InexactNewtonAlgorithm::InexactNewtonAlgorithm(ParameterList &list) maxit_ = lslist.get("Function Evaluation Limit", 20); c1_ = lslist.get("Sufficient Decrease Tolerance", 1e-4); rhodec_ = lslist.sublist("Line-Search Method").get("Backtracking Rate", 0.5); - sigma1_ = lslist.sublist("PQN").get("Lower Step Size Safeguard", 0.1); - sigma2_ = lslist.sublist("PQN").get("Upper Step Size Safeguard", 0.9); - algoName_ = lslist.sublist("PQN").get("Subproblem Solver","Spectral Gradient"); - int sp_maxit = lslist.sublist("PQN").get("Subproblem Iteration Limit", 1000); - sp_tol1_ = lslist.sublist("PQN").get("Subproblem Absolute Tolerance", 1e-4); - sp_tol2_ = lslist.sublist("PQN").get("Subproblem Relative Tolerance", 1e-2); - sp_exp_ = lslist.sublist("PQN").get("Subproblem Tolerance Exponent", 1.0); + sigma1_ = lslist.sublist("Inexact Newton").get("Lower Step Size Safeguard", 0.1); + sigma2_ = lslist.sublist("Inexact Newton").get("Upper Step Size Safeguard", 0.9); + algoName_ = lslist.sublist("Inexact Newton").get("Subproblem Solver","Spectral Gradient"); + int sp_maxit = lslist.sublist("Inexact Newton").get("Subproblem Iteration Limit", 1000); + sp_tol1_ = lslist.sublist("Inexact Newton").get("Subproblem Absolute Tolerance", 1e-4); + sp_tol2_ = lslist.sublist("Inexact Newton").get("Subproblem Relative Tolerance", 1e-2); + sp_exp_ = lslist.sublist("Inexact Newton").get("Subproblem Tolerance Exponent", 1.0); Real opt_tol = lslist.sublist("Status Test").get("Gradient Tolerance", 1e-8); sp_tol_min_ = static_cast(1e-4)*opt_tol; verbosity_ = list.sublist("General").get("Output Level", 0); From 7a8bb433360a1385863f4cfefb1534576bc85c98 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Fri, 6 Jan 2023 17:35:31 -0700 Subject: [PATCH 36/65] Added more "TypeP" objective functions: 1.) TypeBIndicatorObjective: Indicator function for linear constraints - Ax = b, l <= x <= u 2.) BallObjective: Indicator function for norm constraints - norm(x-x0) <= r Indicator functions return zero if the input x is feasible with respect to the constraint and infinity otherwise (implemented using ROL_INF). --- .../objective/ROL_BallIndicatorObjective.hpp | 92 ++++++++++++++++ .../objective/ROL_TypeBIndicatorObjective.hpp | 103 ++++++++++++++++++ 2 files changed, 195 insertions(+) create mode 100644 packages/rol/src/function/objective/ROL_BallIndicatorObjective.hpp create mode 100644 packages/rol/src/function/objective/ROL_TypeBIndicatorObjective.hpp diff --git a/packages/rol/src/function/objective/ROL_BallIndicatorObjective.hpp b/packages/rol/src/function/objective/ROL_BallIndicatorObjective.hpp new file mode 100644 index 000000000000..812772717c34 --- /dev/null +++ b/packages/rol/src/function/objective/ROL_BallIndicatorObjective.hpp @@ -0,0 +1,92 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +#ifndef ROL_BALLINDICATOROBJECTIVE_H +#define ROL_BALLINDICATOROBJECTIVE_H + +#include "ROL_Objective.hpp" + +/** @ingroup func_group + \class ROL::BallIndicatorObjective + \brief Provides the interface to evaluate the indicator function of norm constraints. + + --- +*/ + + +namespace ROL { + +template +class BallIndicatorObjective : public Objective { +private: + const Ptr> x_, pwa_; + const Real rad_; + +public: + + BallIndicatorObjective(const Ptr> &x, Real rad) + : x_(x), pwa_(x->clone()), rad_(rad) {} + + Real value( const Vector &x, Real &tol ) { + const Real zero(0), one(1); + pwa_->set(x); pwa_->axpy(-one,*x_); + Real norm = pwa_->norm(); + return (norm <= rad_) ? zero : ROL_INF(); + } + + void prox( Vector &Pv, const Vector &v, Real t, Real &tol){ + pwa_->set(v); pwa_->axpy(-one,*x_); + Real norm = pwa_->norm(); + if(norm <= rad_) { + Pv.set(v); + } + else { + Pv.set(*x_); + Pv.axpy(rad_/norm,*pwa_); + } + } +}; // class BallIndicatorObjective + +} // namespace ROL + +#endif diff --git a/packages/rol/src/function/objective/ROL_TypeBIndicatorObjective.hpp b/packages/rol/src/function/objective/ROL_TypeBIndicatorObjective.hpp new file mode 100644 index 000000000000..1789905e96df --- /dev/null +++ b/packages/rol/src/function/objective/ROL_TypeBIndicatorObjective.hpp @@ -0,0 +1,103 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +#ifndef ROL_TYPEBINDICATOROBJECTIVE_H +#define ROL_TYPEBINDICATOROBJECTIVE_H + +#include "ROL_Objective.hpp" +#include "ROL_PolyhedralProjectionFactory.hpp" + +/** @ingroup func_group + \class ROL::TypeBIndicatorObjective + \brief Provides the interface to evaluate the indicator function of linear constraints. + + --- +*/ + + +namespace ROL { + +template +class TypeBIndicatorObjective : public Objective { +private: + const Ptr> proj_; + const Ptr> res_; + +public: + + TypeBIndicatorObjective(const Ptr> &bnd) + : proj_(makePtr>(bnd)) {} + + TypeBIndicatorObjective(const Vector &xprim, + const Vector &xdual, + const Ptr> &bnd, + const Ptr> &con, + const Vector &mul, + const Vector &res, + ParameterList &list) + proj_(PolyhedralProjectionFactory(xprim,xdual,bnd,con,mul,res,list)), + res_(res.clone()) {} + + TypeBIndicatorObjective(const Ptr> &proj) + : proj_(proj), res_(proj->getResidual()->clone()) {} + + Real value( const Vector &x, Real &tol ) { + const Real zero(0), eps(ROL_EPSILON()); + Real val(0); + bool isBndFeasible = proj_->getBoundConstraint()->isFeasible(x); + bool isConFeasible = true; + if (res_ != nullPtr) { + proj_->getLinearConstraint()->value(*res_,x,tol); + if (res_->norm() > eps) isConFeasible = false; + } + return (isBndFeasible && isConFeasible) ? zero : ROL_INF(); + } + + void prox( Vector &Pv, const Vector &v, Real t, Real &tol){ + Pv.set(v); proj_->project(Pv); + } +}; // class TypeBIndicatorObjective + +} // namespace ROL + +#endif From 944fd19010ca0014fdee9cb8ba1ff9731088d21f Mon Sep 17 00:00:00 2001 From: Bobby Date: Mon, 9 Jan 2023 00:12:19 -0700 Subject: [PATCH 37/65] working ncg alg --- .../ROL_TypeP_TrustRegionAlgorithm_Def.hpp | 42 +++++++++---------- packages/rol/test/algorithm/TypeP/test_04.cpp | 4 +- 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp index b45e9b355776..094560708b43 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp @@ -98,7 +98,7 @@ TrustRegionAlgorithm::TrustRegionAlgorithm(ParameterList &list, // Subsolver (spectral projected gradient) parameters useMin_ = lmlist.sublist("Solver").get("Use Smallest Model Iterate", true); useNMSP_ = lmlist.sublist("Solver").get("Use Nonmonotone Search", false); - algSelect_ = lmlist.sublist("Solver").get("Select Subproblem Solver", 3); + algSelect_ = lmlist.sublist("Solver").get("Select Subproblem Solver", 1); // Subsolver (nonlinear conjugate gradient) parameters) ncgType_ = lmlist.sublist("Solver").get("Nonlinear CG Type", 1); etaNCG_ = lmlist.sublist("Solver").get("Truncation Parameter for HZ CG", 1e-2); @@ -821,7 +821,6 @@ void TrustRegionAlgorithm::dprox(Vector &x, } } -<<<<<<< HEAD // NCG Subsolver template void TrustRegionAlgorithm::dncg(Vector &y,// x @@ -853,7 +852,7 @@ void TrustRegionAlgorithm::dncg(Vector &y,// x int NCGiter_(0); Real mval(sval+nval); Real tol(std::sqrt(ROL_EPSILON())), safeguard(tol); - Real hk(0),Qk(0), snorm(0), snorm0(0),gnorm(0),gnorm0(0),gnorm02(0),gnorm2(0), sHs(0), gs(0), ds(0), ss(0), nold(nval), sold(sval), mold(mval); + Real hk(0),Qk(0), snorm(0), snorm0(0),gnorm(0),gnorm0(0),gnorm02(0),gnorm2(0), sHs(0), gs(0), ds(0), ss(0), nold(nval), mold(mval); Real alphamax(1),sy(0),gg(0),eta_(0), alpha(alphamax), lambdaTmp(1), t0ncg(1); Real beta(0), coeff(0); bool reset(true); @@ -864,8 +863,8 @@ void TrustRegionAlgorithm::dncg(Vector &y,// x // Compute initial step coeff = t0_ / gmod.norm(); t0ncg = std::max(lambdaMin_,std::min(coeff,lambdaMax_)); - pgstep(px, dx, nobj, y, gmod.dual(), t0ncg, tol);//solves from y, solution in px, step is pwa - s.set(dx); + pgstep(px, dx, nobj, y, gmod.dual(), t0ncg, tol);//solves from y, solution in px, step is dx + s.set(dx); // set s to dx gs = gmod.apply(s); // gs = ss = s.dot(s); // Norm squared of step snorm = std::sqrt(ss); // norm(step) @@ -883,18 +882,17 @@ void TrustRegionAlgorithm::dncg(Vector &y,// x while (NCGiter_ < maxit_) { NCGiter_++; snorm0 = snorm; - pwa3.set(y); - pwa3.axpy(one,s); - pwa3.axpy(-one,s); - snorm = pwa3.norm(); // y + s - x + pwa3.set(y);// y + pwa3.axpy(one,s); // = y + s + pwa3.axpy(-one,x); // = y + s - x + snorm = pwa3.norm(); alphamax = one; - if (snorm >= (one - safeguard*del)){ - pwa3.set(y); - pwa3.axpy(-one,x);// here is y - x + if (snorm >= (one - safeguard)*del){ + pwa3.axpy(-one,s); ds = s.dot(pwa3); ss = s.dot(s); - alphamax = std::min(one, (-ds + std::sqrt(ds*ds + ss*(del*del - snorm0*snorm0)))/ss); + alphamax = std::min(one, (-ds + std::sqrt(ds*ds + ss*(del*del - snorm0*snorm0)))/ss); } // Update quantities to evaluate quadratic model value and gradient @@ -906,11 +904,10 @@ void TrustRegionAlgorithm::dncg(Vector &y,// x else{ alpha = std::min(alphamax, -(gs + nval - nold)/sHs); } - // Check compute alpha as the minimizer of an upper quadratic model y.axpy(alpha, s); gmod.axpy(alpha, dwa.dual()); // need dual here? - sold = sold + alpha*gs + half*alpha*alpha*sHs; + sval = sval + alpha*gs + half*alpha*alpha*sHs; // Evaluate nonsmooth term nobj.update(y,UpdateType::Trial); nold = nobj.value(y,tol); state_->nnval++; @@ -928,7 +925,7 @@ void TrustRegionAlgorithm::dncg(Vector &y,// x lambdaTmp = t0_/gmod.norm(); } else { - lambdaTmp = s.dot(s); + lambdaTmp = s.dot(s)/sHs; } // Get steepest descent direction @@ -963,19 +960,19 @@ void TrustRegionAlgorithm::dncg(Vector &y,// x beta = std::max(zero, -pwa5.dot(dx)/s.dot(pwa5)); } else if (ncgType_ == 4){// DY + - beta = std::max(zero, gnorm2/s.dot(pwa5)); + beta = std::max(zero, -gnorm2/s.dot(pwa5)); } else if (ncgType_ == 5){//FRPR beta = std::min(gnorm2, std::max(gnorm2, pwa5.dot(dx)))/gnorm02; } else{ //DYHS - beta = std::max(zero, std::min(-pwa5.dot(dx), gnorm2)/s.dot(pwa5)); + beta = std::max(zero, -std::min(pwa5.dot(dx), gnorm2)/s.dot(pwa5)); } reset = true; if (beta != zero && beta::dncg(Vector &y,// x nval = nobj.value(px,tol); state_->nnval++; gs = gmod.dot(s); } - + //mval = sval + nval; if (verbosity_ > 1) { outStream << std::endl; - outStream << " Iterate: " << SPiter_ << std::endl; + outStream << " Iterate: " << NCGiter_ << std::endl; outStream << " Spectral step length (lambda): " << t0ncg << std::endl; outStream << " Step length (alpha): " << alpha << std::endl; outStream << " Model decrease (pRed): " << mval-mold << std::endl; @@ -1007,9 +1004,8 @@ void TrustRegionAlgorithm::dncg(Vector &y,// x if (gnorm < gtol) break; } - s.set(y); - s.axpy(-one,x); nval = nold; + } // BRACKETING AND BRENTS FOR UNTRANSFORMED MULTIPLIER //template diff --git a/packages/rol/test/algorithm/TypeP/test_04.cpp b/packages/rol/test/algorithm/TypeP/test_04.cpp index d4b278100d32..5d7d1dc9fdea 100644 --- a/packages/rol/test/algorithm/TypeP/test_04.cpp +++ b/packages/rol/test/algorithm/TypeP/test_04.cpp @@ -117,8 +117,8 @@ int main(int argc, char *argv[]) { list.sublist("Status Test").set("Gradient Tolerance",1e-7); list.sublist("Status Test").set("Constraint Tolerance",1e-8); list.sublist("Status Test").set("Step Tolerance",1e-12); - list.sublist("Status Test").set("Iteration Limit", 1000); - list.sublist("Step").sublist("Trust Region").sublist("Solver").set("Select Subproblem Solver", 3); + list.sublist("Status Test").set("Iteration Limit", 10); + list.sublist("Step").sublist("Trust Region").sublist("TRN").sublist("Solver").set("Select Subproblem Solver", 3); int dim = 5; ROL::Ptr> sol, wts, y; ROL::Ptr> sobj; From 3e081088566c63deaa0499b54118de66c062f3e2 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Wed, 18 Jan 2023 12:23:18 -0700 Subject: [PATCH 38/65] Cleaned up type-p truncated ncg trust-region algorithm. --- .../TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp | 69 ++- .../ROL_TypeP_TrustRegionAlgorithm_Def.hpp | 576 +++++++----------- packages/rol/test/algorithm/TypeP/test_04.cpp | 2 +- 3 files changed, 275 insertions(+), 372 deletions(-) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp index 54db405599fa..dee0d8f42897 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm.hpp @@ -47,6 +47,7 @@ #include "ROL_TypeP_Algorithm.hpp" #include "ROL_TrustRegionModel_U.hpp" #include "ROL_TrustRegionUtilities.hpp" +#include "ROL_Types.hpp" /** \class ROL::TypeP::TrustRegionAlgorithm \brief Provides an interface to run the trust-region algorithm. @@ -55,6 +56,63 @@ namespace ROL { namespace TypeP { +enum ETrustRegionP{ + TRUSTREGION_P_SPG = 0, + TRUSTREGION_P_SPG2, + TRUSTREGION_P_NCG, + TRUSTREGION_P_LAST +}; + +inline std::string ETrustRegionPToString(ETrustRegionP alg) { + std::string retString; + switch(alg) { + case TRUSTREGION_P_SPG: retString = "SPG"; break; + case TRUSTREGION_P_SPG2: retString = "Simplified SPG"; break; + case TRUSTREGION_P_NCG: retString = "NCG"; break; + case TRUSTREGION_P_LAST: retString = "Last Type (Dummy)"; break; + default: retString = "INVALID ETrustRegionP"; + } + return retString; +} + +inline int isValidTrustRegionP(ETrustRegionP alg){ + return( (alg == TRUSTREGION_P_SPG) || + (alg == TRUSTREGION_P_SPG2) || + (alg == TRUSTREGION_P_NCG) || + (alg == TRUSTREGION_P_LAST) + ); +} + +inline ETrustRegionP & operator++(ETrustRegionP &type) { + return type = static_cast(type+1); +} + +inline ETrustRegionP operator++(ETrustRegionP &type, int) { + ETrustRegionP oldval = type; + ++type; + return oldval; +} + +inline ETrustRegionP & operator--(ETrustRegionP &type) { + return type = static_cast(type-1); +} + +inline ETrustRegionP operator--(ETrustRegionP &type, int) { + ETrustRegionP oldval = type; + --type; + return oldval; +} + +inline ETrustRegionP StringToETrustRegionP(std::string s) { + s = removeStringFormat(s); + for ( ETrustRegionP alg = TRUSTREGION_P_SPG; alg < TRUSTREGION_P_LAST; alg++ ) { + if ( !s.compare(removeStringFormat(ETrustRegionPToString(alg))) ) { + return alg; + } + } + return TRUSTREGION_P_SPG; +} + template class TrustRegionAlgorithm : public TypeP::Algorithm { private: @@ -105,10 +163,10 @@ class TrustRegionAlgorithm : public TypeP::Algorithm { int maxSize_; bool useMin_; bool useNMSP_; - Real algSelect_; + ETrustRegionP algSelect_; int ncgType_; - Real etaNCG_; - Real desPar_; + Real etaNCG_; + Real desPar_; // Inexactness Parameters std::vector useInexact_; @@ -252,13 +310,12 @@ class TrustRegionAlgorithm : public TypeP::Algorithm { Real del, TrustRegionModel_U &model, Objective &nobj, - Vector &px, - Vector &pwa, + Vector &s, Vector &pwa1, Vector &pwa2, Vector &pwa3, Vector &pwa4, - Vector &pwa5, + Vector &pwa5, Vector &dwa, std::ostream &outStream = std::cout); diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp index 094560708b43..b7b798049141 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp @@ -49,6 +49,7 @@ namespace ROL { namespace TypeP { + template TrustRegionAlgorithm::TrustRegionAlgorithm(ParameterList &list, const Ptr> &secant) { @@ -95,15 +96,16 @@ TrustRegionAlgorithm::TrustRegionAlgorithm(ParameterList &list, maxit_ = lmlist.sublist("Solver").get("Iteration Limit", 25); tol1_ = lmlist.sublist("Solver").get("Absolute Tolerance", 1e-4); tol2_ = lmlist.sublist("Solver").get("Relative Tolerance", 1e-2); - // Subsolver (spectral projected gradient) parameters - useMin_ = lmlist.sublist("Solver").get("Use Smallest Model Iterate", true); + // Subsolver (spectral projected gradient) parameters + useMin_ = lmlist.sublist("Solver").get("Use Smallest Model Iterate", true); useNMSP_ = lmlist.sublist("Solver").get("Use Nonmonotone Search", false); - algSelect_ = lmlist.sublist("Solver").get("Select Subproblem Solver", 1); + std::string ssname = lmlist.sublist("Solver").get("Subproblem Solver", "SPG"); + algSelect_ = StringToETrustRegionP(ssname); // Subsolver (nonlinear conjugate gradient) parameters) - ncgType_ = lmlist.sublist("Solver").get("Nonlinear CG Type", 1); - etaNCG_ = lmlist.sublist("Solver").get("Truncation Parameter for HZ CG", 1e-2); - desPar_ = lmlist.sublist("Solver").get("Descent parameter for Nonlinear CG", 0.2); - // Inexactness Information + ncgType_ = lmlist.sublist("Solver").sublist("NCG").get("Nonlinear CG Type", 4); + etaNCG_ = lmlist.sublist("Solver").sublist("NCG").get("Truncation Parameter for HZ CG", 1e-2); + desPar_ = lmlist.sublist("Solver").sublist("NCG").get("Descent parameter for Nonlinear CG", 1.0); + // Inexactness Information ParameterList &glist = list.sublist("General"); useInexact_.clear(); useInexact_.push_back(glist.get("Inexact Objective Function", false)); @@ -269,33 +271,35 @@ void TrustRegionAlgorithm::run(Vector &x, gmod->set(*state_->gradientVec); smodel = state_->svalue; ntrial = state_->nvalue; - if (algSelect_==1){ - // Compute Cauchy point (TRON notation: x = x[1]) - dcauchy(*state_->stepVec,alpha_, smodel, ntrial, - *state_->iterateVec, *dg, state_->searchSize, - *model_, nobj, *px, *dwa1, *dwa2, outStream); // Solve 1D optimization problem for alpha - x.plus(*state_->stepVec); // Set x = x[0] + alpha*g - // Model gradient at s = x[1] - x[0] - gmod->plus(*dwa1); // hessVec from Cauchy point computation - - // Apply SPG starting from the Cauchy point->change input - dspg(x,smodel,ntrial,*gmod,*state_->iterateVec,state_->searchSize, - *model_,nobj,*pwa1,*pwa2,*pwa3,*pwa4,*pwa5,*pwa6,*pwa7,*dwa1, - outStream); - pRed = state_->value - (smodel+ntrial); + switch (algSelect_) { + case TRUSTREGION_P_SPG: + default: + // Compute Cauchy point (TRON notation: x = x[1]) + dcauchy(*state_->stepVec,alpha_, smodel, ntrial, + *state_->iterateVec, *dg, state_->searchSize, + *model_, nobj, *px, *dwa1, *dwa2, outStream); // Solve 1D optimization problem for alpha + x.plus(*state_->stepVec); // Set x = x[0] + alpha*g + // Model gradient at s = x[1] - x[0] + gmod->plus(*dwa1); // hessVec from Cauchy point computation + + // Apply SPG starting from the Cauchy point->change input + dspg(x,smodel,ntrial,*gmod,*state_->iterateVec,state_->searchSize, + *model_,nobj,*pwa1,*pwa2,*pwa3,*pwa4,*pwa5,*pwa6,*pwa7,*dwa1, + outStream); + pRed = state_->value - (smodel+ntrial); + break; + case TRUSTREGION_P_SPG2: + dspg2(x,smodel, ntrial, pRed, *gmod, *state_->iterateVec, + state_->searchSize, *model_, nobj, + *pwa1, *pwa2, *px, *dwa1, outStream); + break; + case TRUSTREGION_P_NCG: + dncg(x,smodel,ntrial,*gmod,*state_->iterateVec,state_->searchSize, + *model_,nobj,*pwa1,*pwa2,*pwa3,*pwa4,*pwa5,*pwa6,*dwa1, + outStream); + pRed = state_->value - (smodel+ntrial); + break; } - else if (algSelect_==2) {// SPG2 - dspg2(x,smodel, ntrial, pRed, *gmod, *state_->iterateVec, - state_->searchSize, *model_, nobj, - *pwa1, *pwa2, *px, *dwa1, outStream); - } - else if (algSelect_==3){//NCG - dncg(x,smodel,ntrial,*gmod,*state_->iterateVec,state_->searchSize, - *model_,nobj,*px,*pwa2,*pwa3,*pwa4,*pwa5,*pwa6,*pwa7,*dwa1, - outStream);//doesn't output pRed - pRed = state_->value - (smodel+ntrial);//compute pRed here - - } // Update storage and compute predicted reduction //pRed = -q; // now updated in dcauchy/dspg @@ -823,20 +827,19 @@ void TrustRegionAlgorithm::dprox(Vector &x, // NCG Subsolver template -void TrustRegionAlgorithm::dncg(Vector &y,// x - Real &sval,//smodel - Real &nval, //ntrial - Vector &gmod, // gradient - const Vector &x,//iterateVec +void TrustRegionAlgorithm::dncg(Vector &y, + Real &sval, + Real &nval, + Vector &gmod, + const Vector &x, Real del, TrustRegionModel_U &model, Objective &nobj, - Vector &px, Vector &s, - Vector &dx, + Vector &pwa1, Vector &pwa2, Vector &pwa3, - Vector &dx0, + Vector &pwa4, Vector &pwa5, Vector &dwa, std::ostream &outStream) { @@ -844,349 +847,185 @@ void TrustRegionAlgorithm::dncg(Vector &y,// x // min 1/2 + + phi(y) subject to ||y|| \le del // // Inpute: - // y = Cauchy step - // x = Current iterate - // g = Current gradient - const Real half(0.5), one(1),zero(0); - const Real inf = ROL_INF(); - int NCGiter_(0); - Real mval(sval+nval); + // y = Cauchy step + // sval = smooth model value + // nval = nonsmooth value + // gmod = Current gradient + // x = Current iterate + // del = trust region radius + // model = trust region model + // nobj = nonsmooth objective function + // s = stores the current step + // pwa1 = stores the SPG iterate + // pwa2 = stores the SPG step (i.e., descent direction) + // pwa3 = stores y - x + // pwa4 = stores the previous step + // pwa5 = temporary storage + // dwa = the Hessian applied to the step + const Real zero(0), half(0.5), one(1), two(2); Real tol(std::sqrt(ROL_EPSILON())), safeguard(tol); - Real hk(0),Qk(0), snorm(0), snorm0(0),gnorm(0),gnorm0(0),gnorm02(0),gnorm2(0), sHs(0), gs(0), ds(0), ss(0), nold(nval), mold(mval); - Real alphamax(1),sy(0),gg(0),eta_(0), alpha(alphamax), lambdaTmp(1), t0ncg(1); - Real beta(0), coeff(0); + Real mold(sval+nval), nold(nval); + Real snorm(0), snorm0(0), gnorm(0), gnorm0(0), gnorm2(0); + Real alpha(1), beta(1), lambdaTmp(1), lambda(1), eta(etaNCG_), gamma(1), gammaMax(1); + Real sy(0), gg(0), sHs(0), gs(0), ds(0), ss(0); bool reset(true); // Set y = x y.set(x); - - // Compute initial step - coeff = t0_ / gmod.norm(); - t0ncg = std::max(lambdaMin_,std::min(coeff,lambdaMax_)); - pgstep(px, dx, nobj, y, gmod.dual(), t0ncg, tol);//solves from y, solution in px, step is dx - s.set(dx); // set s to dx - gs = gmod.apply(s); // gs = - ss = s.dot(s); // Norm squared of step - snorm = std::sqrt(ss); // norm(step) - gnorm = snorm/t0_; // norm(step) / lambda - nval = nobj.value(px, tol); state_->nnval++; - + pwa3.zero(); // Initially y - x = 0 + + // Compute initial spectral step length + lambdaTmp = t0_ / gmod.norm(); + lambda = std::max(lambdaMin_,std::min(lambdaTmp,lambdaMax_)); + + // Compute Cauchy point via SPG + pgstep(pwa1, pwa2, nobj, y, gmod.dual(), lambda, tol); // pwa1 = prox(x-lambda g), pwa2 = pwa1 - x + pwa2.scale(one/lambda); // pwa2 = (pwa1 - x) / lambda (for smooth: pwa2 = negative gradient) + s.set(pwa2); // s = (pwa1 - x) / lambda + gs = gmod.apply(s); // gs = / lambda + gnorm = s.norm(); // hk = norm(prox(x-lambda g)-x) / lambda + snorm = lambda * gnorm; // snorm = norm(prox(x-lambda g)-x) + nobj.update(pwa1,UpdateType::Trial); + nval = nobj.value(pwa1, tol); state_->nnval++; // Compute initial projected gradient norm const Real gtol = std::min(tol1_,tol2_*gnorm); - if (verbosity_ > 1) + if (verbosity_ > 1) outStream << " Nonlinear Conjugate Gradient" << std::endl; - NCGiter_ = 0; - while (NCGiter_ < maxit_) { - NCGiter_++; - snorm0 = snorm; - pwa3.set(y);// y - pwa3.axpy(one,s); // = y + s - pwa3.axpy(-one,x); // = y + s - x - snorm = pwa3.norm(); - alphamax = one; - - if (snorm >= (one - safeguard)*del){ - pwa3.axpy(-one,s); - ds = s.dot(pwa3); - ss = s.dot(s); - alphamax = std::min(one, (-ds + std::sqrt(ds*ds + ss*(del*del - snorm0*snorm0)))/ss); - } - - // Update quantities to evaluate quadratic model value and gradient + SPiter_ = 0; + SPflag_ = 1; + while (SPiter_ < maxit_) { + SPiter_++; + + gammaMax = one; + ss = s.dot(s); + if (snorm >= (one - safeguard)*del){ + ds = s.dot(pwa3); + gammaMax = std::min(one, (-ds + std::sqrt(ds*ds + ss*(del*del - snorm0*snorm0)))/(lambda * ss)); + } + + // Compute alpha as the minimizer of an upper quadratic model model.hessVec(dwa,s,x,tol); nhess_++; // dwa = H step - sHs = dwa.apply(s); // sHs = - if (sHs <= safeguard){ - alpha = alphamax; - } - else{ - alpha = std::min(alphamax, -(gs + nval - nold)/sHs); - } - // Check compute alpha as the minimizer of an upper quadratic model - y.axpy(alpha, s); - gmod.axpy(alpha, dwa.dual()); // need dual here? - sval = sval + alpha*gs + half*alpha*alpha*sHs; - // Evaluate nonsmooth term + sHs = dwa.apply(s); // sHs = + gamma = (sHs <= safeguard) ? gammaMax : std::min(gammaMax, -(lambda * gs + nval - nold)/(lambda * lambda * sHs)); + alpha = gamma * lambda; + + // Update quantities to evaluate quadratic model value and gradient + y.axpy(alpha, s); + gmod.axpy(alpha, dwa); // need dual here? + sval += alpha*gs + half*alpha*alpha*sHs; nobj.update(y,UpdateType::Trial); - nold = nobj.value(y,tol); state_->nnval++; - - // Check step size - pwa3.set(y);//temporary storage - pwa3.axpy(-one,x); - snorm = pwa3.norm(); - if (snorm>= (one-safeguard)*del){ - break; - } - - // Update spectral step length - if (sHs <= safeguard){ - lambdaTmp = t0_/gmod.norm(); - } - else { - lambdaTmp = s.dot(s)/sHs; - } - - // Get steepest descent direction - dx0.set(dx); // solution of proximal step dx0. pwa2 = dx. pwa = s - gnorm0 = gnorm; - t0ncg = std::max(lambdaMin_, std::min(lambdaMax_, lambdaTmp)); - pgstep(px, dx, nobj, y, gmod.dual(), t0ncg, tol);//solves from y, solution in pwa2, step is pwa - gnorm = dx.norm(); - hk = gnorm/t0ncg; - - if (hk <= gtol){ - break; - } - gnorm2 = gnorm*gnorm; - gnorm02 = gnorm0*gnorm0; - //use pwa5 for dx - dx0 storage - pwa5.set(dx); - pwa5.axpy(-one, dx0); - if (ncgType_ == 0) {// FR - beta = gnorm2/gnorm02; - } - else if (ncgType_ == 1) {// PR+ - beta = std::max(zero, pwa5.dot(dx)/gnorm02); - } - else if (ncgType_ == 2) {// HZ - sy = s.dot(pwa5); - gg = dx.dot(dx0); - eta_ = -one/(s.norm()*std::min(etaNCG_, gnorm0)); - beta = std::max(eta_, (gnorm2 - gg - 2*s.dot(dx)*(gnorm2 - 2*gg+gnorm02)/sy)/sy); - } - else if (ncgType_ == 3){ // HS+ - beta = std::max(zero, -pwa5.dot(dx)/s.dot(pwa5)); - } - else if (ncgType_ == 4){// DY + - beta = std::max(zero, -gnorm2/s.dot(pwa5)); - } - else if (ncgType_ == 5){//FRPR - beta = std::min(gnorm2, std::max(gnorm2, pwa5.dot(dx)))/gnorm02; - } - else{ //DYHS - beta = std::max(zero, -std::min(pwa5.dot(dx), gnorm2)/s.dot(pwa5)); - } - - reset = true; - - if (beta != zero && betannval++; //is this right? - Qk = gs + nval - nold; - if (Qk <= -(one - desPar_)*gnorm2/t0ncg){ - s.set(pwa5);//s = s0 - reset = false; - } - } - if (reset){// you don't take the NCG step - beta = zero; - s.set(dx); - nval = nobj.value(px,tol); state_->nnval++; - gs = gmod.dot(s); - } - //mval = sval + nval; - - if (verbosity_ > 1) { + nold = nobj.value(y,tol); state_->nnval++; + + // Check step size + pwa3.set(y); pwa3.axpy(-one,x); + snorm0 = pwa3.norm(); + if (snorm0 >= (one-safeguard)*del) { SPflag_ = 2; break; } + + // Update spectral step length + lambdaTmp = (sHs <= safeguard) ? t0_/gmod.norm() : ss/sHs; + lambda = std::max(lambdaMin_, std::min(lambdaMax_, lambdaTmp)); + + // Compute SPG direction + pwa4.set(pwa2); // store previous "negative gradient" + pgstep(pwa1, pwa2, nobj, y, gmod.dual(), lambda, tol); // pwa1 = prox(x-lambda g), pwa2 = pwa1 - x + pwa2.scale(one/lambda); // pwa2 = (pwa1 - x) / lambda (for smooth: pwa2 = negative gradient) + gnorm0 = gnorm; + gnorm = pwa2.norm(); + + // Check stopping condition + if (gnorm <= gtol) { SPflag_ = 0; break; } + + gnorm2 = gnorm * gnorm; + switch (ncgType_) { + case 0: // Fletcher-Reeves + beta = gnorm2/(gnorm0 * gnorm0); + break; + default: + case 1: // Polyak-Ribiere+ + pwa5.set(pwa4); pwa5.axpy(-one,pwa2); + beta = std::max(zero, -pwa5.dot(pwa2)/(gnorm0*gnorm0)); + break; + case 2: // Hager-Zhang + pwa5.set(pwa4); pwa5.axpy(-one,pwa2); + sy = s.dot(pwa5); + gg = pwa2.dot(pwa4); + eta = -one/(s.norm()*std::min(etaNCG_, gnorm0)); + beta = std::max(eta, (gnorm2-gg-two*pwa2.dot(s)*(gnorm2-two*gg+(gnorm0*gnorm0))/sy)/sy); + break; + case 3: // Hestenes-Stiefel+ + pwa5.set(pwa4); pwa5.axpy(-one,pwa2); + beta = std::max(zero, -pwa2.dot(pwa5)/s.dot(pwa5)); + break; + case 4: // Dai-Yuan+ + pwa5.set(pwa4); pwa5.axpy(-one,pwa2); + beta = std::max(zero, gnorm2/s.dot(pwa5)); + break; + case 5: // Fletcher-Reeves-Polyak-Ribiere + pwa5.set(pwa4); pwa5.axpy(-one,pwa2); + beta = std::max(-gnorm2, std::min(gnorm2, -pwa5.dot(pwa2)))/(gnorm0*gnorm0); + break; + case 6: //Dai-Yuan-Hestenes-Stiefles + pwa5.set(pwa4); pwa5.axpy(-one,pwa2); + beta = std::max(zero, std::min(-pwa2.dot(pwa5), gnorm2)/s.dot(pwa5)); + break; + } + + reset = true; + if (beta != zero && beta < ROL_INF()){ + pwa5.set(pwa2); // pwa5 = pwa2 (SPG step) + pwa5.axpy(beta, s); // pwa5 = pwa2 + beta*s + pwa4.set(y); // pwa4 = y + pwa4.axpy(lambda,pwa5); // pwa4 = y + lambda*pwa5 + nobj.update(pwa4,UpdateType::Trial); + nval = nobj.value(pwa4,tol); state_->nnval++; + gs = gmod.apply(pwa5); + if (lambda * gs + nval - nold <= -(one - desPar_)*gnorm2*lambda){ + pwa4.axpy(-one,x); + s.set(pwa5); + reset = false; + } + } + if (reset){ // Reset because either beta=0 or step does not produce descent + pwa4.set(pwa1); pwa4.axpy(-one,x); + s.set(pwa2); + nobj.update(pwa1,UpdateType::Trial); + nval = nobj.value(pwa1,tol); state_->nnval++; + gs = gmod.apply(s); + beta = zero; + } + snorm = pwa4.norm(); + + if (verbosity_ > 1) { outStream << std::endl; - outStream << " Iterate: " << NCGiter_ << std::endl; - outStream << " Spectral step length (lambda): " << t0ncg << std::endl; - outStream << " Step length (alpha): " << alpha << std::endl; - outStream << " Model decrease (pRed): " << mval-mold << std::endl; - outStream << " Optimality criterion: " << gnorm << std::endl; + outStream << " Iterate: " << SPiter_ << std::endl; + outStream << " Spectral step length (lambda): " << lambda << std::endl; + outStream << " Step length (alpha): " << alpha << std::endl; + outStream << " NCG parameter (beta): " << beta << std::endl; + outStream << " Model decrease (pRed): " << mold-(sval+nold) << std::endl; + outStream << " Step size: " << snorm0 << std::endl; + outStream << " Optimality criterion: " << gnorm << std::endl; + outStream << " Optimality tolerance: " << gtol << std::endl; outStream << std::endl; } - if (gnorm < gtol) break; - } - nval = nold; - + nval = nold; } -// BRACKETING AND BRENTS FOR UNTRANSFORMED MULTIPLIER -//template -//void TrustRegionSPGAlgorithm::dprox(Vector &x, -// const Vector &x0, -// Real del, -// Vector &y0, -// Vector &y1, -// Vector &yc, -// Vector &pwa, -// std::ostream &outStream) const { -// // Solve ||P(t*x0 + (1-t)*(x-x0))-x0|| = del using Brent's method -// const Real zero(0), half(0.5), one(1), two(2), three(3); -// const Real eps(ROL_EPSILON()), tol0(1e1*eps), fudge(1.0-1e-2*sqrt(eps)); -// Real f0(0), f1(0), fc(0), u0(0), u1(0), uc(0), t0(1), t1(0), tc(0), d1(1), d2(1), tol(1); -// Real p(0), q(0), r(0), s(0), m(0); -// int cnt(state_->nproj); -// y0.set(x); -// proj_->project(y0,outStream); state_->nproj++; -// pwa.set(y0); pwa.axpy(-one,x0); -// f0 = pwa.norm(); -// if (f0 <= del) { -// x.set(y0); -// return; -// } -// -// // Bracketing -// t1 = static_cast(1e-1); -// f1 = one+del; -// while (f1 >= del) { -// t1 *= static_cast(5e-2); -// y1.set(x); y1.scale(t1); y1.axpy(one-t1,x0); -// proj_->project(y1,outStream); state_->nproj++; -// pwa.set(y1); pwa.axpy(-one,x0); -// f1 = pwa.norm(); -// } -// u1 = (one-t1)/t1; -// -// // Brents -// uc = u0; tc = t0; fc = f0; yc.set(y0); -// d1 = u1-u0; d2 = d1; -// int code = 0; -// while (true) { -// if (std::abs(fc-del) < std::abs(f1-del)) { -// u0 = u1; u1 = uc; uc = u0; -// t0 = t1; t1 = tc; tc = t0; -// f0 = f1; f1 = fc; fc = f0; -// y0.set(y1); y1.set(yc); yc.set(y0); -// } -// tol = two*eps*abs(u1) + half*tol0; -// m = half*(uc - u1); -// if (std::abs(m) <= tol) { code = 1; break; } -// if ((f1 >= fudge*del && f1 <= del)) break; -// if (std::abs(d1) < tol || std::abs(f0-del) <= std::abs(f1-del)) { -// d1 = m; d2 = d1; -// } -// else { -// s = (f1-del)/(f0-del); -// if (u0 == uc) { -// p = two*m*s; -// q = one-s; -// } -// else { -// q = (f0-del)/(fc-del); -// r = (f1-del)/(fc-del); -// p = s*(two*m*q*(q-r)-(u1-u0)*(r-one)); -// q = (q-one)*(r-one)*(s-one); -// } -// if (p > zero) q = -q; -// else p = -p; -// s = d1; -// d1 = d2; -// if (two*p < three*m*q-std::abs(tol*q) && p < std::abs(half*s*q)) { -// d2 = p/q; -// } -// else { -// d1 = m; d2 = d1; -// } -// } -// u0 = u1; t0 = t1; f0 = f1; y0.set(y1); -// if (std::abs(d2) > tol) u1 += d2; -// else if (m > zero) u1 += tol; -// else u1 -= tol; -// t1 = one/(one+u1); -// y1.set(x); y1.scale(t1); y1.axpy(one-t1,x0); -// proj_->project(y1,outStream); state_->nproj++; -// pwa.set(y1); pwa.axpy(-one,x0); -// f1 = pwa.norm(); -// if ((f1 > del && fc > del) || (f1 <= del && fc <= del)) { -// uc = u0; tc = t0; fc = f0; yc.set(y0); -// d1 = u1-u0; d2 = d1; -// } -// } -// if (code==1 && f1>del) x.set(yc); -// else x.set(y1); -// if (verbosity_ > 1) { -// outStream << std::endl; -// outStream << " Trust-Region Subproblem Projection" << std::endl; -// outStream << " Number of polyhedral projections: " << state_->nproj-cnt << std::endl; -// if (code == 1 && f1 > del) { -// outStream << " Multiplier: " << uc << std::endl; -// outStream << " Transformed Multiplier: " << tc << std::endl; -// outStream << " Dual Residual: " << fc-del << std::endl; -// } -// else { -// outStream << " Multiplier: " << u1 << std::endl; -// outStream << " Transformed Multiplier: " << t1 << std::endl; -// outStream << " Dual Residual: " << f1-del << std::endl; -// } -// outStream << " Exit Code: " << code << std::endl; -// outStream << std::endl; -// } -//} - -// RIDDERS' METHOD FOR TRUST-REGION PROJECTION -//template -//void TrustRegionSPGAlgorithm::dprox(Vector &x, -// const Vector &x0, -// Real del, -// Vector &y, -// Vector &y1, -// Vector &yc, -// Vector &p, -// std::ostream &outStream) const { -// // Solve ||P(t*x0 + (1-t)*(x-x0))-x0|| = del using Ridder's method -// const Real half(0.5), one(1), tol(1e1*ROL_EPSILON()); -// const Real fudge(1.0-1e-2*std::sqrt(ROL_EPSILON())); -// Real e0(0), e1(0), e2(0), e(0), a0(0), a1(0.5), a2(1), a(0); -// int cnt(state_->nproj); -// y.set(x); -// proj_->project(y,outStream); state_->nproj++; -// p.set(y); p.axpy(-one,x0); -// e2 = p.norm(); -// if (e2 <= del) { -// x.set(y); -// return; -// } -// bool code = 1; -// while (a2-a0 > tol) { -// a1 = half*(a0+a2); -// y.set(x); y.scale(a1); y.axpy(one-a1,x0); -// proj_->project(y,outStream); state_->nproj++; -// p.set(y); p.axpy(-one,x0); -// e1 = p.norm(); -// if (e1 >= fudge*del && e1 <= del) break; -// a = a1-(a1-a0)*(e1-del)/std::sqrt((e1-del)*(e1-del)-(e0-del)*(e2-del)); -// y.set(x); y.scale(a); y.axpy(one-a,x0); -// proj_->project(y,outStream); state_->nproj++; -// p.set(y); p.axpy(-one,x0); -// e = p.norm(); -// if (e < fudge*del) { -// if (e1 < fudge*del) { e0 = (a < a1 ? e1 : e); a0 = (a < a1 ? a1 : a); } -// else { e0 = e; a0 = a; e2 = e1; a2 = a1; }; -// } -// else if (e > del) { -// if (e1 < fudge*del) { e0 = e1; a0 = a1; e2 = e; a2 = a; } -// else { e2 = (a < a1 ? e : e1); a2 = (a < a1 ? a : a1); } -// } -// else { -// code = 0; -// break; // Exit if fudge*del <= snorm <= del -// } -// } -// x.set(y); -// if (verbosity_ > 1) { -// outStream << std::endl; -// outStream << " Trust-Region Subproblem Projection" << std::endl; -// outStream << " Number of polyhedral projections: " << state_->nproj-cnt << std::endl; -// outStream << " Transformed Multiplier: " << a1 << std::endl; -// outStream << " Dual Residual: " << e1-del << std::endl; -// outStream << " Exit Code: " << code << std::endl; -// outStream << std::endl; -// } -//} template void TrustRegionAlgorithm::writeHeader( std::ostream& os ) const { std::stringstream hist; if (verbosity_ > 1) { hist << std::string(114,'-') << std::endl; - hist << " SPG trust-region method status output definitions" << std::endl << std::endl; + switch (algSelect_) { + default: + case TRUSTREGION_P_SPG: hist << " SPG "; break; + case TRUSTREGION_P_SPG2: hist << " Simplified SPG "; break; + case TRUSTREGION_P_NCG: hist << " NCG "; break; + } + hist << "trust-region method status output definitions" << std::endl << std::endl; hist << " iter - Number of iterates (steps taken)" << std::endl; hist << " value - Objective function value" << std::endl; hist << " gnorm - Norm of the gradient" << std::endl; @@ -1204,8 +1043,8 @@ void TrustRegionAlgorithm::writeHeader( std::ostream& os ) const { << TRUtils::ETRFlagToString(static_cast(flag)) << std::endl; } hist << std::endl; - hist << " iterSPG - Number of Spectral Projected Gradient iterations" << std::endl << std::endl; - hist << " flagSPG - Trust-Region Spectral Projected Gradient flag" << std::endl; + hist << " iterSP - Number of Spectral Projected Gradient iterations" << std::endl << std::endl; + hist << " flagSP - Trust-Region Spectral Projected Gradient flag" << std::endl; hist << " 0 - Converged" << std::endl; hist << " 1 - Iteration Limit Exceeded" << std::endl; hist << std::string(114,'-') << std::endl; @@ -1222,8 +1061,8 @@ void TrustRegionAlgorithm::writeHeader( std::ostream& os ) const { hist << std::setw(10) << std::left << "#hess"; hist << std::setw(10) << std::left << "#prox"; hist << std::setw(10) << std::left << "tr_flag"; - hist << std::setw(10) << std::left << "iterSPG"; - hist << std::setw(10) << std::left << "flagSPG"; + hist << std::setw(10) << std::left << "iterSP"; + hist << std::setw(10) << std::left << "flagSP"; hist << std::endl; os << hist.str(); } @@ -1231,7 +1070,14 @@ void TrustRegionAlgorithm::writeHeader( std::ostream& os ) const { template void TrustRegionAlgorithm::writeName( std::ostream& os ) const { std::stringstream hist; - hist << std::endl << "SPG Trust-Region Method (Type P)" << std::endl; + hist << std::endl; + switch (algSelect_) { + default: + case TRUSTREGION_P_SPG: hist << "SPG "; break; + case TRUSTREGION_P_SPG2: hist << "Simplified SPG "; break; + case TRUSTREGION_P_NCG: hist << "NCG "; break; + } + hist << "Trust-Region Method (Type P)" << std::endl; os << hist.str(); } diff --git a/packages/rol/test/algorithm/TypeP/test_04.cpp b/packages/rol/test/algorithm/TypeP/test_04.cpp index 5d7d1dc9fdea..98684e5f05d8 100644 --- a/packages/rol/test/algorithm/TypeP/test_04.cpp +++ b/packages/rol/test/algorithm/TypeP/test_04.cpp @@ -118,7 +118,7 @@ int main(int argc, char *argv[]) { list.sublist("Status Test").set("Constraint Tolerance",1e-8); list.sublist("Status Test").set("Step Tolerance",1e-12); list.sublist("Status Test").set("Iteration Limit", 10); - list.sublist("Step").sublist("Trust Region").sublist("TRN").sublist("Solver").set("Select Subproblem Solver", 3); + list.sublist("Step").sublist("Trust Region").sublist("TRN").sublist("Solver").set("Subproblem Solver", "NCG"); int dim = 5; ROL::Ptr> sol, wts, y; ROL::Ptr> sobj; From 628a3e8701834f6a64e6821d9738c23ad5df1499 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Wed, 18 Jan 2023 12:32:08 -0700 Subject: [PATCH 39/65] Modified type-p trust-region test to run all subproblem solvers. Fixed gradient counter and spg2 nonsmooth objective value counter. --- .../ROL_TypeP_TrustRegionAlgorithm_Def.hpp | 5 +- packages/rol/test/algorithm/TypeP/test_04.cpp | 49 +++++++++++++++++-- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp index b7b798049141..d5227bee561d 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp @@ -358,7 +358,6 @@ void TrustRegionAlgorithm::run(Vector &x, // Compute gradient at new iterate dwa1->set(*state_->gradientVec); state_->gnorm = computeGradient(x,*state_->gradientVec,*px,*dg,*pwa1,state_->searchSize,sobj,nobj,outStream); - state_->ngrad++; state_->iterateVec->set(x); // Update secant information in trust-region model model_->update(x,*state_->stepVec,*dwa1,*state_->gradientVec, @@ -535,7 +534,7 @@ void TrustRegionAlgorithm::dspg2(Vector &y, // Evaluate nonsmooth term nobj.update(pwa2,UpdateType::Trial); - nval = nobj.value(pwa2,tol); + nval = nobj.value(pwa2,tol); state_->nnval++; // Perform line search alphaMax = one; @@ -554,7 +553,7 @@ void TrustRegionAlgorithm::dspg2(Vector &y, else { y.axpy(alpha,pwa); // New iterate nobj.update(y,UpdateType::Trial); - nval = nobj.value(y, tol); + nval = nobj.value(y, tol); state_->nnval++; sval += alpha * (gs + half * alpha * sHs); gmod.axpy(alpha,dwa); } diff --git a/packages/rol/test/algorithm/TypeP/test_04.cpp b/packages/rol/test/algorithm/TypeP/test_04.cpp index 98684e5f05d8..69e68bfeac7e 100644 --- a/packages/rol/test/algorithm/TypeP/test_04.cpp +++ b/packages/rol/test/algorithm/TypeP/test_04.cpp @@ -118,7 +118,6 @@ int main(int argc, char *argv[]) { list.sublist("Status Test").set("Constraint Tolerance",1e-8); list.sublist("Status Test").set("Step Tolerance",1e-12); list.sublist("Status Test").set("Iteration Limit", 10); - list.sublist("Step").sublist("Trust Region").sublist("TRN").sublist("Solver").set("Subproblem Solver", "NCG"); int dim = 5; ROL::Ptr> sol, wts, y; ROL::Ptr> sobj; @@ -135,11 +134,13 @@ int main(int argc, char *argv[]) { sol = ROL::makePtr>(dim); wts->randomize(static_cast(0),static_cast(1)); y->randomize(static_cast(-5),static_cast(5)); - sol->zero(); nobj = ROL::makePtr>(wts,y); sobj = ROL::makePtr>(dim); + std::vector xstar(dim); + sobj->getSolution(xstar, *wtsP, *yP); + // Check derivatives of smooth function ROL::Ptr> xd = sol->clone(); xd->randomize(-1.0,1.0); @@ -151,11 +152,51 @@ int main(int argc, char *argv[]) { sobj->checkHessVec(*xd,*yd,true,*outStream); sobj->checkHessSym(*xd,*yd,*zd,true,*outStream); + list.sublist("Step").sublist("Trust Region").sublist("TRN").sublist("Solver").set("Subproblem Solver", "SPG"); + sol->zero(); + algo = ROL::makePtr>(list); + algo->run(*sol,*sobj,*nobj,*outStream); + + data = *ROL::staticPtrCast>(sol)->getVector(); + *outStream << " Result: "; + for (int i = 0; i < dim; ++i) { + *outStream << " x" << i+1 << " = " << data[i]; + err = std::max(err,std::abs(data[i]-xstar[i])); + } + *outStream << std::endl; + *outStream << " Truth: "; + for (int i = 0; i < dim; ++i) { + *outStream << " x" << i+1 << " = " << xstar[i]; + } + *outStream << std::endl; + *outStream << " Max-Error = " << err << std::endl; + errorFlag += (err > tol ? 1 : 0); + + list.sublist("Step").sublist("Trust Region").sublist("TRN").sublist("Solver").set("Subproblem Solver", "Simplified SPG"); + sol->zero(); + algo = ROL::makePtr>(list); + algo->run(*sol,*sobj,*nobj,*outStream); + + data = *ROL::staticPtrCast>(sol)->getVector(); + *outStream << " Result: "; + for (int i = 0; i < dim; ++i) { + *outStream << " x" << i+1 << " = " << data[i]; + err = std::max(err,std::abs(data[i]-xstar[i])); + } + *outStream << std::endl; + *outStream << " Truth: "; + for (int i = 0; i < dim; ++i) { + *outStream << " x" << i+1 << " = " << xstar[i]; + } + *outStream << std::endl; + *outStream << " Max-Error = " << err << std::endl; + errorFlag += (err > tol ? 1 : 0); + + list.sublist("Step").sublist("Trust Region").sublist("TRN").sublist("Solver").set("Subproblem Solver", "NCG"); + sol->zero(); algo = ROL::makePtr>(list); algo->run(*sol,*sobj,*nobj,*outStream); - std::vector xstar(dim); - sobj->getSolution(xstar, *wtsP, *yP); data = *ROL::staticPtrCast>(sol)->getVector(); *outStream << " Result: "; for (int i = 0; i < dim; ++i) { From 077c565806d8aef1f5b7d2c48f5ad109fe863fb3 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Wed, 18 Jan 2023 12:35:57 -0700 Subject: [PATCH 40/65] Print relative error in the infinity norm for the trust-region example. --- packages/rol/test/algorithm/TypeP/test_04.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/rol/test/algorithm/TypeP/test_04.cpp b/packages/rol/test/algorithm/TypeP/test_04.cpp index 69e68bfeac7e..d1bc266b8981 100644 --- a/packages/rol/test/algorithm/TypeP/test_04.cpp +++ b/packages/rol/test/algorithm/TypeP/test_04.cpp @@ -140,6 +140,9 @@ int main(int argc, char *argv[]) { std::vector xstar(dim); sobj->getSolution(xstar, *wtsP, *yP); + RealT xmax(0); + for (int i = 0; i < dim; ++i) + xmax = std::max(xmax,std::abs(xstar[i])); // Check derivatives of smooth function ROL::Ptr> xd = sol->clone(); @@ -169,7 +172,7 @@ int main(int argc, char *argv[]) { *outStream << " x" << i+1 << " = " << xstar[i]; } *outStream << std::endl; - *outStream << " Max-Error = " << err << std::endl; + *outStream << " Max Relative Error = " << err/xmax << std::endl; errorFlag += (err > tol ? 1 : 0); list.sublist("Step").sublist("Trust Region").sublist("TRN").sublist("Solver").set("Subproblem Solver", "Simplified SPG"); @@ -189,7 +192,7 @@ int main(int argc, char *argv[]) { *outStream << " x" << i+1 << " = " << xstar[i]; } *outStream << std::endl; - *outStream << " Max-Error = " << err << std::endl; + *outStream << " Max Relative Error = " << err/xmax << std::endl; errorFlag += (err > tol ? 1 : 0); list.sublist("Step").sublist("Trust Region").sublist("TRN").sublist("Solver").set("Subproblem Solver", "NCG"); @@ -209,7 +212,7 @@ int main(int argc, char *argv[]) { *outStream << " x" << i+1 << " = " << xstar[i]; } *outStream << std::endl; - *outStream << " Max-Error = " << err << std::endl; + *outStream << " Max Relative Error = " << err/xmax << std::endl; errorFlag += (err > tol ? 1 : 0); } catch (std::logic_error& err) { From 3610fbcf6e499a2ca3252ae95690f7c34572d00f Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Wed, 18 Jan 2023 12:39:00 -0700 Subject: [PATCH 41/65] Fixed comparison bug in StochasticObjective. --- .../sol/function/randvarfunctional/ROL_StochasticObjective.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rol/src/sol/function/randvarfunctional/ROL_StochasticObjective.hpp b/packages/rol/src/sol/function/randvarfunctional/ROL_StochasticObjective.hpp index 8f0ebf8ac669..9893624d9d80 100644 --- a/packages/rol/src/sol/function/randvarfunctional/ROL_StochasticObjective.hpp +++ b/packages/rol/src/sol/function/randvarfunctional/ROL_StochasticObjective.hpp @@ -178,7 +178,7 @@ class StochasticObjective : public Objective { obj_->update(*x0,type,iter); // Update samplers vsampler_->update(*x0); - if ( type != UpdateType::Trial || type != UpdateType::Revert ) { + if ( type != UpdateType::Trial && type != UpdateType::Revert ) { gsampler_->update(*x0); hsampler_->update(*x0); } From cff3ffeffb337e68501b5bd2e8528fec8012848b Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Wed, 18 Jan 2023 13:31:59 -0700 Subject: [PATCH 42/65] Fixed comments for ncg. --- .../ROL_TypeP_TrustRegionAlgorithm_Def.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp index d5227bee561d..ef3ee115ff69 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp @@ -843,22 +843,22 @@ void TrustRegionAlgorithm::dncg(Vector &y, Vector &dwa, std::ostream &outStream) { // Use NCG to approximately solve TR subproblem: - // min 1/2 + + phi(y) subject to ||y|| \le del + // min 1/2 + + phi(y) subject to ||y-x|| \le del // // Inpute: - // y = Cauchy step + // y = computed iterate // sval = smooth model value // nval = nonsmooth value - // gmod = Current gradient - // x = Current iterate + // gmod = current gradient + // x = current iterate // del = trust region radius // model = trust region model // nobj = nonsmooth objective function - // s = stores the current step - // pwa1 = stores the SPG iterate - // pwa2 = stores the SPG step (i.e., descent direction) - // pwa3 = stores y - x - // pwa4 = stores the previous step + // s = the current step + // pwa1 = the SPG iterate + // pwa2 = the "negative gradient" + // pwa3 = y - x + // pwa4 = the previous "negative gradient" // pwa5 = temporary storage // dwa = the Hessian applied to the step const Real zero(0), half(0.5), one(1), two(2); From a0bb264bb2c6eebcafc932dac33d71adca81fb3b Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Fri, 3 Feb 2023 17:20:23 -0700 Subject: [PATCH 43/65] Corrected difference from paper in projected search for Lin-More. --- .../src/algorithm/TypeB/ROL_TypeB_LinMoreAlgorithm_Def.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/rol/src/algorithm/TypeB/ROL_TypeB_LinMoreAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeB/ROL_TypeB_LinMoreAlgorithm_Def.hpp index 393f217b6bd0..db5123097ce3 100644 --- a/packages/rol/src/algorithm/TypeB/ROL_TypeB_LinMoreAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeB/ROL_TypeB_LinMoreAlgorithm_Def.hpp @@ -456,7 +456,7 @@ Real LinMoreAlgorithm::dprsrch(Vector &x, Vector &s, BoundConstraint &bnd, Vector &pwa, Vector &dwa, std::ostream &outStream) { - const Real half(0.5); + const Real zero(0.0), half(0.5); Real tol = std::sqrt(ROL_EPSILON()); Real beta(1), snorm(0), gs(0); int nsteps = 0; @@ -469,7 +469,7 @@ Real LinMoreAlgorithm::dprsrch(Vector &x, Vector &s, gs = pwa.dot(g); //q = half * pwa.dot(dwa.dual()) + gs; q = half * pwa.apply(dwa) + gs; - if (q <= mu0_*gs || nsteps > pslim_) { + if (q <= mu0_*std::min(gs,zero) || nsteps > pslim_) { search = false; } else { From fb0dd2127f1a69c94681dcf1aa3d76e0b8128030 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Thu, 23 Feb 2023 14:46:18 -0700 Subject: [PATCH 44/65] Updated penalty methods and line search methods to input user defined secant. Also updated factories and solvers for this purpose. --- packages/rol/src/algorithm/ROL_Solver.hpp | 3 ++- packages/rol/src/algorithm/ROL_Solver_Def.hpp | 11 +++++----- .../TypeB/ROL_TypeB_AlgorithmFactory.hpp | 22 +++++++++---------- .../ROL_TypeB_InteriorPointAlgorithm.hpp | 5 ++++- .../ROL_TypeB_InteriorPointAlgorithm_Def.hpp | 6 ++--- .../TypeB/ROL_TypeB_MoreauYosidaAlgorithm.hpp | 4 +++- .../ROL_TypeB_MoreauYosidaAlgorithm_Def.hpp | 12 +++++----- .../TypeE/ROL_TypeE_AlgorithmFactory.hpp | 8 +++---- ...ROL_TypeE_AugmentedLagrangianAlgorithm.hpp | 4 +++- ...TypeE_AugmentedLagrangianAlgorithm_Def.hpp | 6 ++--- .../TypeE/ROL_TypeE_FletcherAlgorithm.hpp | 4 +++- .../TypeE/ROL_TypeE_FletcherAlgorithm_Def.hpp | 6 ++--- .../ROL_TypeE_StabilizedLCLAlgorithm.hpp | 4 +++- .../ROL_TypeE_StabilizedLCLAlgorithm_Def.hpp | 6 ++--- .../TypeG/ROL_TypeG_AlgorithmFactory.hpp | 10 ++++----- ...ROL_TypeG_AugmentedLagrangianAlgorithm.hpp | 4 +++- ...TypeG_AugmentedLagrangianAlgorithm_Def.hpp | 6 ++--- .../ROL_TypeG_InteriorPointAlgorithm.hpp | 5 ++++- .../ROL_TypeG_InteriorPointAlgorithm_Def.hpp | 6 ++--- .../TypeG/ROL_TypeG_MoreauYosidaAlgorithm.hpp | 5 ++++- .../ROL_TypeG_MoreauYosidaAlgorithm_Def.hpp | 6 ++--- .../ROL_TypeG_StabilizedLCLAlgorithm.hpp | 4 +++- .../ROL_TypeG_StabilizedLCLAlgorithm_Def.hpp | 6 ++--- .../TypeU/ROL_TypeU_AlgorithmFactory.hpp | 6 ++--- .../TypeU/ROL_TypeU_LineSearchAlgorithm.hpp | 2 ++ .../ROL_TypeU_LineSearchAlgorithm_Def.hpp | 3 ++- .../ROL_DescentDirection_U_Factory.hpp | 10 ++++++--- .../linesearch/descent/ROL_NewtonKrylov_U.hpp | 2 +- 28 files changed, 103 insertions(+), 73 deletions(-) diff --git a/packages/rol/src/algorithm/ROL_Solver.hpp b/packages/rol/src/algorithm/ROL_Solver.hpp index 759d8ec19b59..0947d6f6fc50 100644 --- a/packages/rol/src/algorithm/ROL_Solver.hpp +++ b/packages/rol/src/algorithm/ROL_Solver.hpp @@ -82,7 +82,8 @@ class Solver { --- */ Solver( const Ptr> &opt, - ParameterList &list ); + ParameterList &list, + const Ptr> &secant = nullPtr ); /** \brief Solve optimization problem with no iteration output. diff --git a/packages/rol/src/algorithm/ROL_Solver_Def.hpp b/packages/rol/src/algorithm/ROL_Solver_Def.hpp index eb51f31056f7..b6b7c9cd15be 100644 --- a/packages/rol/src/algorithm/ROL_Solver_Def.hpp +++ b/packages/rol/src/algorithm/ROL_Solver_Def.hpp @@ -48,13 +48,14 @@ namespace ROL { template Solver::Solver( const Ptr> &opt, - ParameterList &parlist ) + ParameterList &parlist, + const Ptr> &secant ) : opt_(opt), problemType_(opt_->getProblemType()) { switch (problemType_) { - case TYPE_U: algoU_ = TypeU::AlgorithmFactory(parlist); break; - case TYPE_B: algoB_ = TypeB::AlgorithmFactory(parlist); break; - case TYPE_E: algoE_ = TypeE::AlgorithmFactory(parlist); break; - case TYPE_EB: algoG_ = TypeG::AlgorithmFactory(parlist); break; + case TYPE_U: algoU_ = TypeU::AlgorithmFactory(parlist,secant); break; + case TYPE_B: algoB_ = TypeB::AlgorithmFactory(parlist,secant); break; + case TYPE_E: algoE_ = TypeE::AlgorithmFactory(parlist,secant); break; + case TYPE_EB: algoG_ = TypeG::AlgorithmFactory(parlist,secant); break; case TYPE_LAST: ROL_TEST_FOR_EXCEPTION(true,std::invalid_argument, "Error in Solver::solve() : Unsupported problem type"); diff --git a/packages/rol/src/algorithm/TypeB/ROL_TypeB_AlgorithmFactory.hpp b/packages/rol/src/algorithm/TypeB/ROL_TypeB_AlgorithmFactory.hpp index e387734cfcab..3837afb7e37b 100644 --- a/packages/rol/src/algorithm/TypeB/ROL_TypeB_AlgorithmFactory.hpp +++ b/packages/rol/src/algorithm/TypeB/ROL_TypeB_AlgorithmFactory.hpp @@ -143,7 +143,7 @@ inline EAlgorithmB StringToEAlgorithmB(std::string s) { } template -inline Ptr> AlgorithmFactory(ParameterList &parlist) { +inline Ptr> AlgorithmFactory(ParameterList &parlist, const Ptr> &secant = nullPtr) { EAlgorithmB ealg = StringToEAlgorithmB(parlist.sublist("Step").get("Type","Trust Region")); switch(ealg) { case ALGORITHM_B_LINESEARCH: @@ -151,14 +151,14 @@ inline Ptr> AlgorithmFactory(ParameterList &parlist) { std::string desc = parlist.sublist("Step").sublist("Line Search").sublist("Descent Method").get("Type","Newton-Krylov"); if (desc=="Newton-Krylov" || desc=="Newton") - return makePtr>(parlist); + return makePtr>(parlist,secant); else if (desc=="Quasi-Newton Method" || desc=="Quasi-Newton") { std::string method = parlist.sublist("Step").sublist("Line Search").sublist("Quasi-Newton").get("Method","L-Secant-B"); if (method == "L-Secant-B") - return makePtr>(parlist); // Similar to L-BFGS-B + return makePtr>(parlist,secant); // Similar to L-BFGS-B else - return makePtr>(parlist); // PQN + return makePtr>(parlist,secant); // PQN } else { return makePtr>(parlist); @@ -169,17 +169,17 @@ inline Ptr> AlgorithmFactory(ParameterList &parlist) { std::string trmod = parlist.sublist("Step").sublist("Trust Region").get("Subproblem Model","Lin-More"); if (trmod=="Kelley-Sachs") - return makePtr>(parlist); + return makePtr>(parlist,secant); else if (trmod=="SPG") - return makePtr>(parlist); + return makePtr>(parlist,secant); else if (trmod=="Coleman-Li") - return makePtr>(parlist); + return makePtr>(parlist,secant); else - return makePtr>(parlist); + return makePtr>(parlist,secant); } - case ALGORITHM_B_MOREAUYOSIDA: return makePtr>(parlist); - case ALGORITHM_B_PRIMALDUALACTIVESET: return makePtr>(parlist); - case ALGORITHM_B_INTERIORPOINT: return makePtr>(parlist); + case ALGORITHM_B_MOREAUYOSIDA: return makePtr>(parlist,secant); + case ALGORITHM_B_PRIMALDUALACTIVESET: return makePtr>(parlist,secant); + case ALGORITHM_B_INTERIORPOINT: return makePtr>(parlist,secant); case ALGORITHM_B_SPECTRALGRADIENT: return makePtr>(parlist); default: return nullPtr; } diff --git a/packages/rol/src/algorithm/TypeB/ROL_TypeB_InteriorPointAlgorithm.hpp b/packages/rol/src/algorithm/TypeB/ROL_TypeB_InteriorPointAlgorithm.hpp index 7ec438dc1131..5669239f30a9 100644 --- a/packages/rol/src/algorithm/TypeB/ROL_TypeB_InteriorPointAlgorithm.hpp +++ b/packages/rol/src/algorithm/TypeB/ROL_TypeB_InteriorPointAlgorithm.hpp @@ -46,6 +46,7 @@ #include "ROL_TypeB_Algorithm.hpp" #include "ROL_InteriorPointObjective.hpp" +#include "ROL_Secant.hpp" /** \class ROL::TypeB::InteriorPointAlgorithm \brief Provides an interface to run the Moreau-Yosida algorithm. @@ -57,6 +58,8 @@ namespace TypeB { template class InteriorPointAlgorithm : public TypeB::Algorithm { private: + const Ptr> secant_; + Real mumin_; Real mumax_; Real rho_; @@ -96,7 +99,7 @@ class InteriorPointAlgorithm : public TypeB::Algorithm { std::ostream &outStream = std::cout); public: - InteriorPointAlgorithm(ParameterList &list); + InteriorPointAlgorithm(ParameterList &list, const Ptr> &secant = nullPtr); using TypeB::Algorithm::run; void run( Vector &x, diff --git a/packages/rol/src/algorithm/TypeB/ROL_TypeB_InteriorPointAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeB/ROL_TypeB_InteriorPointAlgorithm_Def.hpp index 1e7ad3a9c18e..c2ed5f154cf0 100644 --- a/packages/rol/src/algorithm/TypeB/ROL_TypeB_InteriorPointAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeB/ROL_TypeB_InteriorPointAlgorithm_Def.hpp @@ -50,8 +50,8 @@ namespace ROL { namespace TypeB { template -InteriorPointAlgorithm::InteriorPointAlgorithm(ParameterList &list) - : TypeB::Algorithm::Algorithm(), +InteriorPointAlgorithm::InteriorPointAlgorithm(ParameterList &list, const Ptr> &secant) + : TypeB::Algorithm::Algorithm(), secant_(secant), list_(list), subproblemIter_(0), print_(false) { // Set status test status_->reset(); @@ -159,7 +159,7 @@ void InteriorPointAlgorithm::run( Vector &x, // Solve interior point subproblem list_.sublist("Status Test").set("Gradient Tolerance", gtol_); list_.sublist("Status Test").set("Step Tolerance", stol_); - algo = TypeU::AlgorithmFactory(list_); + algo = TypeU::AlgorithmFactory(list_,secant_); if (hasPolyProj_) algo->run(x,g,ipobj, *proj_->getLinearConstraint(), *proj_->getMultiplier(), diff --git a/packages/rol/src/algorithm/TypeB/ROL_TypeB_MoreauYosidaAlgorithm.hpp b/packages/rol/src/algorithm/TypeB/ROL_TypeB_MoreauYosidaAlgorithm.hpp index 662a89a951b2..b28574daae76 100644 --- a/packages/rol/src/algorithm/TypeB/ROL_TypeB_MoreauYosidaAlgorithm.hpp +++ b/packages/rol/src/algorithm/TypeB/ROL_TypeB_MoreauYosidaAlgorithm.hpp @@ -46,6 +46,7 @@ #include "ROL_TypeB_Algorithm.hpp" #include "ROL_MoreauYosidaObjective.hpp" +#include "ROL_Secant.hpp" /** \class ROL::TypeB::MoreauYosidaAlgorithm \brief Provides an interface to run the Moreau-Yosida algorithm. @@ -57,6 +58,7 @@ namespace TypeB { template class MoreauYosidaAlgorithm : public TypeB::Algorithm { private: + const Ptr> secant_; Real compViolation_; Real gnorm_; Real maxPenalty_; @@ -93,7 +95,7 @@ class MoreauYosidaAlgorithm : public TypeB::Algorithm { std::ostream &outStream = std::cout); public: - MoreauYosidaAlgorithm(ParameterList &list); + MoreauYosidaAlgorithm(ParameterList &list, const Ptr> &secant = nullPtr); using TypeB::Algorithm::run; void run( Vector &x, diff --git a/packages/rol/src/algorithm/TypeB/ROL_TypeB_MoreauYosidaAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeB/ROL_TypeB_MoreauYosidaAlgorithm_Def.hpp index 93e9b8998d70..8f7837614389 100644 --- a/packages/rol/src/algorithm/TypeB/ROL_TypeB_MoreauYosidaAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeB/ROL_TypeB_MoreauYosidaAlgorithm_Def.hpp @@ -50,8 +50,8 @@ namespace ROL { namespace TypeB { template -MoreauYosidaAlgorithm::MoreauYosidaAlgorithm(ParameterList &list) - : TypeB::Algorithm::Algorithm(), +MoreauYosidaAlgorithm::MoreauYosidaAlgorithm(ParameterList &list, const Ptr> &secant) + : TypeB::Algorithm::Algorithm(), secant_(secant), tau_(10), print_(false), list_(list), subproblemIter_(0) { // Set status test status_->reset(); @@ -79,9 +79,9 @@ MoreauYosidaAlgorithm::MoreauYosidaAlgorithm(ParameterList &list) stepname_ = steplist.sublist("Subproblem").get("Step Type","Trust Region"); // Output settings - verbosity_ = list.sublist("General").get("Output Level", 0); - writeHeader_ = verbosity_ > 2; - print_ = (verbosity_ > 2 ? true : print_); + verbosity_ = list.sublist("General").get("Output Level", 0); + writeHeader_ = verbosity_ > 2; + print_ = (verbosity_ > 2 ? true : print_); list_.sublist("General").set("Output Level",(print_ ? verbosity_ : 0)); } @@ -159,7 +159,7 @@ void MoreauYosidaAlgorithm::run( Vector &x, while (status_->check(*state_)) { // Solve augmented Lagrangian subproblem - algo = TypeU::AlgorithmFactory(list_); + algo = TypeU::AlgorithmFactory(list_,secant_); if (hasEcon_) algo->run(x,g,myobj,*proj_->getLinearConstraint(), *proj_->getMultiplier(),*proj_->getResidual(), outStream); diff --git a/packages/rol/src/algorithm/TypeE/ROL_TypeE_AlgorithmFactory.hpp b/packages/rol/src/algorithm/TypeE/ROL_TypeE_AlgorithmFactory.hpp index 0fca8760efd5..709968d76f86 100644 --- a/packages/rol/src/algorithm/TypeE/ROL_TypeE_AlgorithmFactory.hpp +++ b/packages/rol/src/algorithm/TypeE/ROL_TypeE_AlgorithmFactory.hpp @@ -122,13 +122,13 @@ inline EAlgorithmE StringToEAlgorithmE(std::string s) { } template -inline Ptr> AlgorithmFactory(ParameterList &parlist) { +inline Ptr> AlgorithmFactory(ParameterList &parlist, const Ptr> &secant = nullPtr) { EAlgorithmE ealg = StringToEAlgorithmE(parlist.sublist("Step").get("Type","Augmented Lagrangian")); switch(ealg) { - case ALGORITHM_E_AUGMENTEDLAGRANGIAN: return makePtr>(parlist); - case ALGORITHM_E_FLETCHER: return makePtr>(parlist); + case ALGORITHM_E_AUGMENTEDLAGRANGIAN: return makePtr>(parlist,secant); + case ALGORITHM_E_FLETCHER: return makePtr>(parlist,secant); case ALGORITHM_E_COMPOSITESTEP: return makePtr>(parlist); - case ALGORITHM_E_STABILIZEDLCL: return makePtr>(parlist); + case ALGORITHM_E_STABILIZEDLCL: return makePtr>(parlist,secant); default: return nullPtr; } } diff --git a/packages/rol/src/algorithm/TypeE/ROL_TypeE_AugmentedLagrangianAlgorithm.hpp b/packages/rol/src/algorithm/TypeE/ROL_TypeE_AugmentedLagrangianAlgorithm.hpp index 638fda670e3f..8ecaf6350afd 100644 --- a/packages/rol/src/algorithm/TypeE/ROL_TypeE_AugmentedLagrangianAlgorithm.hpp +++ b/packages/rol/src/algorithm/TypeE/ROL_TypeE_AugmentedLagrangianAlgorithm.hpp @@ -46,6 +46,7 @@ #include "ROL_TypeE_Algorithm.hpp" #include "ROL_AugmentedLagrangianObjective.hpp" +#include "ROL_Secant.hpp" /** \class ROL::TypeE::AugmentedLagrangianAlgorithm \brief Provides an interface to run equality constrained optimization algorithms @@ -58,6 +59,7 @@ namespace TypeE { template class AugmentedLagrangianAlgorithm : public TypeE::Algorithm { private: + const Ptr> secant_; ParameterList list_; bool useRelTol_; // Lagrange multiplier update @@ -107,7 +109,7 @@ class AugmentedLagrangianAlgorithm : public TypeE::Algorithm { public: - AugmentedLagrangianAlgorithm(ParameterList &list); + AugmentedLagrangianAlgorithm(ParameterList &list, const Ptr> &secant = nullPtr); using TypeE::Algorithm::run; virtual void run( Vector &x, diff --git a/packages/rol/src/algorithm/TypeE/ROL_TypeE_AugmentedLagrangianAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeE/ROL_TypeE_AugmentedLagrangianAlgorithm_Def.hpp index b168c4023280..00ad83c7dc48 100644 --- a/packages/rol/src/algorithm/TypeE/ROL_TypeE_AugmentedLagrangianAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeE/ROL_TypeE_AugmentedLagrangianAlgorithm_Def.hpp @@ -50,8 +50,8 @@ namespace ROL { namespace TypeE { template -AugmentedLagrangianAlgorithm::AugmentedLagrangianAlgorithm( ParameterList &list ) - : TypeE::Algorithm::Algorithm(), list_(list), subproblemIter_(0) { +AugmentedLagrangianAlgorithm::AugmentedLagrangianAlgorithm( ParameterList &list, const Ptr> &secant ) + : TypeE::Algorithm::Algorithm(), secant_(secant), list_(list), subproblemIter_(0) { // Set status test status_->reset(); status_->add(makePtr>(list)); @@ -203,7 +203,7 @@ void AugmentedLagrangianAlgorithm::run( Vector &x, // Solve unconstrained augmented Lagrangian subproblem list_.sublist("Status Test").set("Gradient Tolerance",optTolerance_); list_.sublist("Status Test").set("Step Tolerance",1.e-6*optTolerance_); - algo = TypeU::AlgorithmFactory(list_); + algo = TypeU::AlgorithmFactory(list_,secant_); algo->run(x,g,alobj,outStream); subproblemIter_ = algo->getState()->iter; diff --git a/packages/rol/src/algorithm/TypeE/ROL_TypeE_FletcherAlgorithm.hpp b/packages/rol/src/algorithm/TypeE/ROL_TypeE_FletcherAlgorithm.hpp index 5cd70f32acd8..e4c8fb42e727 100644 --- a/packages/rol/src/algorithm/TypeE/ROL_TypeE_FletcherAlgorithm.hpp +++ b/packages/rol/src/algorithm/TypeE/ROL_TypeE_FletcherAlgorithm.hpp @@ -46,6 +46,7 @@ #include "ROL_TypeE_Algorithm.hpp" #include "ROL_FletcherObjectiveE.hpp" +#include "ROL_Secant.hpp" /** \class ROL::TypeE::FletcherAlgorithm \brief Provides an interface to run equality constrained optimization algorithms @@ -59,6 +60,7 @@ template class FletcherAlgorithm : public TypeE::Algorithm { private: + const Ptr> secant_; ParameterList list_; std::string subStep_; // Penalty function data @@ -77,7 +79,7 @@ class FletcherAlgorithm : public TypeE::Algorithm { public: - FletcherAlgorithm(ParameterList &list); + FletcherAlgorithm(ParameterList &list, const Ptr> &secant = nullPtr); void initialize( Vector &x, const Vector &g, diff --git a/packages/rol/src/algorithm/TypeE/ROL_TypeE_FletcherAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeE/ROL_TypeE_FletcherAlgorithm_Def.hpp index 912217c2c7ca..58fe400391bb 100644 --- a/packages/rol/src/algorithm/TypeE/ROL_TypeE_FletcherAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeE/ROL_TypeE_FletcherAlgorithm_Def.hpp @@ -50,8 +50,8 @@ namespace ROL { namespace TypeE { template -FletcherAlgorithm::FletcherAlgorithm( ParameterList &list ) - : TypeE::Algorithm::Algorithm(), list_(list), subproblemIter_(0) { +FletcherAlgorithm::FletcherAlgorithm( ParameterList &list, const Ptr> &secant ) + : TypeE::Algorithm::Algorithm(), secant_(secant), list_(list), subproblemIter_(0) { // Set status test status_->reset(); status_->add(makePtr>(list)); @@ -133,7 +133,7 @@ void FletcherAlgorithm::run( Vector &x, while (status_->check(*state_)) { // Minimize Fletcher penalty - algo = TypeU::AlgorithmFactory(list_); + algo = TypeU::AlgorithmFactory(list_,secant_); algo->run(x,g,fobj,outStream); subproblemIter_ = algo->getState()->iter; diff --git a/packages/rol/src/algorithm/TypeE/ROL_TypeE_StabilizedLCLAlgorithm.hpp b/packages/rol/src/algorithm/TypeE/ROL_TypeE_StabilizedLCLAlgorithm.hpp index a29ae726f311..44f60ed647a1 100644 --- a/packages/rol/src/algorithm/TypeE/ROL_TypeE_StabilizedLCLAlgorithm.hpp +++ b/packages/rol/src/algorithm/TypeE/ROL_TypeE_StabilizedLCLAlgorithm.hpp @@ -48,6 +48,7 @@ #include "ROL_AugmentedLagrangianObjective.hpp" #include "ROL_ElasticLinearConstraint.hpp" #include "ROL_ElasticObjective.hpp" +#include "ROL_Secant.hpp" /** \class ROL::TypeE::StabilizedLCLAlgorithm \brief Provides an interface to run equality constrained optimization algorithms @@ -61,6 +62,7 @@ namespace TypeE { template class StabilizedLCLAlgorithm : public TypeE::Algorithm { private: + const Ptr> secant_; ParameterList list_; // Lagrange multiplier update bool useDefaultInitPen_; @@ -110,7 +112,7 @@ class StabilizedLCLAlgorithm : public TypeE::Algorithm { public: - StabilizedLCLAlgorithm(ParameterList &list); + StabilizedLCLAlgorithm(ParameterList &list, const Ptr> &secant = nullPtr); using TypeE::Algorithm::run; virtual void run( Problem &problem, diff --git a/packages/rol/src/algorithm/TypeE/ROL_TypeE_StabilizedLCLAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeE/ROL_TypeE_StabilizedLCLAlgorithm_Def.hpp index afc16308cb3e..2f7a4b47b126 100644 --- a/packages/rol/src/algorithm/TypeE/ROL_TypeE_StabilizedLCLAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeE/ROL_TypeE_StabilizedLCLAlgorithm_Def.hpp @@ -51,8 +51,8 @@ namespace ROL { namespace TypeE { template -StabilizedLCLAlgorithm::StabilizedLCLAlgorithm( ParameterList &list ) - : TypeE::Algorithm::Algorithm(), list_(list), subproblemIter_(0) { +StabilizedLCLAlgorithm::StabilizedLCLAlgorithm( ParameterList &list, const Ptr> &secant ) + : TypeE::Algorithm::Algorithm(), secant_(secant), list_(list), subproblemIter_(0) { // Set status test status_->reset(); status_->add(makePtr>(list)); @@ -255,7 +255,7 @@ void StabilizedLCLAlgorithm::run( Vector &x, // Solve linearly constrained augmented Lagrangian subproblem list_.sublist("Status Test").set("Gradient Tolerance",optTolerance_); list_.sublist("Status Test").set("Step Tolerance",1.e-6*optTolerance_); - algo = TypeB::AlgorithmFactory(list_); + algo = TypeB::AlgorithmFactory(list_,secant_); algo->run(elc,outStream); x.set(*xp->get(0)); diff --git a/packages/rol/src/algorithm/TypeG/ROL_TypeG_AlgorithmFactory.hpp b/packages/rol/src/algorithm/TypeG/ROL_TypeG_AlgorithmFactory.hpp index deacad7d2f52..113392ee7aee 100644 --- a/packages/rol/src/algorithm/TypeG/ROL_TypeG_AlgorithmFactory.hpp +++ b/packages/rol/src/algorithm/TypeG/ROL_TypeG_AlgorithmFactory.hpp @@ -127,13 +127,13 @@ inline EAlgorithmG StringToEAlgorithmG(std::string s) { } template -inline Ptr> AlgorithmFactory(ParameterList &parlist) { +inline Ptr> AlgorithmFactory(ParameterList &parlist, const Ptr> &secant = nullPtr) { EAlgorithmG ealg = StringToEAlgorithmG(parlist.sublist("Step").get("Type","Augmented Lagrangian")); switch(ealg) { - case ALGORITHM_G_AUGMENTEDLAGRANGIAN: return makePtr>(parlist); - case ALGORITHM_G_MOREAUYOSIDA: return makePtr>(parlist); - case ALGORITHM_G_INTERIORPOINT: return makePtr>(parlist); - case ALGORITHM_G_STABILIZEDLCL: return makePtr>(parlist); + case ALGORITHM_G_AUGMENTEDLAGRANGIAN: return makePtr>(parlist,secant); + case ALGORITHM_G_MOREAUYOSIDA: return makePtr>(parlist,secant); + case ALGORITHM_G_INTERIORPOINT: return makePtr>(parlist,secant); + case ALGORITHM_G_STABILIZEDLCL: return makePtr>(parlist,secant); default: return nullPtr; } } diff --git a/packages/rol/src/algorithm/TypeG/ROL_TypeG_AugmentedLagrangianAlgorithm.hpp b/packages/rol/src/algorithm/TypeG/ROL_TypeG_AugmentedLagrangianAlgorithm.hpp index 1e1a115c9940..aec53ee9f40f 100644 --- a/packages/rol/src/algorithm/TypeG/ROL_TypeG_AugmentedLagrangianAlgorithm.hpp +++ b/packages/rol/src/algorithm/TypeG/ROL_TypeG_AugmentedLagrangianAlgorithm.hpp @@ -46,6 +46,7 @@ #include "ROL_TypeG_Algorithm.hpp" #include "ROL_AugmentedLagrangianObjective.hpp" +#include "ROL_Secant.hpp" /** \class ROL::TypeG::AugmentedLagrangianAlgorithm \brief Provides an interface to run general constrained optimization algorithms @@ -59,6 +60,7 @@ namespace TypeG { template class AugmentedLagrangianAlgorithm : public TypeG::Algorithm { private: + const Ptr> secant_; ParameterList list_; bool useRelTol_; // Lagrange multiplier update @@ -111,7 +113,7 @@ class AugmentedLagrangianAlgorithm : public TypeG::Algorithm { public: - AugmentedLagrangianAlgorithm(ParameterList &list); + AugmentedLagrangianAlgorithm(ParameterList &list, const Ptr> &secant = nullPtr); using TypeG::Algorithm::run; void run( Vector &x, diff --git a/packages/rol/src/algorithm/TypeG/ROL_TypeG_AugmentedLagrangianAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeG/ROL_TypeG_AugmentedLagrangianAlgorithm_Def.hpp index 5ee665d3677b..72f3e8b570d7 100644 --- a/packages/rol/src/algorithm/TypeG/ROL_TypeG_AugmentedLagrangianAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeG/ROL_TypeG_AugmentedLagrangianAlgorithm_Def.hpp @@ -50,8 +50,8 @@ namespace ROL { namespace TypeG { template -AugmentedLagrangianAlgorithm::AugmentedLagrangianAlgorithm( ParameterList &list ) - : TypeG::Algorithm::Algorithm(), list_(list), subproblemIter_(0) { +AugmentedLagrangianAlgorithm::AugmentedLagrangianAlgorithm( ParameterList &list, const Ptr> &secant ) + : TypeG::Algorithm::Algorithm(), secant_(secant), list_(list), subproblemIter_(0) { // Set status test status_->reset(); status_->add(makePtr>(list)); @@ -217,7 +217,7 @@ void AugmentedLagrangianAlgorithm::run( Vector &x, // Solve unconstrained augmented Lagrangian subproblem list_.sublist("Status Test").set("Gradient Tolerance",optTolerance_); list_.sublist("Status Test").set("Step Tolerance",1.e-6*optTolerance_); - algo = TypeB::AlgorithmFactory(list_); + algo = TypeB::AlgorithmFactory(list_,secant_); if (hasPolyProj_) algo->run(x,g,alobj,bnd,*proj_->getLinearConstraint(), *proj_->getMultiplier(),*proj_->getResidual(), outStream); diff --git a/packages/rol/src/algorithm/TypeG/ROL_TypeG_InteriorPointAlgorithm.hpp b/packages/rol/src/algorithm/TypeG/ROL_TypeG_InteriorPointAlgorithm.hpp index 8b69dd4fbfef..e3fabab2cb65 100644 --- a/packages/rol/src/algorithm/TypeG/ROL_TypeG_InteriorPointAlgorithm.hpp +++ b/packages/rol/src/algorithm/TypeG/ROL_TypeG_InteriorPointAlgorithm.hpp @@ -46,6 +46,7 @@ #include "ROL_TypeG_Algorithm.hpp" #include "ROL_InteriorPointObjective.hpp" +#include "ROL_Secant.hpp" /** \class ROL::TypeG::InteriorPointAlgorithm \brief Provides an interface to run the interior point algorithm. @@ -57,6 +58,8 @@ namespace TypeG { template class InteriorPointAlgorithm : public TypeG::Algorithm { private: + const Ptr> secant_; + Real mumin_; Real mumax_; Real rho_; @@ -106,7 +109,7 @@ class InteriorPointAlgorithm : public TypeG::Algorithm { std::ostream &outStream = std::cout); public: - InteriorPointAlgorithm(ParameterList &list); + InteriorPointAlgorithm(ParameterList &list, const Ptr> &secant_ = nullPtr); using TypeG::Algorithm::run; void run( Vector &x, diff --git a/packages/rol/src/algorithm/TypeG/ROL_TypeG_InteriorPointAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeG/ROL_TypeG_InteriorPointAlgorithm_Def.hpp index 57cb177c672d..2d8f86510d7c 100644 --- a/packages/rol/src/algorithm/TypeG/ROL_TypeG_InteriorPointAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeG/ROL_TypeG_InteriorPointAlgorithm_Def.hpp @@ -50,8 +50,8 @@ namespace ROL { namespace TypeG { template -InteriorPointAlgorithm::InteriorPointAlgorithm(ParameterList &list) - : TypeG::Algorithm::Algorithm(), +InteriorPointAlgorithm::InteriorPointAlgorithm(ParameterList &list, const Ptr> &secant) + : TypeG::Algorithm::Algorithm(), secant_(secant), list_(list), subproblemIter_(0), print_(false) { // Set status test status_->reset(); @@ -182,7 +182,7 @@ void InteriorPointAlgorithm::run( Vector &x, list_.sublist("Status Test").set("Gradient Tolerance", gtol_); list_.sublist("Status Test").set("Constraint Tolerance", ctol_); list_.sublist("Status Test").set("Step Tolerance", stol_); - algo = TypeE::AlgorithmFactory(list_); + algo = TypeE::AlgorithmFactory(list_,secant_); if (hasPolyProj_) algo->run(x,g,ipobj,econ,emul,eres, *proj_->getLinearConstraint(), *proj_->getMultiplier(), diff --git a/packages/rol/src/algorithm/TypeG/ROL_TypeG_MoreauYosidaAlgorithm.hpp b/packages/rol/src/algorithm/TypeG/ROL_TypeG_MoreauYosidaAlgorithm.hpp index 6648a3c15b13..68697b89d756 100644 --- a/packages/rol/src/algorithm/TypeG/ROL_TypeG_MoreauYosidaAlgorithm.hpp +++ b/packages/rol/src/algorithm/TypeG/ROL_TypeG_MoreauYosidaAlgorithm.hpp @@ -46,6 +46,7 @@ #include "ROL_TypeG_Algorithm.hpp" #include "ROL_MoreauYosidaObjective.hpp" +#include "ROL_Secant.hpp" /** \class ROL::TypeG::MoreauYosidaAlgorithm \brief Provides an interface to run the Moreau-Yosida algorithm. @@ -57,6 +58,8 @@ namespace TypeG { template class MoreauYosidaAlgorithm : public TypeG::Algorithm { private: + const Ptr> secant_; + Real compViolation_; Real gnorm_; Real maxPenalty_; @@ -100,7 +103,7 @@ class MoreauYosidaAlgorithm : public TypeG::Algorithm { std::ostream &outStream = std::cout); public: - MoreauYosidaAlgorithm(ParameterList &list); + MoreauYosidaAlgorithm(ParameterList &list, const Ptr> &secant = nullPtr); using TypeG::Algorithm::run; void run( Vector &x, diff --git a/packages/rol/src/algorithm/TypeG/ROL_TypeG_MoreauYosidaAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeG/ROL_TypeG_MoreauYosidaAlgorithm_Def.hpp index 8dd234878316..d285b825cc13 100644 --- a/packages/rol/src/algorithm/TypeG/ROL_TypeG_MoreauYosidaAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeG/ROL_TypeG_MoreauYosidaAlgorithm_Def.hpp @@ -50,8 +50,8 @@ namespace ROL { namespace TypeG { template -MoreauYosidaAlgorithm::MoreauYosidaAlgorithm(ParameterList &list) - : TypeG::Algorithm::Algorithm(), +MoreauYosidaAlgorithm::MoreauYosidaAlgorithm(ParameterList &list, const Ptr> &secant) + : TypeG::Algorithm::Algorithm(), secant_(secant), tau_(10), print_(false), list_(list), subproblemIter_(0) { // Set status test status_->reset(); @@ -178,7 +178,7 @@ void MoreauYosidaAlgorithm::run( Vector &x, while (status_->check(*state_)) { // Solve augmented Lagrangian subproblem - algo = TypeE::AlgorithmFactory(list_); + algo = TypeE::AlgorithmFactory(list_,secant_); emul.zero(); if (hasPolyProj_) algo->run(x,g,myobj,econ,emul,eres, *proj_->getLinearConstraint(), diff --git a/packages/rol/src/algorithm/TypeG/ROL_TypeG_StabilizedLCLAlgorithm.hpp b/packages/rol/src/algorithm/TypeG/ROL_TypeG_StabilizedLCLAlgorithm.hpp index 64e49344ed74..3726189ce012 100644 --- a/packages/rol/src/algorithm/TypeG/ROL_TypeG_StabilizedLCLAlgorithm.hpp +++ b/packages/rol/src/algorithm/TypeG/ROL_TypeG_StabilizedLCLAlgorithm.hpp @@ -48,6 +48,7 @@ #include "ROL_AugmentedLagrangianObjective.hpp" #include "ROL_ElasticLinearConstraint.hpp" #include "ROL_ElasticObjective.hpp" +#include "ROL_Secant.hpp" /** \class ROL::TypeG::StabilizedLCLAlgorithm \brief Provides an interface to run general constrained optimization algorithms @@ -60,6 +61,7 @@ namespace TypeG { template class StabilizedLCLAlgorithm : public TypeG::Algorithm { private: + const Ptr> secant_; ParameterList list_; // Lagrange multiplier update bool useDefaultInitPen_; @@ -111,7 +113,7 @@ class StabilizedLCLAlgorithm : public TypeG::Algorithm { public: - StabilizedLCLAlgorithm(ParameterList &list); + StabilizedLCLAlgorithm(ParameterList &list, const Ptr> &secant = nullPtr); using TypeG::Algorithm::run; virtual void run( Problem &problem, diff --git a/packages/rol/src/algorithm/TypeG/ROL_TypeG_StabilizedLCLAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeG/ROL_TypeG_StabilizedLCLAlgorithm_Def.hpp index 63443012a318..6b1a03efb84a 100644 --- a/packages/rol/src/algorithm/TypeG/ROL_TypeG_StabilizedLCLAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeG/ROL_TypeG_StabilizedLCLAlgorithm_Def.hpp @@ -51,8 +51,8 @@ namespace ROL { namespace TypeG { template -StabilizedLCLAlgorithm::StabilizedLCLAlgorithm( ParameterList &list ) - : TypeG::Algorithm::Algorithm(), list_(list), subproblemIter_(0) { +StabilizedLCLAlgorithm::StabilizedLCLAlgorithm( ParameterList &list, const Ptr> &secant ) + : TypeG::Algorithm::Algorithm(), secant_(secant), list_(list), subproblemIter_(0) { // Set status test status_->reset(); status_->add(makePtr>(list)); @@ -268,7 +268,7 @@ void StabilizedLCLAlgorithm::run( Vector &x, // Solve linearly constrained augmented Lagrangian subproblem list_.sublist("Status Test").set("Gradient Tolerance",optTolerance_); list_.sublist("Status Test").set("Step Tolerance",1.e-6*optTolerance_); - algo = TypeB::AlgorithmFactory(list_); + algo = TypeB::AlgorithmFactory(list_,secant_); algo->run(elc,outStream); x.set(*xp->get(0)); diff --git a/packages/rol/src/algorithm/TypeU/ROL_TypeU_AlgorithmFactory.hpp b/packages/rol/src/algorithm/TypeU/ROL_TypeU_AlgorithmFactory.hpp index 06dc44d1e088..11695d24865a 100644 --- a/packages/rol/src/algorithm/TypeU/ROL_TypeU_AlgorithmFactory.hpp +++ b/packages/rol/src/algorithm/TypeU/ROL_TypeU_AlgorithmFactory.hpp @@ -122,12 +122,12 @@ inline EAlgorithmU StringToEAlgorithmU(std::string s) { } template -inline Ptr> AlgorithmFactory(ParameterList &parlist) { +inline Ptr> AlgorithmFactory(ParameterList &parlist, const Ptr> &secant = nullPtr) { EAlgorithmU ealg = StringToEAlgorithmU(parlist.sublist("Step").get("Type","Trust Region")); switch(ealg) { case ALGORITHM_U_BUNDLE: return makePtr>(parlist); - case ALGORITHM_U_LINESEARCH: return makePtr>(parlist); - case ALGORITHM_U_TRUSTREGION: return makePtr>(parlist); + case ALGORITHM_U_LINESEARCH: return makePtr>(parlist,secant); + case ALGORITHM_U_TRUSTREGION: return makePtr>(parlist,secant); default: return nullPtr; } } diff --git a/packages/rol/src/algorithm/TypeU/ROL_TypeU_LineSearchAlgorithm.hpp b/packages/rol/src/algorithm/TypeU/ROL_TypeU_LineSearchAlgorithm.hpp index a3bfc78e6112..00134e2aab8f 100644 --- a/packages/rol/src/algorithm/TypeU/ROL_TypeU_LineSearchAlgorithm.hpp +++ b/packages/rol/src/algorithm/TypeU/ROL_TypeU_LineSearchAlgorithm.hpp @@ -48,6 +48,7 @@ #include "ROL_LineSearch_U_Types.hpp" #include "ROL_DescentDirection_U.hpp" #include "ROL_LineSearch_U.hpp" +#include "ROL_Secant.hpp" /** \class ROL::TypeU::LineSearchAlgorithm \brief Provides an interface to run unconstrained line search algorithms. @@ -135,6 +136,7 @@ class LineSearchAlgorithm : public Algorithm { @param[in] lineSearch is a user-defined line search object */ LineSearchAlgorithm( ParameterList &parlist, + const Ptr> &secant = nullPtr, const Ptr> &descent = nullPtr, const Ptr> &lineSearch = nullPtr ); diff --git a/packages/rol/src/algorithm/TypeU/ROL_TypeU_LineSearchAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeU/ROL_TypeU_LineSearchAlgorithm_Def.hpp index ccd78d6a2cd8..f039d5fd910c 100644 --- a/packages/rol/src/algorithm/TypeU/ROL_TypeU_LineSearchAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeU/ROL_TypeU_LineSearchAlgorithm_Def.hpp @@ -52,6 +52,7 @@ namespace TypeU { template LineSearchAlgorithm::LineSearchAlgorithm( ParameterList &parlist, + const Ptr> &secant, const Ptr> &descent, const Ptr> &lineSearch ) : Algorithm(), desc_(descent), lineSearch_(lineSearch), @@ -81,7 +82,7 @@ LineSearchAlgorithm::LineSearchAlgorithm( ParameterList &parlist, ParameterList& dlist = Llist.sublist("Descent Method"); descentName_ = dlist.get("Type","Quasi-Newton Method"); edesc_ = StringToEDescentU(descentName_); - desc_ = DescentDirectionUFactory(parlist); + desc_ = DescentDirectionUFactory(parlist,secant); } else { descentName_ = Llist.sublist("Descent Method").get("User Defined Descent Direction Name","Unspecified User Defined Descent Direction"); diff --git a/packages/rol/src/algorithm/TypeU/linesearch/descent/ROL_DescentDirection_U_Factory.hpp b/packages/rol/src/algorithm/TypeU/linesearch/descent/ROL_DescentDirection_U_Factory.hpp index 35e3061025e7..d754edf8e450 100644 --- a/packages/rol/src/algorithm/TypeU/linesearch/descent/ROL_DescentDirection_U_Factory.hpp +++ b/packages/rol/src/algorithm/TypeU/linesearch/descent/ROL_DescentDirection_U_Factory.hpp @@ -52,15 +52,19 @@ namespace ROL { template -inline Ptr> DescentDirectionUFactory(ParameterList &parlist) { +inline Ptr> DescentDirectionUFactory(ParameterList &parlist, const Ptr> &secant = nullPtr) { EDescentU edesc = StringToEDescentU( parlist.sublist("Step").sublist("Line Search").sublist("Descent Method").get("Type","Quasi-Newton Method")); switch(edesc) { case DESCENT_U_STEEPEST: return makePtr>(); case DESCENT_U_NONLINEARCG: return makePtr>(parlist); - case DESCENT_U_SECANT: return makePtr>(parlist); + case DESCENT_U_SECANT: return makePtr>(parlist, secant); case DESCENT_U_NEWTON: return makePtr>(); - case DESCENT_U_NEWTONKRYLOV: return makePtr>(parlist); + case DESCENT_U_NEWTONKRYLOV: + { + Ptr> krylov = nullPtr; + return makePtr>(parlist,krylov,secant); + } default: return nullPtr; } } diff --git a/packages/rol/src/algorithm/TypeU/linesearch/descent/ROL_NewtonKrylov_U.hpp b/packages/rol/src/algorithm/TypeU/linesearch/descent/ROL_NewtonKrylov_U.hpp index 0b0f180c8a02..8c4f153969db 100644 --- a/packages/rol/src/algorithm/TypeU/linesearch/descent/ROL_NewtonKrylov_U.hpp +++ b/packages/rol/src/algorithm/TypeU/linesearch/descent/ROL_NewtonKrylov_U.hpp @@ -140,7 +140,7 @@ class NewtonKrylov_U : public DescentDirection_U { @param[in] secant is a user-defined secant object */ NewtonKrylov_U(ParameterList &parlist, const Ptr> &krylov, - Ptr> &secant, const bool computeObj = true) + const Ptr> &secant, const bool computeObj = true) : secant_(secant), krylov_(krylov), ekv_(KRYLOV_USERDEFINED), esec_(SECANT_USERDEFINED), useSecantPrecond_(false) { From e706ad74ab15213999ab371191433123221e2807 Mon Sep 17 00:00:00 2001 From: Bobby Date: Tue, 16 May 2023 11:59:29 -0600 Subject: [PATCH 45/65] l1 fluid flow cylinder example, no cmake --- .../dynamic/navier-stokes/example_01_l1.cpp | 467 ++++++++++++++++++ .../navier-stokes/l1penaltydynamic.hpp | 159 ++++++ 2 files changed, 626 insertions(+) create mode 100644 packages/rol/example/PDE-OPT/dynamic/navier-stokes/example_01_l1.cpp create mode 100644 packages/rol/example/PDE-OPT/dynamic/navier-stokes/l1penaltydynamic.hpp diff --git a/packages/rol/example/PDE-OPT/dynamic/navier-stokes/example_01_l1.cpp b/packages/rol/example/PDE-OPT/dynamic/navier-stokes/example_01_l1.cpp new file mode 100644 index 000000000000..c601f009995a --- /dev/null +++ b/packages/rol/example/PDE-OPT/dynamic/navier-stokes/example_01_l1.cpp @@ -0,0 +1,467 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +/*! \file example_01_l1.cpp + \brief Shows how to solve the Navier-Stokes control problem. +*/ + +#include "Teuchos_Comm.hpp" +#include "Teuchos_GlobalMPISession.hpp" +#include "Tpetra_Core.hpp" +#include "Tpetra_Version.hpp" + +#include +#include +//#include + +#include "ROL_Bounds.hpp" +#include "ROL_Stream.hpp" +#include "ROL_ParameterList.hpp" +#include "ROL_OptimizationSolver.hpp" +#include "ROL_ReducedDynamicObjective.hpp" +#include "ROL_DynamicConstraintCheck.hpp" +#include "ROL_DynamicObjectiveCheck.hpp" + +#include "../../TOOLS/dynconstraint.hpp" +#include "../../TOOLS/pdeconstraint.hpp" +#include "../../TOOLS/pdeobjective.hpp" +#include "../../TOOLS/ltiobjective.hpp" +#include "../../TOOLS/meshreader.hpp" +#include "../../TOOLS/pdevector.hpp" +#include "dynpde_navier-stokes.hpp" +#include "obj_navier-stokes.hpp" +#include "initial_condition.hpp" +#include "l1penaltydynamic.hpp" + +#include "ROL_TypeP_TrustRegionAlgorithm.hpp" + +template +void computeInitialCondition(const ROL::Ptr> &u0, + const ROL::Ptr> &ck, + const ROL::Ptr> &uo, + const ROL::Ptr> &un, + const ROL::Ptr> &zk, + const ROL::Ptr> &con, + const Real dt, + std::ostream &outStream); + +int main(int argc, char *argv[]) { + //feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW); + using RealT = double; + + /*** Initialize communicator. ***/ + Teuchos::GlobalMPISession mpiSession(&argc, &argv); + ROL::Ptr> comm + = Tpetra::getDefaultComm(); + + // This little trick lets us print to std::cout only if a (dummy) command-line argument is provided. + const int numProcs = (comm->getSize() > 1) ? comm->getSize() : 0; + const int myRank = comm->getRank(); + ROL::Ptr outStream = ROL::makeStreamPtr( std::cout, (argc > 1) && (myRank==0) ); + + int errorFlag = 0; + + // *** Example body. + try { + + /*** Read in XML input ***/ + ROL::Ptr parlist = ROL::getParametersFromXmlFile("input.xml"); + int nt = parlist->sublist("Time Discretization").get("Number of Time Steps", 100); + RealT T = parlist->sublist("Time Discretization").get("End Time", 1.0); + RealT dt = T/static_cast(nt); + bool useParametricControl = parlist->sublist("Problem").get("Use Parametric Control", true); + int verbosity = parlist->sublist("General").get("Print Verbosity", 0); + verbosity = (myRank==0 ? verbosity : 0); + parlist->sublist("General").set("Print Verbosity", verbosity); + bool solveOutput = parlist->sublist("Dynamic Constraint").sublist("Solve").get("Output Iteration History", false); + solveOutput = (myRank==0 ? solveOutput : false); + parlist->sublist("Dynamic Constraint").sublist("Solve").set("Output Iteration History", solveOutput); + solveOutput = parlist->sublist("SimOpt").sublist("Solve").get("Output Iteration History", false); + solveOutput = (myRank==0 ? solveOutput : false); + parlist->sublist("SimOpt").sublist("Solve").set("Output Iteration History", solveOutput); + RealT Re = parlist->sublist("Problem").get("Reynolds Number",200.0); + + parlist->sublist("Reduced Dynamic Objective").set("State Domain Seed",12321*(myRank+1)); + parlist->sublist("Reduced Dynamic Objective").set("State Range Seed", 32123*(myRank+1)); + parlist->sublist("Reduced Dynamic Objective").set("Adjoint Domain Seed",23432*(myRank+1)); + parlist->sublist("Reduced Dynamic Objective").set("Adjoint Range Seed", 43234*(myRank+1)); + parlist->sublist("Reduced Dynamic Objective").set("State Sensitivity Domain Seed",34543*(myRank+1)); + parlist->sublist("Reduced Dynamic Objective").set("State Sensitivity Range Seed", 54345*(myRank+1)); + + /*************************************************************************/ + /***************** BUILD GOVERNING PDE ***********************************/ + /*************************************************************************/ + /*** Initialize mesh data structure. ***/ + ROL::Ptr> meshMgr + = ROL::makePtr>(*parlist, numProcs); + // Initialize PDE describing Navier-Stokes equations. + ROL::Ptr> pde + = ROL::makePtr>(*parlist); + + /*************************************************************************/ + /***************** BUILD CONSTRAINT **************************************/ + /*************************************************************************/ + ROL::Ptr> dyn_con + = ROL::makePtr>(pde,meshMgr,comm,*parlist,*outStream); + const ROL::Ptr> assembler = dyn_con->getAssembler(); + dyn_con->setSolveParameters(*parlist); + dyn_con->getAssembler()->printMeshData(*outStream); + + /*************************************************************************/ + /***************** BUILD VECTORS *****************************************/ + /*************************************************************************/ + ROL::Ptr> u0_ptr = assembler->createStateVector(); + ROL::Ptr> uo_ptr = assembler->createStateVector(); + ROL::Ptr> un_ptr = assembler->createStateVector(); + ROL::Ptr> ck_ptr = assembler->createResidualVector(); + ROL::Ptr> u0, uo, un, ck, zk; + u0 = ROL::makePtr>(u0_ptr,pde,*assembler,*parlist); + uo = ROL::makePtr>(uo_ptr,pde,*assembler,*parlist); + un = ROL::makePtr>(un_ptr,pde,*assembler,*parlist); + ck = ROL::makePtr>(ck_ptr,pde,*assembler,*parlist); + if (!useParametricControl) { + ROL::Ptr> zk_ptr = assembler->createControlVector(); + zk = ROL::makePtr>(zk_ptr,pde,*assembler,*parlist); + } + else { + zk = ROL::makePtr>(ROL::makePtr>(1)); + } + ROL::Ptr> z + = ROL::PartitionedVector::create(*zk, nt); // nt 'clones' of zk's + + // write l1 obj that takes in rol vector, loops nt entries, grabs + // data from nt entries, sum abs of zk clones + + /*************************************************************************/ + /***************** BUILD COST FUNCTIONAL *********************************/ + /*************************************************************************/ + std::vector>> qoi_vec(3,ROL::nullPtr), qoi_T(1,ROL::nullPtr); + RealT w1 = parlist->sublist("Problem").get("State Cost",1.0); + RealT w2 = parlist->sublist("Problem").get("State Boundary Cost",1.0); + RealT w3 = parlist->sublist("Problem").get("Control Cost",0.0); + RealT wT = parlist->sublist("Problem").get("Final Time State Cost",1.0); + + std::vector wts = {w1, w2, w3}, wts_T = {wT}; + std::string intObj = parlist->sublist("Problem").get("Integrated Objective Type", "Dissipation"); + std::string ftObj = parlist->sublist("Problem").get("Final Time Objective Type", "Tracking"); + + qoi_vec[0] = ROL::makePtr>(intObj, + *parlist, + pde->getVelocityFE(), + pde->getPressureFE(), + pde->getFieldHelper()); + qoi_vec[1] = ROL::makePtr>(pde->getVelocityFE(), + pde->getPressureFE(), + pde->getVelocityBdryFE(1), + pde->getBdryCellLocIds(1), + pde->getFieldHelper()); + qoi_T[0] = ROL::makePtr>(ftObj, + *parlist, + pde->getVelocityFE(), + pde->getPressureFE(), + pde->getFieldHelper()); + if (useParametricControl) { + qoi_vec[2] = ROL::makePtr>(); + } + else { + qoi_vec[2] = ROL::makePtr>(pde->getVelocityFE(), + pde->getPressureFE(), + pde->getVelocityBdryFE(4), + pde->getBdryCellLocIds(4), + pde->getFieldHelper()); + } + ROL::Ptr> obj_k // pde integrated obj + = ROL::makePtr>(qoi_vec,wts,assembler); + ROL::Ptr> obj_T // final time obj + = ROL::makePtr>(qoi_T,wts_T,assembler); + ROL::Ptr> dyn_obj // combination + = ROL::makePtr>(*parlist,obj_k,obj_T);// integrates over interval, added over timepoints somewhere + + /*************************************************************************/ + /***************** BUILD REDUCED COST FUNCTIONAL *************************/ + /*************************************************************************/ + std::vector> timeStamp(nt); + for( int k=0; k(Re) << ".txt"; + std::ifstream infile(file.str()); + if (infile.good()) { + dyn_con->inputTpetraVector(u0_ptr, file.str()); + } + else { + PotentialFlow pf(pde->getVelocityFE(), + pde->getPressureFE(), + pde->getCellNodes(), + assembler->getDofManager()->getCellDofs(), + assembler->getCellIds(), + pde->getFieldHelper(), + *parlist); + pf.build(u0_ptr); + computeInitialCondition(u0,ck,uo,un,zk,dyn_con,dt,*outStream); + dyn_con->outputTpetraVector(u0_ptr, file.str()); + } + *outStream << "Initial condition time: " + << static_cast(std::clock()-timer_init)/static_cast(CLOCKS_PER_SEC) + << " seconds." << std::endl << std::endl; + // Construct reduce dynamic objective function + ROL::ParameterList &rpl = parlist->sublist("Reduced Dynamic Objective"); + ROL::Ptr> obj + = ROL::makePtr>(dyn_obj, dyn_con, u0, zk, ck, timeStamp, rpl, outStream);// summing over + // create l1 dynamic objective for nobj, pass to TRnonsmooth + ROL::Ptr> nobj + = ROL::makePtr>(rpl,timeStamp); + + //Algo pointer + ROL::Ptr> algo; + + /*************************************************************************/ + /***************** RUN VECTOR AND DERIVATIVE CHECKS **********************/ + /*************************************************************************/ + bool checkDeriv = parlist->sublist("Problem").get("Check Derivatives",false); + if ( checkDeriv ) { + ROL::Ptr> dz = ROL::PartitionedVector::create(*zk, nt); + ROL::Ptr> hz = ROL::PartitionedVector::create(*zk, nt); + zk->randomize(); z->randomize(); dz->randomize(); hz->randomize(); + uo->randomize(); un->randomize(); + ROL::ValidateFunction validate(1,13,20,11,true,*outStream); + ROL::DynamicObjectiveCheck::check(*dyn_obj,validate,*uo,*un,*zk); + ROL::DynamicConstraintCheck::check(*dyn_con,validate,*uo,*un,*zk); + obj->checkGradient(*z,*dz,true,*outStream); + obj->checkHessVec(*z,*dz,true,*outStream); + obj->checkHessSym(*z,*dz,*hz,true,*outStream); + } + + /*************************************************************************/ + /***************** RUN VECTOR AND DERIVATIVE CHECKS **********************/ + /*************************************************************************/ + bool printU0 = parlist->sublist("Problem").get("Print Uncontrolled State", false); + if (printU0) { + std::clock_t timer_print0 = std::clock(); + zk->zero(); uo->set(*u0); un->zero(); + for (int k = 1; k < nt; ++k) { + // Print previous state to file + std::stringstream u0file; + u0file << "uncontrolled_state." << k-1 << ".txt"; + dyn_con->outputTpetraVector(uo_ptr, u0file.str()); + // Advance time stepper + dyn_con->solve(*ck, *uo, *un, *zk, timeStamp[k]); + uo->set(*un); + } + // Print previous state to file + std::stringstream u0file; + u0file << "uncontrolled_state." << nt-1 << ".txt"; + dyn_con->outputTpetraVector(uo_ptr, u0file.str()); + *outStream << "Output uncontrolled state time: " + << static_cast(std::clock()-timer_print0)/static_cast(CLOCKS_PER_SEC) + << " seconds." << std::endl << std::endl; + } + + /*************************************************************************/ + /***************** SOLVE OPTIMIZATION PROBLEM ****************************/ + /*************************************************************************/ + z->zero(); + if (useParametricControl) { + // Linearly interpolate between optimal values for angular velocity + // amplitude and Strouhal number obtained for Re=200, 1000 in + // JW He, R Glowinski, R Metcalfe, A Nordlander, J Periaux + // Active Control and Drag Optimization for Flow Past a + // Circular Cylinder + // Journal of Computation Physics, 163, pg. 83-117, 2000. + RealT Re = parlist->sublist("Problem").get("Reynolds Number",200.0); + RealT amp0 = 6.0 - (Re - 200.0)/1600.0; + RealT Se0 = 0.74 - (Re - 200.0) * (0.115/800.0); + RealT amp = parlist->sublist("Problem").sublist("Initial Guess").get("Amplitude", amp0); + RealT Se = parlist->sublist("Problem").sublist("Initial Guess").get("Strouhal Number", Se0); + RealT ph = parlist->sublist("Problem").sublist("Initial Guess").get("Phase Shift", 0.0); + for( int k=0; k> zn + = ROL::dynamicPtrCast>(z->get(k))->getParameter()->getVector(); + (*zn)[0] = -amp * std::sin(2.0 * M_PI * Se * timeStamp[k].t[0] + ph); + } + } + parlist->sublist("Step").sublist("Trust Region").sublist("TRN").sublist("Solver").set("Subproblem Solver", "NCG"); + algo = ROL::makePtr>(*parlist); + + //ROL::OptimizationProblem problem(obj,z);// need to change this + //ROL::OptimizationSolver solver(problem,*parlist);// need to change this + std::clock_t timer = std::clock(); + //solver.solve(*outStream); + algo->run(*un, *obj, *nobj, *outStream); + *outStream << "Optimization time: " + << static_cast(std::clock()-timer)/static_cast(CLOCKS_PER_SEC) + << " seconds." << std::endl << std::endl; + + /*************************************************************************/ + /***************** OUTPUT RESULTS ****************************************/ + /*************************************************************************/ + std::clock_t timer_print = std::clock(); + // Output state and control to file + uo->set(*u0); un->zero(); + for (int k = 1; k < nt; ++k) { + // Print previous state to file + std::stringstream ufile; + ufile << "state." << k-1 << ".txt"; + dyn_con->outputTpetraVector(uo_ptr, ufile.str()); + // Print current control + if (!useParametricControl) { + std::stringstream zfile; + zfile << "control." << k-1 << ".txt"; + dyn_con->outputTpetraVector(ROL::dynamicPtrCast>(z->get(k-1))->getVector(),zfile.str()); + } + else { + if (myRank == 0) { + std::stringstream zname; + zname << "control." << k-1 << ".txt"; + std::ofstream zfile; + zfile.open(zname.str()); + zfile << std::scientific << std::setprecision(15); + ROL::Ptr> zn + = ROL::dynamicPtrCast>(z->get(k-1))->getParameter()->getVector(); + zfile << std::right << std::setw(25) << (*zn)[0]; + zfile.close(); + } + } + // Advance time stepper + dyn_con->solve(*ck, *uo, *un, *z->get(k), timeStamp[k]); + uo->set(*un); + } + // Print previous state to file + std::stringstream ufile; + ufile << "state." << nt-1 << ".txt"; + dyn_con->outputTpetraVector(uo_ptr, ufile.str()); + // Print current control + if (!useParametricControl) { + std::stringstream zfile; + zfile << "control." << nt-1 << ".txt"; + dyn_con->outputTpetraVector(ROL::dynamicPtrCast>(z->get(nt-1))->getVector(),zfile.str()); + } + else { + if (myRank == 0) { + std::stringstream zname; + zname << "control." << nt-1 << ".txt"; + std::ofstream zfile; + zfile.open(zname.str()); + zfile << std::scientific << std::setprecision(15); + ROL::Ptr> zn + = ROL::dynamicPtrCast>(z->get(nt-1))->getParameter()->getVector(); + zfile << std::right << std::setw(25) << (*zn)[0]; + zfile.close(); + } + } + *outStream << "Output time: " + << static_cast(std::clock()-timer_print)/static_cast(CLOCKS_PER_SEC) + << " seconds." << std::endl << std::endl; + } + catch (std::logic_error& err) { + *outStream << err.what() << "\n"; + errorFlag = -1000; + }; // end try + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return 0; +} + +template +void computeInitialCondition(const ROL::Ptr> &u0, + const ROL::Ptr> &ck, + const ROL::Ptr> &uo, + const ROL::Ptr> &un, + const ROL::Ptr> &zk, + const ROL::Ptr> &con, + const Real dt, + std::ostream &outStream) { + Real T = 80.0; + int nt = static_cast(T/dt); + std::vector> ts(nt); + for( int k=0; kzero(); uo->set(*u0); un->zero(); + Real unorm = uo->norm(); + outStream << std::scientific << std::setprecision(6); + outStream << std::right << std::setw(8) << "ts" + << std::right << std::setw(16) << "||u(ts)||" + << std::right << std::setw(16) << "avg time (sec)" + << std::endl; + outStream << std::right << std::setw(8) << 0 + << std::right << std::setw(16) << unorm + << std::right << std::setw(16) << "---" + << std::endl; + std::vector time(10); + std::clock_t timer_step; + Real time_avg(0); + for (int k = 1; k < nt; ++k) { + // Advance time stepper + timer_step = std::clock(); + con->solve(*ck, *uo, *un, *zk, ts[k]); + time[k%10] = static_cast(std::clock()-timer_step)/static_cast(CLOCKS_PER_SEC); + uo->set(*un); + if ( k%10==0 ) { + unorm = uo->norm(); + time_avg = 0.0; + for (int i = 0; i < 10; ++i) { + time_avg += time[i]; + } + time_avg *= 0.1; + outStream << std::right << std::setw(8) << k + << std::right << std::setw(16) << unorm + << std::right << std::setw(16) << time_avg + << std::endl; + } + } + u0->set(*uo); +} + + diff --git a/packages/rol/example/PDE-OPT/dynamic/navier-stokes/l1penaltydynamic.hpp b/packages/rol/example/PDE-OPT/dynamic/navier-stokes/l1penaltydynamic.hpp new file mode 100644 index 000000000000..ec126a2bf9dc --- /dev/null +++ b/packages/rol/example/PDE-OPT/dynamic/navier-stokes/l1penaltydynamic.hpp @@ -0,0 +1,159 @@ + +#ifndef L1DYNOBJECTIVE_HPP +#define L1DYNOBJECTIVE_HPP + +#include "ROL_Objective.hpp" +#include "../../TOOLS/ltiobjective.hpp" +#include "../../TOOLS/meshreader.hpp" +#include "../../TOOLS/pdevector.hpp" + +namespace ROL { + +template +class L1_Dyn_Objective : public ROL::Objective { + using size_type = typename std::vector::size_type; +private: + Real theta_, beta_; + const size_type Nt_; + const std::vector> ts_; + ROL::PartitionedVector &partition ( Vector& x ) const { + return static_cast&>(x); + } + + const ROL::PartitionedVector &partition ( const Vector& x ) const { + return static_cast&>(x); + } + + ROL::Ptr > getConstParameter(const ROL::Vector &x) const { + ROL::Ptr > xp; + try { + xp = dynamic_cast&>(x).getVector(); + } + catch (std::exception &e) { + try { + ROL::Ptr > xvec + = dynamic_cast&>(x).getParameter(); + if ( xvec == ROL::nullPtr ) { + xp = ROL::nullPtr; + } + else { + xp = xvec->getVector(); + } + } + catch (std::exception &ee) { + xp = ROL::nullPtr; + } + } + return xp; + } + + ROL::Ptr > getParameter(ROL::Vector &x) const { + ROL::Ptr > xp; + try { + xp = dynamic_cast&>(x).getVector(); + } + catch (std::exception &e) { + try { + ROL::Ptr > xvec + = dynamic_cast&>(x).getParameter(); + if ( xvec == ROL::nullPtr ) { + xp = ROL::nullPtr; + } + else { + xp = xvec->getVector(); + } + } + catch (std::exception &ee) { + xp = ROL::nullPtr; + } + } + return xp; + } + + struct ProjSymBnd : public Elementwise::BinaryFunction { + Real apply(const Real &xc, const Real &yc) const { return std::min(yc, std::max(-yc, xc)); } + } psb_; + + public: + L1_Dyn_Objective(ROL::ParameterList &parlist, + const std::vector> &timeStamp + ) : Nt_(timeStamp.size()), ts_(timeStamp){ + theta_ = parlist.sublist("Time Discretization").get("Theta", 1.0); + beta_ = parlist.get("L1 Parameter", 1e-2); + } + + // value + Real value(const ROL::Vector &z, + Real &tol + ){ + + const PartitionedVector &zp = partition(z); + const Real one(1); + Real dt(0), val(0); + + for (size_type k = 1; k < Nt_; ++k){//dynamic obj + + ROL::Ptr> zpn = getConstParameter(*zp.get(k)); // ROL vector of partition/kth timestep + ROL::Ptr> zpo = getConstParameter(*zp.get(k-1)); // ROL vector of partition/kth timestep + dt = ts_[k].t[1] - ts_[k].t[0]; + for (size_type i = 0; i < zpn->size(); ++i){ + val += dt*((one - theta_)*std::abs((*zpo)[i]) + theta_*std::abs((*zpn)[i])); + } // end i for + }// end k for + return beta_*val; + } //end value + + // prox + void prox(Vector &Pz, + const Vector &z, + Real t, + Real &tol + ) + { + + //partitioned vectors + const PartitionedVector &zp = partition(z); + PartitionedVector &Pzp = partition(Pz); + + //constants + const Real one(1), zero(0); + Real hk(0), hkplus(0); + Real l1param(0); + + for (size_type k = 0; k<=Nt_; ++k) {//dynamic part; 0->Nt inclusive + + ROL::Ptr> zk = getConstParameter(zp[k]); //kth timestep + ROL::Ptr> Pzk = getParameter(Pzp[k]); + + // update prox parameter + if (k == 0){ + hkplus = ts_[k+1].t[1] - ts_[k+1].t[0]; + l1param = t*hkplus*beta_*theta_; + } else if (k == Nt_) { + hk = ts_[k].t[1] - ts_[k].t[0]; + l1param = t*hk*beta_*(one - theta_); + } else { + hk = ts_[k].t[1] - ts_[k].t[0]; + hkplus = ts_[k+1].t[1] - ts_[k+1].t[0]; + l1param = t*beta_*(hk*(one - theta_) + theta_*hkplus); + } + + //Pzk.set(*shift_);//no shift + //Pzk.axpy(static_cast(-1), zk); + //Pzk.scale(static_cast(1)/t); //not right with t in l1param + //Pzk.applyBinary(psb_, l1param); //instead of weights + //Pzk.scale(t); //not scaled right + //Pzk.plus(zk); + + for (size_type i = 0; i < zk->size(); ++i){ + if ((*zk)[i] > l1param) { (*Pzk)[i] = (*zk)[i] + l1param; } + else if ((*zk)[i] < l1param) {(*Pzk)[i] = (*zk)[i] - l1param;} + else { (*Pzk)[i] = zero;} + } // end i loop + + }//end k for + + }//end prox +}; +}// namespace rol +#endif From 8b388797abbf993dad29d59224fb62765c77786c Mon Sep 17 00:00:00 2001 From: Bobby Date: Tue, 16 May 2023 12:14:00 -0600 Subject: [PATCH 46/65] no rol namespace in NS l1 example --- .../dynamic/navier-stokes/example_01_l1.cpp | 4 +-- .../navier-stokes/l1penaltydynamic.hpp | 25 +++++++++---------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/packages/rol/example/PDE-OPT/dynamic/navier-stokes/example_01_l1.cpp b/packages/rol/example/PDE-OPT/dynamic/navier-stokes/example_01_l1.cpp index c601f009995a..7638e132ef5a 100644 --- a/packages/rol/example/PDE-OPT/dynamic/navier-stokes/example_01_l1.cpp +++ b/packages/rol/example/PDE-OPT/dynamic/navier-stokes/example_01_l1.cpp @@ -253,8 +253,8 @@ int main(int argc, char *argv[]) { ROL::Ptr> obj = ROL::makePtr>(dyn_obj, dyn_con, u0, zk, ck, timeStamp, rpl, outStream);// summing over // create l1 dynamic objective for nobj, pass to TRnonsmooth - ROL::Ptr> nobj - = ROL::makePtr>(rpl,timeStamp); + ROL::Ptr> nobj + = ROL::makePtr>(rpl,timeStamp); //Algo pointer ROL::Ptr> algo; diff --git a/packages/rol/example/PDE-OPT/dynamic/navier-stokes/l1penaltydynamic.hpp b/packages/rol/example/PDE-OPT/dynamic/navier-stokes/l1penaltydynamic.hpp index ec126a2bf9dc..6dfcac9db736 100644 --- a/packages/rol/example/PDE-OPT/dynamic/navier-stokes/l1penaltydynamic.hpp +++ b/packages/rol/example/PDE-OPT/dynamic/navier-stokes/l1penaltydynamic.hpp @@ -7,7 +7,6 @@ #include "../../TOOLS/meshreader.hpp" #include "../../TOOLS/pdevector.hpp" -namespace ROL { template class L1_Dyn_Objective : public ROL::Objective { @@ -16,12 +15,12 @@ class L1_Dyn_Objective : public ROL::Objective { Real theta_, beta_; const size_type Nt_; const std::vector> ts_; - ROL::PartitionedVector &partition ( Vector& x ) const { - return static_cast&>(x); + ROL::PartitionedVector &partition ( ROL::Vector& x ) const { + return static_cast&>(x); } - const ROL::PartitionedVector &partition ( const Vector& x ) const { - return static_cast&>(x); + const ROL::PartitionedVector &partition ( const ROL::Vector& x ) const { + return static_cast&>(x); } ROL::Ptr > getConstParameter(const ROL::Vector &x) const { @@ -70,13 +69,13 @@ class L1_Dyn_Objective : public ROL::Objective { return xp; } - struct ProjSymBnd : public Elementwise::BinaryFunction { + struct ProjSymBnd : public ROL::Elementwise::BinaryFunction { Real apply(const Real &xc, const Real &yc) const { return std::min(yc, std::max(-yc, xc)); } } psb_; public: L1_Dyn_Objective(ROL::ParameterList &parlist, - const std::vector> &timeStamp + const std::vector> &timeStamp ) : Nt_(timeStamp.size()), ts_(timeStamp){ theta_ = parlist.sublist("Time Discretization").get("Theta", 1.0); beta_ = parlist.get("L1 Parameter", 1e-2); @@ -87,7 +86,7 @@ class L1_Dyn_Objective : public ROL::Objective { Real &tol ){ - const PartitionedVector &zp = partition(z); + const ROL::PartitionedVector &zp = partition(z); const Real one(1); Real dt(0), val(0); @@ -104,16 +103,16 @@ class L1_Dyn_Objective : public ROL::Objective { } //end value // prox - void prox(Vector &Pz, - const Vector &z, + void prox(ROL::Vector &Pz, + const ROL::Vector &z, Real t, Real &tol ) { //partitioned vectors - const PartitionedVector &zp = partition(z); - PartitionedVector &Pzp = partition(Pz); + const ROL::PartitionedVector &zp = partition(z); + ROL::PartitionedVector &Pzp = partition(Pz); //constants const Real one(1), zero(0); @@ -155,5 +154,5 @@ class L1_Dyn_Objective : public ROL::Objective { }//end prox }; -}// namespace rol + #endif From bd25f9229e9816dd0069c234c59e982850f0a354 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Wed, 7 Jun 2023 10:24:58 -0600 Subject: [PATCH 47/65] 1.) Updated dynamic interface to use new update (in progrress). 2.) Updated TypeB algorithms so that they do not write to a stringstream. 3.) Added a test to verify that prox gradient defaults to gradient descent when the nonsmooth term is zero. --- packages/rol/example/CMakeLists.txt | 1 + .../PDE-OPT/dynamic/adv_diff/example_01.cpp | 7 +- .../dynamic/navier-stokes/example_01.cpp | 7 +- .../PDE-OPT/navier-stokes/CMakeLists.txt | 6 + .../TypeB/ROL_TypeB_Algorithm_Def.hpp | 62 ++++---- .../ROL_TypeB_ColemanLiAlgorithm_Def.hpp | 142 +++++++++--------- .../TypeB/ROL_TypeB_GradientAlgorithm_Def.hpp | 92 ++++++------ .../ROL_TypeB_InteriorPointAlgorithm_Def.hpp | 122 +++++++-------- .../ROL_TypeB_KelleySachsAlgorithm_Def.hpp | 130 ++++++++-------- .../TypeB/ROL_TypeB_LSecantBAlgorithm_Def.hpp | 120 +++++++-------- .../TypeB/ROL_TypeB_LinMoreAlgorithm_Def.hpp | 138 ++++++++--------- .../ROL_TypeB_MoreauYosidaAlgorithm_Def.hpp | 118 +++++++-------- .../ROL_TypeB_NewtonKrylovAlgorithm_Def.hpp | 122 +++++++-------- ...TypeB_PrimalDualActiveSetAlgorithm_Def.hpp | 138 ++++++++--------- .../ROL_TypeB_QuasiNewtonAlgorithm_Def.hpp | 116 +++++++------- ...OL_TypeB_SpectralGradientAlgorithm_Def.hpp | 108 ++++++------- .../ROL_TypeB_TrustRegionSPGAlgorithm_Def.hpp | 140 ++++++++--------- .../TypeU/ROL_TypeU_LineSearchAlgorithm.hpp | 1 + .../dynamic/ROL_ReducedDynamicObjective.hpp | 22 +++ .../rol/src/function/sketching/ROL_Sketch.hpp | 16 ++ .../rol/test/algorithm/TypeP/CMakeLists.txt | 9 ++ 21 files changed, 837 insertions(+), 780 deletions(-) diff --git a/packages/rol/example/CMakeLists.txt b/packages/rol/example/CMakeLists.txt index 5c58be7b2fb9..455edd1462f4 100644 --- a/packages/rol/example/CMakeLists.txt +++ b/packages/rol/example/CMakeLists.txt @@ -23,6 +23,7 @@ ADD_SUBDIRECTORY(dense-hessian) ADD_SUBDIRECTORY(stream-buffer) ADD_SUBDIRECTORY(oed) ADD_SUBDIRECTORY(lincon-test) +ADD_SUBDIRECTORY(shardes) IF(${PACKAGE_NAME}_ENABLE_Sacado) ADD_SUBDIRECTORY(sacado) diff --git a/packages/rol/example/PDE-OPT/dynamic/adv_diff/example_01.cpp b/packages/rol/example/PDE-OPT/dynamic/adv_diff/example_01.cpp index c1e8adafe9f8..504a35219c89 100644 --- a/packages/rol/example/PDE-OPT/dynamic/adv_diff/example_01.cpp +++ b/packages/rol/example/PDE-OPT/dynamic/adv_diff/example_01.cpp @@ -53,7 +53,7 @@ #include "ROL_Stream.hpp" #include "ROL_ParameterList.hpp" -#include "ROL_OptimizationSolver.hpp" +#include "ROL_Solver.hpp" #include "ROL_ReducedDynamicObjective.hpp" #include "ROL_Bounds.hpp" #include "ROL_DynamicConstraintCheck.hpp" @@ -185,8 +185,9 @@ int main(int argc, char *argv[]) { /*************************************************************************/ /***************** SOLVE OPTIMIZATION PROBLEM ****************************/ /*************************************************************************/ - ROL::OptimizationProblem problem(obj,z,bnd); - ROL::OptimizationSolver solver(problem,*parlist); + auto problem = ROL::makePtr>(obj,z); + problem->addBoundConstraint(bnd); + ROL::Solver solver(problem,*parlist); z->zero(); std::clock_t timer = std::clock(); solver.solve(*outStream); diff --git a/packages/rol/example/PDE-OPT/dynamic/navier-stokes/example_01.cpp b/packages/rol/example/PDE-OPT/dynamic/navier-stokes/example_01.cpp index 3b5e1ef9c39d..f3b6d269e787 100644 --- a/packages/rol/example/PDE-OPT/dynamic/navier-stokes/example_01.cpp +++ b/packages/rol/example/PDE-OPT/dynamic/navier-stokes/example_01.cpp @@ -57,7 +57,7 @@ #include "ROL_Bounds.hpp" #include "ROL_Stream.hpp" #include "ROL_ParameterList.hpp" -#include "ROL_OptimizationSolver.hpp" +#include "ROL_Solver.hpp" #include "ROL_ReducedDynamicObjective.hpp" #include "ROL_DynamicConstraintCheck.hpp" #include "ROL_DynamicObjectiveCheck.hpp" @@ -310,8 +310,9 @@ int main(int argc, char *argv[]) { (*zn)[0] = -amp * std::sin(2.0 * M_PI * Se * timeStamp[k].t[0] + ph); } } - ROL::OptimizationProblem problem(obj,z); - ROL::OptimizationSolver solver(problem,*parlist); + ROL::Ptr> problem = ROL::makePtr>(obj,z); + problem->finalize(false,true,*outStream); + ROL::Solver solver(problem,*parlist); std::clock_t timer = std::clock(); solver.solve(*outStream); *outStream << "Optimization time: " diff --git a/packages/rol/example/PDE-OPT/navier-stokes/CMakeLists.txt b/packages/rol/example/PDE-OPT/navier-stokes/CMakeLists.txt index 138990ae9eac..d0e32f490fa7 100644 --- a/packages/rol/example/PDE-OPT/navier-stokes/CMakeLists.txt +++ b/packages/rol/example/PDE-OPT/navier-stokes/CMakeLists.txt @@ -41,6 +41,12 @@ IF(${PROJECT_NAME}_ENABLE_Intrepid AND ADD_DIR_TO_NAME ) + TRIBITS_ADD_EXECUTABLE( + example_06 + SOURCES example_06.cpp + ADD_DIR_TO_NAME + ) + TRIBITS_ADD_TEST( example_01 ARGS PrintItAll diff --git a/packages/rol/src/algorithm/TypeB/ROL_TypeB_Algorithm_Def.hpp b/packages/rol/src/algorithm/TypeB/ROL_TypeB_Algorithm_Def.hpp index 5cf3b4e41ddd..f9d765fb28c7 100644 --- a/packages/rol/src/algorithm/TypeB/ROL_TypeB_Algorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeB/ROL_TypeB_Algorithm_Def.hpp @@ -258,16 +258,16 @@ void Algorithm::run( Vector &x, template void Algorithm::writeHeader( std::ostream& os ) const { - std::stringstream hist; - hist << " "; - hist << std::setw(6) << std::left << "iter"; - hist << std::setw(15) << std::left << "value"; - hist << std::setw(15) << std::left << "gnorm"; - hist << std::setw(15) << std::left << "snorm"; - hist << std::setw(10) << std::left << "#fval"; - hist << std::setw(10) << std::left << "#grad"; - hist << std::endl; - os << hist.str(); + std::ios_base::fmtflags osFlags(os.flags()); + os << " "; + os << std::setw(6) << std::left << "iter"; + os << std::setw(15) << std::left << "value"; + os << std::setw(15) << std::left << "gnorm"; + os << std::setw(15) << std::left << "snorm"; + os << std::setw(10) << std::left << "#fval"; + os << std::setw(10) << std::left << "#grad"; + os << std::endl; + os.flags(osFlags); } template @@ -277,36 +277,36 @@ void Algorithm::writeName( std::ostream &os ) const { template void Algorithm::writeOutput( std::ostream& os, bool write_header ) const { - std::stringstream hist; - hist << std::scientific << std::setprecision(6); + std::ios_base::fmtflags osFlags(os.flags()); + os << std::scientific << std::setprecision(6); if ( write_header ) writeHeader(os); if ( state_->iter == 0 ) { - hist << " "; - hist << std::setw(6) << std::left << state_->iter; - hist << std::setw(15) << std::left << state_->value; - hist << std::setw(15) << std::left << state_->gnorm; - hist << std::endl; + os << " "; + os << std::setw(6) << std::left << state_->iter; + os << std::setw(15) << std::left << state_->value; + os << std::setw(15) << std::left << state_->gnorm; + os << std::endl; } else { - hist << " "; - hist << std::setw(6) << std::left << state_->iter; - hist << std::setw(15) << std::left << state_->value; - hist << std::setw(15) << std::left << state_->gnorm; - hist << std::setw(15) << std::left << state_->snorm; - hist << std::setw(10) << std::left << state_->nfval; - hist << std::setw(10) << std::left << state_->ngrad; - hist << std::endl; + os << " "; + os << std::setw(6) << std::left << state_->iter; + os << std::setw(15) << std::left << state_->value; + os << std::setw(15) << std::left << state_->gnorm; + os << std::setw(15) << std::left << state_->snorm; + os << std::setw(10) << std::left << state_->nfval; + os << std::setw(10) << std::left << state_->ngrad; + os << std::endl; } - os << hist.str(); + os.flags(osFlags); } template void Algorithm::writeExitStatus( std::ostream& os ) const { - std::stringstream hist; - hist << "Optimization Terminated with Status: "; - hist << EExitStatusToString(state_->statusFlag); - hist << std::endl; - os << hist.str(); + std::ios_base::fmtflags osFlags(os.flags()); + os << "Optimization Terminated with Status: "; + os << EExitStatusToString(state_->statusFlag); + os << std::endl; + os.flags(osFlags); } template diff --git a/packages/rol/src/algorithm/TypeB/ROL_TypeB_ColemanLiAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeB/ROL_TypeB_ColemanLiAlgorithm_Def.hpp index 7cca63c40f5b..f2d7195c5c1b 100644 --- a/packages/rol/src/algorithm/TypeB/ROL_TypeB_ColemanLiAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeB/ROL_TypeB_ColemanLiAlgorithm_Def.hpp @@ -419,97 +419,97 @@ void ColemanLiAlgorithm::applyPrecond(Vector &hv, template void ColemanLiAlgorithm::writeHeader( std::ostream& os ) const { - std::stringstream hist; + std::ios_base::fmtflags osFlags(os.flags()); if (verbosity_ > 1) { - hist << std::string(114,'-') << std::endl; - hist << " Coleman-Li affine-scaling trust-region method status output definitions" << std::endl << std::endl; - hist << " iter - Number of iterates (steps taken)" << std::endl; - hist << " value - Objective function value" << std::endl; - hist << " gnorm - Norm of the gradient" << std::endl; - hist << " snorm - Norm of the step (update to optimization vector)" << std::endl; - hist << " delta - Trust-Region radius" << std::endl; - hist << " #fval - Number of times the objective function was evaluated" << std::endl; - hist << " #grad - Number of times the gradient was computed" << std::endl; - hist << " #hess - Number of times the Hessian was applied" << std::endl; - hist << " #proj - Number of times the projection was applied" << std::endl; - hist << std::endl; - hist << " tr_flag - Trust-Region flag" << std::endl; + os << std::string(114,'-') << std::endl; + os << " Coleman-Li affine-scaling trust-region method status output definitions" << std::endl << std::endl; + os << " iter - Number of iterates (steps taken)" << std::endl; + os << " value - Objective function value" << std::endl; + os << " gnorm - Norm of the gradient" << std::endl; + os << " snorm - Norm of the step (update to optimization vector)" << std::endl; + os << " delta - Trust-Region radius" << std::endl; + os << " #fval - Number of times the objective function was evaluated" << std::endl; + os << " #grad - Number of times the gradient was computed" << std::endl; + os << " #hess - Number of times the Hessian was applied" << std::endl; + os << " #proj - Number of times the projection was applied" << std::endl; + os << std::endl; + os << " tr_flag - Trust-Region flag" << std::endl; for( int flag = TRUtils::SUCCESS; flag != TRUtils::UNDEFINED; ++flag ) { - hist << " " << NumberToString(flag) << " - " - << TRUtils::ETRFlagToString(static_cast(flag)) << std::endl; + os << " " << NumberToString(flag) << " - " + << TRUtils::ETRFlagToString(static_cast(flag)) << std::endl; } - hist << std::endl; - hist << " iterCG - Number of Truncated CG iterations" << std::endl << std::endl; - hist << " flagGC - Trust-Region Truncated CG flag" << std::endl; + os << std::endl; + os << " iterCG - Number of Truncated CG iterations" << std::endl << std::endl; + os << " flagGC - Trust-Region Truncated CG flag" << std::endl; for( int flag = CG_FLAG_SUCCESS; flag != CG_FLAG_UNDEFINED; ++flag ) { - hist << " " << NumberToString(flag) << " - " - << ECGFlagToString(static_cast(flag)) << std::endl; + os << " " << NumberToString(flag) << " - " + << ECGFlagToString(static_cast(flag)) << std::endl; } - hist << std::string(114,'-') << std::endl; + os << std::string(114,'-') << std::endl; } - hist << " "; - hist << std::setw(6) << std::left << "iter"; - hist << std::setw(15) << std::left << "value"; - hist << std::setw(15) << std::left << "gnorm"; - hist << std::setw(15) << std::left << "snorm"; - hist << std::setw(15) << std::left << "delta"; - hist << std::setw(10) << std::left << "#fval"; - hist << std::setw(10) << std::left << "#grad"; - hist << std::setw(10) << std::left << "#hess"; - hist << std::setw(10) << std::left << "#proj"; - hist << std::setw(10) << std::left << "tr_flag"; - hist << std::setw(10) << std::left << "iterCG"; - hist << std::setw(10) << std::left << "flagCG"; - hist << std::endl; - os << hist.str(); + os << " "; + os << std::setw(6) << std::left << "iter"; + os << std::setw(15) << std::left << "value"; + os << std::setw(15) << std::left << "gnorm"; + os << std::setw(15) << std::left << "snorm"; + os << std::setw(15) << std::left << "delta"; + os << std::setw(10) << std::left << "#fval"; + os << std::setw(10) << std::left << "#grad"; + os << std::setw(10) << std::left << "#hess"; + os << std::setw(10) << std::left << "#proj"; + os << std::setw(10) << std::left << "tr_flag"; + os << std::setw(10) << std::left << "iterCG"; + os << std::setw(10) << std::left << "flagCG"; + os << std::endl; + os.flags(osFlags); } template void ColemanLiAlgorithm::writeName( std::ostream& os ) const { - std::stringstream hist; - hist << std::endl << "Coleman-Li Affine-Scaling Trust-Region Method (Type B, Bound Constraints)" << std::endl; - os << hist.str(); + std::ios_base::fmtflags osFlags(os.flags()); + os << std::endl << "Coleman-Li Affine-Scaling Trust-Region Method (Type B, Bound Constraints)" << std::endl; + os.flags(osFlags); } template void ColemanLiAlgorithm::writeOutput( std::ostream& os, bool write_header ) const { - std::stringstream hist; - hist << std::scientific << std::setprecision(6); + std::ios_base::fmtflags osFlags(os.flags()); + os << std::scientific << std::setprecision(6); if ( state_->iter == 0 ) writeName(os); if ( write_header ) writeHeader(os); if ( state_->iter == 0 ) { - hist << " "; - hist << std::setw(6) << std::left << state_->iter; - hist << std::setw(15) << std::left << state_->value; - hist << std::setw(15) << std::left << state_->gnorm; - hist << std::setw(15) << std::left << "---"; - hist << std::setw(15) << std::left << state_->searchSize; - hist << std::setw(10) << std::left << state_->nfval; - hist << std::setw(10) << std::left << state_->ngrad; - hist << std::setw(10) << std::left << nhess_; - hist << std::setw(10) << std::left << state_->nproj; - hist << std::setw(10) << std::left << "---"; - hist << std::setw(10) << std::left << "---"; - hist << std::setw(10) << std::left << "---"; - hist << std::endl; + os << " "; + os << std::setw(6) << std::left << state_->iter; + os << std::setw(15) << std::left << state_->value; + os << std::setw(15) << std::left << state_->gnorm; + os << std::setw(15) << std::left << "---"; + os << std::setw(15) << std::left << state_->searchSize; + os << std::setw(10) << std::left << state_->nfval; + os << std::setw(10) << std::left << state_->ngrad; + os << std::setw(10) << std::left << nhess_; + os << std::setw(10) << std::left << state_->nproj; + os << std::setw(10) << std::left << "---"; + os << std::setw(10) << std::left << "---"; + os << std::setw(10) << std::left << "---"; + os << std::endl; } else { - hist << " "; - hist << std::setw(6) << std::left << state_->iter; - hist << std::setw(15) << std::left << state_->value; - hist << std::setw(15) << std::left << state_->gnorm; - hist << std::setw(15) << std::left << state_->snorm; - hist << std::setw(15) << std::left << state_->searchSize; - hist << std::setw(10) << std::left << state_->nfval; - hist << std::setw(10) << std::left << state_->ngrad; - hist << std::setw(10) << std::left << nhess_; - hist << std::setw(10) << std::left << state_->nproj; - hist << std::setw(10) << std::left << TRflag_; - hist << std::setw(10) << std::left << SPiter_; - hist << std::setw(10) << std::left << SPflag_; - hist << std::endl; + os << " "; + os << std::setw(6) << std::left << state_->iter; + os << std::setw(15) << std::left << state_->value; + os << std::setw(15) << std::left << state_->gnorm; + os << std::setw(15) << std::left << state_->snorm; + os << std::setw(15) << std::left << state_->searchSize; + os << std::setw(10) << std::left << state_->nfval; + os << std::setw(10) << std::left << state_->ngrad; + os << std::setw(10) << std::left << nhess_; + os << std::setw(10) << std::left << state_->nproj; + os << std::setw(10) << std::left << TRflag_; + os << std::setw(10) << std::left << SPiter_; + os << std::setw(10) << std::left << SPflag_; + os << std::endl; } - os << hist.str(); + os.flags(osFlags); } } // namespace TypeB diff --git a/packages/rol/src/algorithm/TypeB/ROL_TypeB_GradientAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeB/ROL_TypeB_GradientAlgorithm_Def.hpp index e9dba1fbcb01..1a46caa70f7a 100644 --- a/packages/rol/src/algorithm/TypeB/ROL_TypeB_GradientAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeB/ROL_TypeB_GradientAlgorithm_Def.hpp @@ -264,69 +264,69 @@ void GradientAlgorithm::run( Vector &x, template void GradientAlgorithm::writeHeader( std::ostream& os ) const { - std::stringstream hist; + std::ios_base::fmtflags osFlags(os.flags()); if (verbosity_ > 1) { - hist << std::string(109,'-') << std::endl; - hist << "Projected gradient descent"; - hist << " status output definitions" << std::endl << std::endl; - hist << " iter - Number of iterates (steps taken)" << std::endl; - hist << " value - Objective function value" << std::endl; - hist << " gnorm - Norm of the gradient" << std::endl; - hist << " snorm - Norm of the step (update to optimization vector)" << std::endl; - hist << " alpha - Line search step length" << std::endl; - hist << " #fval - Cumulative number of times the objective function was evaluated" << std::endl; - hist << " #grad - Cumulative number of times the gradient was computed" << std::endl; - hist << std::string(109,'-') << std::endl; + os << std::string(109,'-') << std::endl; + os << "Projected gradient descent"; + os << " status output definitions" << std::endl << std::endl; + os << " iter - Number of iterates (steps taken)" << std::endl; + os << " value - Objective function value" << std::endl; + os << " gnorm - Norm of the gradient" << std::endl; + os << " snorm - Norm of the step (update to optimization vector)" << std::endl; + os << " alpha - Line search step length" << std::endl; + os << " #fval - Cumulative number of times the objective function was evaluated" << std::endl; + os << " #grad - Cumulative number of times the gradient was computed" << std::endl; + os << std::string(109,'-') << std::endl; } - hist << " "; - hist << std::setw(6) << std::left << "iter"; - hist << std::setw(15) << std::left << "value"; - hist << std::setw(15) << std::left << "gnorm"; - hist << std::setw(15) << std::left << "snorm"; - hist << std::setw(15) << std::left << "alpha"; - hist << std::setw(10) << std::left << "#fval"; - hist << std::setw(10) << std::left << "#grad"; - hist << std::endl; - os << hist.str(); + os << " "; + os << std::setw(6) << std::left << "iter"; + os << std::setw(15) << std::left << "value"; + os << std::setw(15) << std::left << "gnorm"; + os << std::setw(15) << std::left << "snorm"; + os << std::setw(15) << std::left << "alpha"; + os << std::setw(10) << std::left << "#fval"; + os << std::setw(10) << std::left << "#grad"; + os << std::endl; + os.flags(osFlags); } template void GradientAlgorithm::writeName( std::ostream& os ) const { - std::stringstream hist; - hist << std::endl << "Projected Gradient Descent with Backtracking Line Search (Type B, Bound Constraints)" << std::endl; - os << hist.str(); + std::ios_base::fmtflags osFlags(os.flags()); + os << std::endl << "Projected Gradient Descent with Backtracking Line Search (Type B, Bound Constraints)" << std::endl; + os.flags(osFlags); } template void GradientAlgorithm::writeOutput( std::ostream& os, bool write_header ) const { - std::stringstream hist; - hist << std::scientific << std::setprecision(6); + std::ios_base::fmtflags osFlags(os.flags()); + os << std::scientific << std::setprecision(6); if ( state_->iter == 0 ) writeName(os); if ( write_header ) writeHeader(os); if ( state_->iter == 0 ) { - hist << " "; - hist << std::setw(6) << std::left << state_->iter; - hist << std::setw(15) << std::left << state_->value; - hist << std::setw(15) << std::left << state_->gnorm; - hist << std::setw(15) << std::left << "---"; - hist << std::setw(15) << std::left << "---"; - hist << std::setw(10) << std::left << state_->nfval; - hist << std::setw(10) << std::left << state_->ngrad; - hist << std::endl; + os << " "; + os << std::setw(6) << std::left << state_->iter; + os << std::setw(15) << std::left << state_->value; + os << std::setw(15) << std::left << state_->gnorm; + os << std::setw(15) << std::left << "---"; + os << std::setw(15) << std::left << "---"; + os << std::setw(10) << std::left << state_->nfval; + os << std::setw(10) << std::left << state_->ngrad; + os << std::endl; } else { - hist << " "; - hist << std::setw(6) << std::left << state_->iter; - hist << std::setw(15) << std::left << state_->value; - hist << std::setw(15) << std::left << state_->gnorm; - hist << std::setw(15) << std::left << state_->snorm; - hist << std::setw(15) << std::left << state_->searchSize; - hist << std::setw(10) << std::left << state_->nfval; - hist << std::setw(10) << std::left << state_->ngrad; - hist << std::endl; + os << " "; + os << std::setw(6) << std::left << state_->iter; + os << std::setw(15) << std::left << state_->value; + os << std::setw(15) << std::left << state_->gnorm; + os << std::setw(15) << std::left << state_->snorm; + os << std::setw(15) << std::left << state_->searchSize; + os << std::setw(10) << std::left << state_->nfval; + os << std::setw(10) << std::left << state_->ngrad; + os << std::endl; } - os << hist.str(); + os.flags(osFlags); } } // namespace TypeB diff --git a/packages/rol/src/algorithm/TypeB/ROL_TypeB_InteriorPointAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeB/ROL_TypeB_InteriorPointAlgorithm_Def.hpp index c2ed5f154cf0..218313a63a0a 100644 --- a/packages/rol/src/algorithm/TypeB/ROL_TypeB_InteriorPointAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeB/ROL_TypeB_InteriorPointAlgorithm_Def.hpp @@ -201,84 +201,84 @@ void InteriorPointAlgorithm::run( Vector &x, template void InteriorPointAlgorithm::writeHeader( std::ostream& os ) const { - std::stringstream hist; + std::ios_base::fmtflags osFlags(os.flags()); if (verbosity_ > 1) { - hist << std::string(109,'-') << std::endl; - hist << "Interior Point Solver"; - hist << " status output definitions" << std::endl << std::endl; - hist << " iter - Number of iterates (steps taken)" << std::endl; - hist << " fval - Objective function value" << std::endl; - hist << " gnorm - Norm of the gradient" << std::endl; - hist << " snorm - Norm of the step (update to optimization vector)" << std::endl; - hist << " penalty - Penalty parameter for bound constraints" << std::endl; - hist << " #fval - Cumulative number of times the objective function was evaluated" << std::endl; - hist << " #grad - Cumulative number of times the gradient was computed" << std::endl; - hist << " optTol - Subproblem optimality tolerance" << std::endl; - hist << " subiter - Number of subproblem iterations" << std::endl; - hist << std::string(109,'-') << std::endl; + os << std::string(109,'-') << std::endl; + os << "Interior Point Solver"; + os << " status output definitions" << std::endl << std::endl; + os << " iter - Number of iterates (steps taken)" << std::endl; + os << " fval - Objective function value" << std::endl; + os << " gnorm - Norm of the gradient" << std::endl; + os << " snorm - Norm of the step (update to optimization vector)" << std::endl; + os << " penalty - Penalty parameter for bound constraints" << std::endl; + os << " #fval - Cumulative number of times the objective function was evaluated" << std::endl; + os << " #grad - Cumulative number of times the gradient was computed" << std::endl; + os << " optTol - Subproblem optimality tolerance" << std::endl; + os << " subiter - Number of subproblem iterations" << std::endl; + os << std::string(109,'-') << std::endl; } - hist << " "; - hist << std::setw(6) << std::left << "iter"; - hist << std::setw(15) << std::left << "fval"; - hist << std::setw(15) << std::left << "gnorm"; - hist << std::setw(15) << std::left << "snorm"; - hist << std::setw(10) << std::left << "penalty"; - hist << std::setw(8) << std::left << "#fval"; - hist << std::setw(8) << std::left << "#grad"; - hist << std::setw(10) << std::left << "optTol"; - hist << std::setw(8) << std::left << "subIter"; - hist << std::endl; - os << hist.str(); + os << " "; + os << std::setw(6) << std::left << "iter"; + os << std::setw(15) << std::left << "fval"; + os << std::setw(15) << std::left << "gnorm"; + os << std::setw(15) << std::left << "snorm"; + os << std::setw(10) << std::left << "penalty"; + os << std::setw(8) << std::left << "#fval"; + os << std::setw(8) << std::left << "#grad"; + os << std::setw(10) << std::left << "optTol"; + os << std::setw(8) << std::left << "subIter"; + os << std::endl; + os.flags(osFlags); } template void InteriorPointAlgorithm::writeName( std::ostream& os ) const { - std::stringstream hist; - hist << std::endl << "Interior Point Solver (Type B, Bound Constraints)"; - hist << std::endl; - hist << "Subproblem Solver: " << stepname_ << std::endl; - os << hist.str(); + std::ios_base::fmtflags osFlags(os.flags()); + os << std::endl << "Interior Point Solver (Type B, Bound Constraints)"; + os << std::endl; + os << "Subproblem Solver: " << stepname_ << std::endl; + os.flags(osFlags); } template void InteriorPointAlgorithm::writeOutput( std::ostream& os, bool write_header ) const { - std::stringstream hist; - hist << std::scientific << std::setprecision(6); + std::ios_base::fmtflags osFlags(os.flags()); + os << std::scientific << std::setprecision(6); if ( state_->iter == 0 ) writeName(os); if ( write_header ) writeHeader(os); if ( state_->iter == 0 ) { - hist << " "; - hist << std::setw(6) << std::left << state_->iter; - hist << std::setw(15) << std::left << state_->value; - hist << std::setw(15) << std::left << state_->gnorm; - hist << std::setw(15) << std::left << "---"; - hist << std::scientific << std::setprecision(2); - hist << std::setw(10) << std::left << state_->searchSize; - hist << std::setw(8) << std::left << state_->nfval; - hist << std::setw(8) << std::left << state_->ngrad; - hist << std::setw(10) << std::left << "---"; - hist << std::setw(8) << std::left << "---"; - hist << std::endl; + os << " "; + os << std::setw(6) << std::left << state_->iter; + os << std::setw(15) << std::left << state_->value; + os << std::setw(15) << std::left << state_->gnorm; + os << std::setw(15) << std::left << "---"; + os << std::scientific << std::setprecision(2); + os << std::setw(10) << std::left << state_->searchSize; + os << std::setw(8) << std::left << state_->nfval; + os << std::setw(8) << std::left << state_->ngrad; + os << std::setw(10) << std::left << "---"; + os << std::setw(8) << std::left << "---"; + os << std::endl; } else { - hist << " "; - hist << std::setw(6) << std::left << state_->iter; - hist << std::setw(15) << std::left << state_->value; - hist << std::setw(15) << std::left << state_->gnorm; - hist << std::setw(15) << std::left << state_->snorm; - hist << std::scientific << std::setprecision(2); - hist << std::setw(10) << std::left << state_->searchSize; - hist << std::scientific << std::setprecision(6); - hist << std::setw(8) << std::left << state_->nfval; - hist << std::setw(8) << std::left << state_->ngrad; - hist << std::scientific << std::setprecision(2); - hist << std::setw(10) << std::left << gtol_; - hist << std::scientific << std::setprecision(6); - hist << std::setw(8) << std::left << subproblemIter_; - hist << std::endl; + os << " "; + os << std::setw(6) << std::left << state_->iter; + os << std::setw(15) << std::left << state_->value; + os << std::setw(15) << std::left << state_->gnorm; + os << std::setw(15) << std::left << state_->snorm; + os << std::scientific << std::setprecision(2); + os << std::setw(10) << std::left << state_->searchSize; + os << std::scientific << std::setprecision(6); + os << std::setw(8) << std::left << state_->nfval; + os << std::setw(8) << std::left << state_->ngrad; + os << std::scientific << std::setprecision(2); + os << std::setw(10) << std::left << gtol_; + os << std::scientific << std::setprecision(6); + os << std::setw(8) << std::left << subproblemIter_; + os << std::endl; } - os << hist.str(); + os.flags(osFlags); } } // namespace TypeB diff --git a/packages/rol/src/algorithm/TypeB/ROL_TypeB_KelleySachsAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeB/ROL_TypeB_KelleySachsAlgorithm_Def.hpp index 2839f687320d..470b0212c282 100644 --- a/packages/rol/src/algorithm/TypeB/ROL_TypeB_KelleySachsAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeB/ROL_TypeB_KelleySachsAlgorithm_Def.hpp @@ -486,93 +486,93 @@ void KelleySachsAlgorithm::applyFreePrecond(Vector &hv, template void KelleySachsAlgorithm::writeHeader( std::ostream& os ) const { - std::stringstream hist; + std::ios_base::fmtflags osFlags(os.flags()); if (verbosity_ > 1) { - hist << std::string(114,'-') << std::endl; - hist << " Kelley-Sachs trust-region method status output definitions" << std::endl << std::endl; - hist << " iter - Number of iterates (steps taken)" << std::endl; - hist << " value - Objective function value" << std::endl; - hist << " gnorm - Norm of the gradient" << std::endl; - hist << " snorm - Norm of the step (update to optimization vector)" << std::endl; - hist << " delta - Trust-Region radius" << std::endl; - hist << " #fval - Number of times the objective function was evaluated" << std::endl; - hist << " #grad - Number of times the gradient was computed" << std::endl; - hist << " #hess - Number of times the Hessian was applied" << std::endl; - hist << std::endl; - hist << " tr_flag - Trust-Region flag" << std::endl; + os << std::string(114,'-') << std::endl; + os << " Kelley-Sachs trust-region method status output definitions" << std::endl << std::endl; + os << " iter - Number of iterates (steps taken)" << std::endl; + os << " value - Objective function value" << std::endl; + os << " gnorm - Norm of the gradient" << std::endl; + os << " snorm - Norm of the step (update to optimization vector)" << std::endl; + os << " delta - Trust-Region radius" << std::endl; + os << " #fval - Number of times the objective function was evaluated" << std::endl; + os << " #grad - Number of times the gradient was computed" << std::endl; + os << " #hess - Number of times the Hessian was applied" << std::endl; + os << std::endl; + os << " tr_flag - Trust-Region flag" << std::endl; for( int flag = TRUtils::SUCCESS; flag != TRUtils::UNDEFINED; ++flag ) { - hist << " " << NumberToString(flag) << " - " + os << " " << NumberToString(flag) << " - " << TRUtils::ETRFlagToString(static_cast(flag)) << std::endl; } - hist << std::endl; - hist << " iterCG - Number of Truncated CG iterations" << std::endl << std::endl; - hist << " flagGC - Trust-Region Truncated CG flag" << std::endl; + os << std::endl; + os << " iterCG - Number of Truncated CG iterations" << std::endl << std::endl; + os << " flagGC - Trust-Region Truncated CG flag" << std::endl; for( int flag = CG_FLAG_SUCCESS; flag != CG_FLAG_UNDEFINED; ++flag ) { - hist << " " << NumberToString(flag) << " - " + os << " " << NumberToString(flag) << " - " << ECGFlagToString(static_cast(flag)) << std::endl; } - hist << std::string(114,'-') << std::endl; + os << std::string(114,'-') << std::endl; } - hist << " "; - hist << std::setw(6) << std::left << "iter"; - hist << std::setw(15) << std::left << "value"; - hist << std::setw(15) << std::left << "gnorm"; - hist << std::setw(15) << std::left << "snorm"; - hist << std::setw(15) << std::left << "delta"; - hist << std::setw(10) << std::left << "#fval"; - hist << std::setw(10) << std::left << "#grad"; - hist << std::setw(10) << std::left << "#hess"; - hist << std::setw(10) << std::left << "tr_flag"; - hist << std::setw(10) << std::left << "iterCG"; - hist << std::setw(10) << std::left << "flagCG"; - hist << std::endl; - os << hist.str(); + os << " "; + os << std::setw(6) << std::left << "iter"; + os << std::setw(15) << std::left << "value"; + os << std::setw(15) << std::left << "gnorm"; + os << std::setw(15) << std::left << "snorm"; + os << std::setw(15) << std::left << "delta"; + os << std::setw(10) << std::left << "#fval"; + os << std::setw(10) << std::left << "#grad"; + os << std::setw(10) << std::left << "#hess"; + os << std::setw(10) << std::left << "tr_flag"; + os << std::setw(10) << std::left << "iterCG"; + os << std::setw(10) << std::left << "flagCG"; + os << std::endl; + os.flags(osFlags); } template void KelleySachsAlgorithm::writeName( std::ostream& os ) const { - std::stringstream hist; - hist << std::endl << "Kelley-Sachs Trust-Region Method (Type B, Bound Constraints)" << std::endl; - os << hist.str(); + std::ios_base::fmtflags osFlags(os.flags()); + os << std::endl << "Kelley-Sachs Trust-Region Method (Type B, Bound Constraints)" << std::endl; + os.flags(osFlags); } template void KelleySachsAlgorithm::writeOutput( std::ostream& os, bool write_header ) const { - std::stringstream hist; - hist << std::scientific << std::setprecision(6); + std::ios_base::fmtflags osFlags(os.flags()); + os << std::scientific << std::setprecision(6); if ( state_->iter == 0 ) writeName(os); if ( write_header ) writeHeader(os); if ( state_->iter == 0 ) { - hist << " "; - hist << std::setw(6) << std::left << state_->iter; - hist << std::setw(15) << std::left << state_->value; - hist << std::setw(15) << std::left << state_->gnorm; - hist << std::setw(15) << std::left << "---"; - hist << std::setw(15) << std::left << state_->searchSize; - hist << std::setw(10) << std::left << state_->nfval; - hist << std::setw(10) << std::left << state_->ngrad; - hist << std::setw(10) << std::left << nhess_; - hist << std::setw(10) << std::left << "---"; - hist << std::setw(10) << std::left << "---"; - hist << std::setw(10) << std::left << "---"; - hist << std::endl; + os << " "; + os << std::setw(6) << std::left << state_->iter; + os << std::setw(15) << std::left << state_->value; + os << std::setw(15) << std::left << state_->gnorm; + os << std::setw(15) << std::left << "---"; + os << std::setw(15) << std::left << state_->searchSize; + os << std::setw(10) << std::left << state_->nfval; + os << std::setw(10) << std::left << state_->ngrad; + os << std::setw(10) << std::left << nhess_; + os << std::setw(10) << std::left << "---"; + os << std::setw(10) << std::left << "---"; + os << std::setw(10) << std::left << "---"; + os << std::endl; } else { - hist << " "; - hist << std::setw(6) << std::left << state_->iter; - hist << std::setw(15) << std::left << state_->value; - hist << std::setw(15) << std::left << state_->gnorm; - hist << std::setw(15) << std::left << state_->snorm; - hist << std::setw(15) << std::left << state_->searchSize; - hist << std::setw(10) << std::left << state_->nfval; - hist << std::setw(10) << std::left << state_->ngrad; - hist << std::setw(10) << std::left << nhess_; - hist << std::setw(10) << std::left << TRflag_; - hist << std::setw(10) << std::left << SPiter_; - hist << std::setw(10) << std::left << SPflag_; - hist << std::endl; + os << " "; + os << std::setw(6) << std::left << state_->iter; + os << std::setw(15) << std::left << state_->value; + os << std::setw(15) << std::left << state_->gnorm; + os << std::setw(15) << std::left << state_->snorm; + os << std::setw(15) << std::left << state_->searchSize; + os << std::setw(10) << std::left << state_->nfval; + os << std::setw(10) << std::left << state_->ngrad; + os << std::setw(10) << std::left << nhess_; + os << std::setw(10) << std::left << TRflag_; + os << std::setw(10) << std::left << SPiter_; + os << std::setw(10) << std::left << SPflag_; + os << std::endl; } - os << hist.str(); + os.flags(osFlags); } } // namespace TypeB diff --git a/packages/rol/src/algorithm/TypeB/ROL_TypeB_LSecantBAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeB/ROL_TypeB_LSecantBAlgorithm_Def.hpp index e0114b087e28..1b9037800551 100644 --- a/packages/rol/src/algorithm/TypeB/ROL_TypeB_LSecantBAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeB/ROL_TypeB_LSecantBAlgorithm_Def.hpp @@ -481,82 +481,82 @@ void LSecantBAlgorithm::applyFreePrecond(Vector &hv, template void LSecantBAlgorithm::writeHeader( std::ostream& os ) const { - std::stringstream hist; + std::ios_base::fmtflags osFlags(os.flags()); if (verbosity_ > 1) { - hist << std::string(114,'-') << std::endl; - hist << " L-Secant-B line search method status output definitions" << std::endl << std::endl; - hist << " iter - Number of iterates (steps taken)" << std::endl; - hist << " value - Objective function value" << std::endl; - hist << " gnorm - Norm of the gradient" << std::endl; - hist << " snorm - Norm of the step (update to optimization vector)" << std::endl; - hist << " LSpar - Line-Search parameter" << std::endl; - hist << " #fval - Number of times the objective function was evaluated" << std::endl; - hist << " #grad - Number of times the gradient was computed" << std::endl; - hist << " #proj - Number of times the projection was applied" << std::endl; - hist << " iterCG - Number of Truncated CG iterations" << std::endl << std::endl; - hist << " flagGC - Trust-Region Truncated CG flag" << std::endl; - hist << " 0 - Converged" << std::endl; - hist << " 1 - Iteration Limit Exceeded" << std::endl; - hist << " 2 - Bounds Exceeded" << std::endl; - hist << std::string(114,'-') << std::endl; + os << std::string(114,'-') << std::endl; + os << " L-Secant-B line search method status output definitions" << std::endl << std::endl; + os << " iter - Number of iterates (steps taken)" << std::endl; + os << " value - Objective function value" << std::endl; + os << " gnorm - Norm of the gradient" << std::endl; + os << " snorm - Norm of the step (update to optimization vector)" << std::endl; + os << " LSpar - Line-Search parameter" << std::endl; + os << " #fval - Number of times the objective function was evaluated" << std::endl; + os << " #grad - Number of times the gradient was computed" << std::endl; + os << " #proj - Number of times the projection was applied" << std::endl; + os << " iterCG - Number of Truncated CG iterations" << std::endl << std::endl; + os << " flagGC - Trust-Region Truncated CG flag" << std::endl; + os << " 0 - Converged" << std::endl; + os << " 1 - Iteration Limit Exceeded" << std::endl; + os << " 2 - Bounds Exceeded" << std::endl; + os << std::string(114,'-') << std::endl; } - hist << " "; - hist << std::setw(6) << std::left << "iter"; - hist << std::setw(15) << std::left << "value"; - hist << std::setw(15) << std::left << "gnorm"; - hist << std::setw(15) << std::left << "snorm"; - hist << std::setw(15) << std::left << "LSpar"; - hist << std::setw(10) << std::left << "#fval"; - hist << std::setw(10) << std::left << "#grad"; - hist << std::setw(10) << std::left << "#proj"; - hist << std::setw(10) << std::left << "iterCG"; - hist << std::setw(10) << std::left << "flagCG"; - hist << std::endl; - os << hist.str(); + os << " "; + os << std::setw(6) << std::left << "iter"; + os << std::setw(15) << std::left << "value"; + os << std::setw(15) << std::left << "gnorm"; + os << std::setw(15) << std::left << "snorm"; + os << std::setw(15) << std::left << "LSpar"; + os << std::setw(10) << std::left << "#fval"; + os << std::setw(10) << std::left << "#grad"; + os << std::setw(10) << std::left << "#proj"; + os << std::setw(10) << std::left << "iterCG"; + os << std::setw(10) << std::left << "flagCG"; + os << std::endl; + os.flags(osFlags); } template void LSecantBAlgorithm::writeName( std::ostream& os ) const { - std::stringstream hist; - hist << std::endl << "L-Secant-B Line-Search Method (Type B, Bound Constraints)" << std::endl; - os << hist.str(); + std::ios_base::fmtflags osFlags(os.flags()); + os << std::endl << "L-Secant-B Line-Search Method (Type B, Bound Constraints)" << std::endl; + os.flags(osFlags); } template void LSecantBAlgorithm::writeOutput( std::ostream& os, bool write_header ) const { - std::stringstream hist; - hist << std::scientific << std::setprecision(6); + std::ios_base::fmtflags osFlags(os.flags()); + os << std::scientific << std::setprecision(6); if ( state_->iter == 0 ) writeName(os); if ( write_header ) writeHeader(os); if ( state_->iter == 0 ) { - hist << " "; - hist << std::setw(6) << std::left << state_->iter; - hist << std::setw(15) << std::left << state_->value; - hist << std::setw(15) << std::left << state_->gnorm; - hist << std::setw(15) << std::left << "---"; - hist << std::setw(15) << std::left << state_->searchSize; - hist << std::setw(10) << std::left << state_->nfval; - hist << std::setw(10) << std::left << state_->ngrad; - hist << std::setw(10) << std::left << state_->nproj; - hist << std::setw(10) << std::left << "---"; - hist << std::setw(10) << std::left << "---"; - hist << std::endl; + os << " "; + os << std::setw(6) << std::left << state_->iter; + os << std::setw(15) << std::left << state_->value; + os << std::setw(15) << std::left << state_->gnorm; + os << std::setw(15) << std::left << "---"; + os << std::setw(15) << std::left << state_->searchSize; + os << std::setw(10) << std::left << state_->nfval; + os << std::setw(10) << std::left << state_->ngrad; + os << std::setw(10) << std::left << state_->nproj; + os << std::setw(10) << std::left << "---"; + os << std::setw(10) << std::left << "---"; + os << std::endl; } else { - hist << " "; - hist << std::setw(6) << std::left << state_->iter; - hist << std::setw(15) << std::left << state_->value; - hist << std::setw(15) << std::left << state_->gnorm; - hist << std::setw(15) << std::left << state_->snorm; - hist << std::setw(15) << std::left << state_->searchSize; - hist << std::setw(10) << std::left << state_->nfval; - hist << std::setw(10) << std::left << state_->ngrad; - hist << std::setw(10) << std::left << state_->nproj; - hist << std::setw(10) << std::left << SPiter_; - hist << std::setw(10) << std::left << SPflag_; - hist << std::endl; + os << " "; + os << std::setw(6) << std::left << state_->iter; + os << std::setw(15) << std::left << state_->value; + os << std::setw(15) << std::left << state_->gnorm; + os << std::setw(15) << std::left << state_->snorm; + os << std::setw(15) << std::left << state_->searchSize; + os << std::setw(10) << std::left << state_->nfval; + os << std::setw(10) << std::left << state_->ngrad; + os << std::setw(10) << std::left << state_->nproj; + os << std::setw(10) << std::left << SPiter_; + os << std::setw(10) << std::left << SPflag_; + os << std::endl; } - os << hist.str(); + os.flags(osFlags); } } // namespace TypeB diff --git a/packages/rol/src/algorithm/TypeB/ROL_TypeB_LinMoreAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeB/ROL_TypeB_LinMoreAlgorithm_Def.hpp index db5123097ce3..6a148bfe8af2 100644 --- a/packages/rol/src/algorithm/TypeB/ROL_TypeB_LinMoreAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeB/ROL_TypeB_LinMoreAlgorithm_Def.hpp @@ -644,105 +644,105 @@ void LinMoreAlgorithm::applyFreePrecond(Vector &hv, template void LinMoreAlgorithm::writeHeader( std::ostream& os ) const { - std::stringstream hist; + std::ios_base::fmtflags osFlags(os.flags()); if (verbosity_ > 1) { - hist << std::string(114,'-') << std::endl; - hist << " Lin-More trust-region method status output definitions" << std::endl << std::endl; - hist << " iter - Number of iterates (steps taken)" << std::endl; - hist << " value - Objective function value" << std::endl; - hist << " gnorm - Norm of the gradient" << std::endl; - hist << " snorm - Norm of the step (update to optimization vector)" << std::endl; - hist << " delta - Trust-Region radius" << std::endl; - hist << " #fval - Number of times the objective function was evaluated" << std::endl; - hist << " #grad - Number of times the gradient was computed" << std::endl; - hist << " #hess - Number of times the Hessian was applied" << std::endl; - hist << " #proj - Number of times the projection was applied" << std::endl; - hist << std::endl; - hist << " tr_flag - Trust-Region flag" << std::endl; + os << std::string(114,'-') << std::endl; + os << " Lin-More trust-region method status output definitions" << std::endl << std::endl; + os << " iter - Number of iterates (steps taken)" << std::endl; + os << " value - Objective function value" << std::endl; + os << " gnorm - Norm of the gradient" << std::endl; + os << " snorm - Norm of the step (update to optimization vector)" << std::endl; + os << " delta - Trust-Region radius" << std::endl; + os << " #fval - Number of times the objective function was evaluated" << std::endl; + os << " #grad - Number of times the gradient was computed" << std::endl; + os << " #hess - Number of times the Hessian was applied" << std::endl; + os << " #proj - Number of times the projection was applied" << std::endl; + os << std::endl; + os << " tr_flag - Trust-Region flag" << std::endl; for( int flag = TRUtils::SUCCESS; flag != TRUtils::UNDEFINED; ++flag ) { - hist << " " << NumberToString(flag) << " - " + os << " " << NumberToString(flag) << " - " << TRUtils::ETRFlagToString(static_cast(flag)) << std::endl; } - hist << std::endl; + os << std::endl; if (minit_ > 0) { - hist << " iterCG - Number of Truncated CG iterations" << std::endl << std::endl; - hist << " flagGC - Trust-Region Truncated CG flag" << std::endl; + os << " iterCG - Number of Truncated CG iterations" << std::endl << std::endl; + os << " flagGC - Trust-Region Truncated CG flag" << std::endl; for( int flag = CG_FLAG_SUCCESS; flag != CG_FLAG_UNDEFINED; ++flag ) { - hist << " " << NumberToString(flag) << " - " + os << " " << NumberToString(flag) << " - " << ECGFlagToString(static_cast(flag)) << std::endl; } } - hist << std::string(114,'-') << std::endl; + os << std::string(114,'-') << std::endl; } - hist << " "; - hist << std::setw(6) << std::left << "iter"; - hist << std::setw(15) << std::left << "value"; - hist << std::setw(15) << std::left << "gnorm"; - hist << std::setw(15) << std::left << "snorm"; - hist << std::setw(15) << std::left << "delta"; - hist << std::setw(10) << std::left << "#fval"; - hist << std::setw(10) << std::left << "#grad"; - hist << std::setw(10) << std::left << "#hess"; - hist << std::setw(10) << std::left << "#proj"; - hist << std::setw(10) << std::left << "tr_flag"; + os << " "; + os << std::setw(6) << std::left << "iter"; + os << std::setw(15) << std::left << "value"; + os << std::setw(15) << std::left << "gnorm"; + os << std::setw(15) << std::left << "snorm"; + os << std::setw(15) << std::left << "delta"; + os << std::setw(10) << std::left << "#fval"; + os << std::setw(10) << std::left << "#grad"; + os << std::setw(10) << std::left << "#hess"; + os << std::setw(10) << std::left << "#proj"; + os << std::setw(10) << std::left << "tr_flag"; if (minit_ > 0) { - hist << std::setw(10) << std::left << "iterCG"; - hist << std::setw(10) << std::left << "flagCG"; + os << std::setw(10) << std::left << "iterCG"; + os << std::setw(10) << std::left << "flagCG"; } - hist << std::endl; - os << hist.str(); + os << std::endl; + os.flags(osFlags); } template void LinMoreAlgorithm::writeName( std::ostream& os ) const { - std::stringstream hist; - hist << std::endl << "Lin-More Trust-Region Method (Type B, Bound Constraints)" << std::endl; - os << hist.str(); + std::ios_base::fmtflags osFlags(os.flags()); + os << std::endl << "Lin-More Trust-Region Method (Type B, Bound Constraints)" << std::endl; + os.flags(osFlags); } template void LinMoreAlgorithm::writeOutput( std::ostream& os, bool write_header ) const { - std::stringstream hist; - hist << std::scientific << std::setprecision(6); + std::ios_base::fmtflags osFlags(os.flags()); + os << std::scientific << std::setprecision(6); if ( state_->iter == 0 ) writeName(os); if ( write_header ) writeHeader(os); if ( state_->iter == 0 ) { - hist << " "; - hist << std::setw(6) << std::left << state_->iter; - hist << std::setw(15) << std::left << state_->value; - hist << std::setw(15) << std::left << state_->gnorm; - hist << std::setw(15) << std::left << "---"; - hist << std::setw(15) << std::left << state_->searchSize; - hist << std::setw(10) << std::left << state_->nfval; - hist << std::setw(10) << std::left << state_->ngrad; - hist << std::setw(10) << std::left << nhess_; - hist << std::setw(10) << std::left << state_->nproj; - hist << std::setw(10) << std::left << "---"; + os << " "; + os << std::setw(6) << std::left << state_->iter; + os << std::setw(15) << std::left << state_->value; + os << std::setw(15) << std::left << state_->gnorm; + os << std::setw(15) << std::left << "---"; + os << std::setw(15) << std::left << state_->searchSize; + os << std::setw(10) << std::left << state_->nfval; + os << std::setw(10) << std::left << state_->ngrad; + os << std::setw(10) << std::left << nhess_; + os << std::setw(10) << std::left << state_->nproj; + os << std::setw(10) << std::left << "---"; if (minit_ > 0) { - hist << std::setw(10) << std::left << "---"; - hist << std::setw(10) << std::left << "---"; + os << std::setw(10) << std::left << "---"; + os << std::setw(10) << std::left << "---"; } - hist << std::endl; + os << std::endl; } else { - hist << " "; - hist << std::setw(6) << std::left << state_->iter; - hist << std::setw(15) << std::left << state_->value; - hist << std::setw(15) << std::left << state_->gnorm; - hist << std::setw(15) << std::left << state_->snorm; - hist << std::setw(15) << std::left << state_->searchSize; - hist << std::setw(10) << std::left << state_->nfval; - hist << std::setw(10) << std::left << state_->ngrad; - hist << std::setw(10) << std::left << nhess_; - hist << std::setw(10) << std::left << state_->nproj; - hist << std::setw(10) << std::left << TRflag_; + os << " "; + os << std::setw(6) << std::left << state_->iter; + os << std::setw(15) << std::left << state_->value; + os << std::setw(15) << std::left << state_->gnorm; + os << std::setw(15) << std::left << state_->snorm; + os << std::setw(15) << std::left << state_->searchSize; + os << std::setw(10) << std::left << state_->nfval; + os << std::setw(10) << std::left << state_->ngrad; + os << std::setw(10) << std::left << nhess_; + os << std::setw(10) << std::left << state_->nproj; + os << std::setw(10) << std::left << TRflag_; if (minit_ > 0) { - hist << std::setw(10) << std::left << SPiter_; - hist << std::setw(10) << std::left << SPflag_; + os << std::setw(10) << std::left << SPiter_; + os << std::setw(10) << std::left << SPflag_; } - hist << std::endl; + os << std::endl; } - os << hist.str(); + os.flags(osFlags); } } // namespace TypeB diff --git a/packages/rol/src/algorithm/TypeB/ROL_TypeB_MoreauYosidaAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeB/ROL_TypeB_MoreauYosidaAlgorithm_Def.hpp index 8f7837614389..1849b51411be 100644 --- a/packages/rol/src/algorithm/TypeB/ROL_TypeB_MoreauYosidaAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeB/ROL_TypeB_MoreauYosidaAlgorithm_Def.hpp @@ -198,82 +198,82 @@ void MoreauYosidaAlgorithm::run( Vector &x, template void MoreauYosidaAlgorithm::writeHeader( std::ostream& os ) const { - std::stringstream hist; + std::ios_base::fmtflags osFlags(os.flags()); if (verbosity_ > 1) { - hist << std::string(109,'-') << std::endl; - hist << "Moreau-Yosida Penalty Solver"; - hist << " status output definitions" << std::endl << std::endl; - hist << " iter - Number of iterates (steps taken)" << std::endl; - hist << " fval - Objective function value" << std::endl; - hist << " gnorm - Norm of the gradient" << std::endl; - hist << " ifeas - Infeasibility metric" << std::endl; - hist << " snorm - Norm of the step (update to optimization vector)" << std::endl; - hist << " penalty - Penalty parameter for bound constraints" << std::endl; - hist << " #fval - Cumulative number of times the objective function was evaluated" << std::endl; - hist << " #grad - Cumulative number of times the gradient was computed" << std::endl; - hist << " subiter - Number of subproblem iterations" << std::endl; - hist << std::string(109,'-') << std::endl; + os << std::string(109,'-') << std::endl; + os << "Moreau-Yosida Penalty Solver"; + os << " status output definitions" << std::endl << std::endl; + os << " iter - Number of iterates (steps taken)" << std::endl; + os << " fval - Objective function value" << std::endl; + os << " gnorm - Norm of the gradient" << std::endl; + os << " ifeas - Infeasibility metric" << std::endl; + os << " snorm - Norm of the step (update to optimization vector)" << std::endl; + os << " penalty - Penalty parameter for bound constraints" << std::endl; + os << " #fval - Cumulative number of times the objective function was evaluated" << std::endl; + os << " #grad - Cumulative number of times the gradient was computed" << std::endl; + os << " subiter - Number of subproblem iterations" << std::endl; + os << std::string(109,'-') << std::endl; } - hist << " "; - hist << std::setw(6) << std::left << "iter"; - hist << std::setw(15) << std::left << "fval"; - hist << std::setw(15) << std::left << "gnorm"; - hist << std::setw(15) << std::left << "ifeas"; - hist << std::setw(15) << std::left << "snorm"; - hist << std::setw(10) << std::left << "penalty"; - hist << std::setw(8) << std::left << "#fval"; - hist << std::setw(8) << std::left << "#grad"; - hist << std::setw(8) << std::left << "subIter"; - hist << std::endl; - os << hist.str(); + os << " "; + os << std::setw(6) << std::left << "iter"; + os << std::setw(15) << std::left << "fval"; + os << std::setw(15) << std::left << "gnorm"; + os << std::setw(15) << std::left << "ifeas"; + os << std::setw(15) << std::left << "snorm"; + os << std::setw(10) << std::left << "penalty"; + os << std::setw(8) << std::left << "#fval"; + os << std::setw(8) << std::left << "#grad"; + os << std::setw(8) << std::left << "subIter"; + os << std::endl; + os.flags(osFlags); } template void MoreauYosidaAlgorithm::writeName( std::ostream& os ) const { - std::stringstream hist; - hist << std::endl << " Moreau-Yosida Penalty Solver"; - hist << std::endl; - os << hist.str(); + std::ios_base::fmtflags osFlags(os.flags()); + os << std::endl << " Moreau-Yosida Penalty Solver"; + os << std::endl; + os.flags(osFlags); } template void MoreauYosidaAlgorithm::writeOutput( std::ostream& os, bool write_header ) const { - std::stringstream hist; - hist << std::scientific << std::setprecision(6); + std::ios_base::fmtflags osFlags(os.flags()); + os << std::scientific << std::setprecision(6); if ( state_->iter == 0 ) writeName(os); if ( write_header ) writeHeader(os); if ( state_->iter == 0 ) { - hist << " "; - hist << std::setw(6) << std::left << state_->iter; - hist << std::setw(15) << std::left << state_->value; - hist << std::setw(15) << std::left << gnorm_; - hist << std::setw(15) << std::left << compViolation_; - hist << std::setw(15) << std::left << "---"; - hist << std::scientific << std::setprecision(2); - hist << std::setw(10) << std::left << state_->searchSize; - hist << std::scientific << std::setprecision(6); - hist << std::setw(8) << std::left << state_->nfval; - hist << std::setw(8) << std::left << state_->ngrad; - hist << std::setw(8) << std::left << "---"; - hist << std::endl; + os << " "; + os << std::setw(6) << std::left << state_->iter; + os << std::setw(15) << std::left << state_->value; + os << std::setw(15) << std::left << gnorm_; + os << std::setw(15) << std::left << compViolation_; + os << std::setw(15) << std::left << "---"; + os << std::scientific << std::setprecision(2); + os << std::setw(10) << std::left << state_->searchSize; + os << std::scientific << std::setprecision(6); + os << std::setw(8) << std::left << state_->nfval; + os << std::setw(8) << std::left << state_->ngrad; + os << std::setw(8) << std::left << "---"; + os << std::endl; } else { - hist << " "; - hist << std::setw(6) << std::left << state_->iter; - hist << std::setw(15) << std::left << state_->value; - hist << std::setw(15) << std::left << gnorm_; - hist << std::setw(15) << std::left << compViolation_; - hist << std::setw(15) << std::left << state_->snorm; - hist << std::scientific << std::setprecision(2); - hist << std::setw(10) << std::left << state_->searchSize; - hist << std::scientific << std::setprecision(6); - hist << std::setw(8) << std::left << state_->nfval; - hist << std::setw(8) << std::left << state_->ngrad; - hist << std::setw(8) << std::left << subproblemIter_; - hist << std::endl; + os << " "; + os << std::setw(6) << std::left << state_->iter; + os << std::setw(15) << std::left << state_->value; + os << std::setw(15) << std::left << gnorm_; + os << std::setw(15) << std::left << compViolation_; + os << std::setw(15) << std::left << state_->snorm; + os << std::scientific << std::setprecision(2); + os << std::setw(10) << std::left << state_->searchSize; + os << std::scientific << std::setprecision(6); + os << std::setw(8) << std::left << state_->nfval; + os << std::setw(8) << std::left << state_->ngrad; + os << std::setw(8) << std::left << subproblemIter_; + os << std::endl; } - os << hist.str(); + os.flags(osFlags); } } // namespace TypeB diff --git a/packages/rol/src/algorithm/TypeB/ROL_TypeB_NewtonKrylovAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeB/ROL_TypeB_NewtonKrylovAlgorithm_Def.hpp index fbe80f8aa03b..98cce7ef1932 100644 --- a/packages/rol/src/algorithm/TypeB/ROL_TypeB_NewtonKrylovAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeB/ROL_TypeB_NewtonKrylovAlgorithm_Def.hpp @@ -268,96 +268,96 @@ void NewtonKrylovAlgorithm::run( Vector &x, template void NewtonKrylovAlgorithm::writeHeader( std::ostream& os ) const { - std::stringstream hist; + std::ios_base::fmtflags osFlags(os.flags()); if (verbosity_ > 1) { - hist << std::string(114,'-') << std::endl; + os << std::string(114,'-') << std::endl; if (!useSecantHessVec_) { - hist << "Line-Search Projected Newton"; + os << "Line-Search Projected Newton"; } else { - hist << "Line-Search Projected Quasi-Newton with " << secantName_ << " Hessian approximation"; + os << "Line-Search Projected Quasi-Newton with " << secantName_ << " Hessian approximation"; } - hist << " status output definitions" << std::endl << std::endl; - hist << " iter - Number of iterates (steps taken)" << std::endl; - hist << " value - Objective function value" << std::endl; - hist << " gnorm - Norm of the gradient" << std::endl; - hist << " snorm - Norm of the step (update to optimization vector)" << std::endl; - hist << " alpha - Line search step length" << std::endl; - hist << " #fval - Cumulative number of times the objective function was evaluated" << std::endl; - hist << " #grad - Cumulative number of times the gradient was computed" << std::endl; - hist << " ls_#fval - Number of the times the objective function was evaluated during the line search" << std::endl; - hist << " iterCG - Number of Krylov iterations" << std::endl << std::endl; - hist << " flagGC - Krylov flag" << std::endl; + os << " status output definitions" << std::endl << std::endl; + os << " iter - Number of iterates (steps taken)" << std::endl; + os << " value - Objective function value" << std::endl; + os << " gnorm - Norm of the gradient" << std::endl; + os << " snorm - Norm of the step (update to optimization vector)" << std::endl; + os << " alpha - Line search step length" << std::endl; + os << " #fval - Cumulative number of times the objective function was evaluated" << std::endl; + os << " #grad - Cumulative number of times the gradient was computed" << std::endl; + os << " ls_#fval - Number of the times the objective function was evaluated during the line search" << std::endl; + os << " iterCG - Number of Krylov iterations" << std::endl << std::endl; + os << " flagGC - Krylov flag" << std::endl; for( int flag = CG_FLAG_SUCCESS; flag != CG_FLAG_UNDEFINED; ++flag ) { - hist << " " << NumberToString(flag) << " - " + os << " " << NumberToString(flag) << " - " << ECGFlagToString(static_cast(flag)) << std::endl; } - hist << std::string(114,'-') << std::endl; + os << std::string(114,'-') << std::endl; } - hist << " "; - hist << std::setw(6) << std::left << "iter"; - hist << std::setw(15) << std::left << "value"; - hist << std::setw(15) << std::left << "gnorm"; - hist << std::setw(15) << std::left << "snorm"; - hist << std::setw(15) << std::left << "alpha"; - hist << std::setw(10) << std::left << "#fval"; - hist << std::setw(10) << std::left << "#grad"; - hist << std::setw(10) << std::left << "#ls_fval"; - hist << std::setw(10) << std::left << "iterCG"; - hist << std::setw(10) << std::left << "flagCG"; - hist << std::endl; - os << hist.str(); + os << " "; + os << std::setw(6) << std::left << "iter"; + os << std::setw(15) << std::left << "value"; + os << std::setw(15) << std::left << "gnorm"; + os << std::setw(15) << std::left << "snorm"; + os << std::setw(15) << std::left << "alpha"; + os << std::setw(10) << std::left << "#fval"; + os << std::setw(10) << std::left << "#grad"; + os << std::setw(10) << std::left << "#ls_fval"; + os << std::setw(10) << std::left << "iterCG"; + os << std::setw(10) << std::left << "flagCG"; + os << std::endl; + os.flags(osFlags); } template void NewtonKrylovAlgorithm::writeName( std::ostream& os ) const { - std::stringstream hist; + std::ios_base::fmtflags osFlags(os.flags()); if (!useSecantHessVec_) { - hist << std::endl << "Line-Search Projected Newton (Type B, Bound Constraints)" << std::endl; + os << std::endl << "Line-Search Projected Newton (Type B, Bound Constraints)" << std::endl; } else { - hist << std::endl << "Line-Search Projected Quasi-Newton with " + os << std::endl << "Line-Search Projected Quasi-Newton with " << secantName_ << " Hessian approximation" << std::endl; } - os << hist.str(); + os.flags(osFlags); } template void NewtonKrylovAlgorithm::writeOutput( std::ostream& os, bool write_header ) const { - std::stringstream hist; - hist << std::scientific << std::setprecision(6); + std::ios_base::fmtflags osFlags(os.flags()); + os << std::scientific << std::setprecision(6); if ( state_->iter == 0 ) writeName(os); if ( write_header ) writeHeader(os); if ( state_->iter == 0 ) { - hist << " "; - hist << std::setw(6) << std::left << state_->iter; - hist << std::setw(15) << std::left << state_->value; - hist << std::setw(15) << std::left << state_->gnorm; - hist << std::setw(15) << std::left << "---"; - hist << std::setw(15) << std::left << "---"; - hist << std::setw(10) << std::left << state_->nfval; - hist << std::setw(10) << std::left << state_->ngrad; - hist << std::setw(10) << std::left << "---"; - hist << std::setw(10) << std::left << "---"; - hist << std::setw(10) << std::left << "---"; - hist << std::endl; + os << " "; + os << std::setw(6) << std::left << state_->iter; + os << std::setw(15) << std::left << state_->value; + os << std::setw(15) << std::left << state_->gnorm; + os << std::setw(15) << std::left << "---"; + os << std::setw(15) << std::left << "---"; + os << std::setw(10) << std::left << state_->nfval; + os << std::setw(10) << std::left << state_->ngrad; + os << std::setw(10) << std::left << "---"; + os << std::setw(10) << std::left << "---"; + os << std::setw(10) << std::left << "---"; + os << std::endl; } else { - hist << " "; - hist << std::setw(6) << std::left << state_->iter; - hist << std::setw(15) << std::left << state_->value; - hist << std::setw(15) << std::left << state_->gnorm; - hist << std::setw(15) << std::left << state_->snorm; - hist << std::setw(15) << std::left << state_->searchSize; - hist << std::setw(10) << std::left << state_->nfval; - hist << std::setw(10) << std::left << state_->ngrad; - hist << std::setw(10) << std::left << ls_nfval_; - hist << std::setw(10) << std::left << iterKrylov_; - hist << std::setw(10) << std::left << flagKrylov_; - hist << std::endl; + os << " "; + os << std::setw(6) << std::left << state_->iter; + os << std::setw(15) << std::left << state_->value; + os << std::setw(15) << std::left << state_->gnorm; + os << std::setw(15) << std::left << state_->snorm; + os << std::setw(15) << std::left << state_->searchSize; + os << std::setw(10) << std::left << state_->nfval; + os << std::setw(10) << std::left << state_->ngrad; + os << std::setw(10) << std::left << ls_nfval_; + os << std::setw(10) << std::left << iterKrylov_; + os << std::setw(10) << std::left << flagKrylov_; + os << std::endl; } - os << hist.str(); + os.flags(osFlags); } } // namespace TypeB diff --git a/packages/rol/src/algorithm/TypeB/ROL_TypeB_PrimalDualActiveSetAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeB/ROL_TypeB_PrimalDualActiveSetAlgorithm_Def.hpp index dd07aab8a9c2..5733f542df6a 100644 --- a/packages/rol/src/algorithm/TypeB/ROL_TypeB_PrimalDualActiveSetAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeB/ROL_TypeB_PrimalDualActiveSetAlgorithm_Def.hpp @@ -302,126 +302,126 @@ void PrimalDualActiveSetAlgorithm::run( Vector &x, template void PrimalDualActiveSetAlgorithm::writeHeader( std::ostream& os ) const { - std::stringstream hist; + std::ios_base::fmtflags osFlags(os.flags()); if (verbosity_ > 1) { - hist << std::string(114,'-') << std::endl; + os << std::string(114,'-') << std::endl; if (!useSecantHessVec_) { - hist << "Primal Dual Active Set Newton's Method"; + os << "Primal Dual Active Set Newton's Method"; } else { - hist << "Primal Dual Active Set Quasi-Newton Method with " << secantName_ << " Hessian approximation"; + os << "Primal Dual Active Set Quasi-Newton Method with " << secantName_ << " Hessian approximation"; } - hist << " status output definitions" << std::endl << std::endl; - hist << " iter - Number of iterates (steps taken)" << std::endl; - hist << " value - Objective function value" << std::endl; - hist << " gnorm - Norm of the gradient" << std::endl; - hist << " snorm - Norm of the step (update to optimization vector)" << std::endl; - hist << " #fval - Cumulative number of times the objective function was evaluated" << std::endl; - hist << " #grad - Cumulative number of times the gradient was computed" << std::endl; + os << " status output definitions" << std::endl << std::endl; + os << " iter - Number of iterates (steps taken)" << std::endl; + os << " value - Objective function value" << std::endl; + os << " gnorm - Norm of the gradient" << std::endl; + os << " snorm - Norm of the step (update to optimization vector)" << std::endl; + os << " #fval - Cumulative number of times the objective function was evaluated" << std::endl; + os << " #grad - Cumulative number of times the gradient was computed" << std::endl; if (maxit_ > 1) { - hist << " iterPDAS - Number of Primal Dual Active Set iterations" << std::endl << std::endl; - hist << " flagPDAS - Primal Dual Active Set flag" << std::endl; - hist << " iterK - Number of Krylov iterations" << std::endl << std::endl; + os << " iterPDAS - Number of Primal Dual Active Set iterations" << std::endl << std::endl; + os << " flagPDAS - Primal Dual Active Set flag" << std::endl; + os << " iterK - Number of Krylov iterations" << std::endl << std::endl; } else { - hist << " iterK - Number of Krylov iterations" << std::endl << std::endl; - hist << " flagK - Krylov flag" << std::endl; + os << " iterK - Number of Krylov iterations" << std::endl << std::endl; + os << " flagK - Krylov flag" << std::endl; for( int flag = CG_FLAG_SUCCESS; flag != CG_FLAG_UNDEFINED; ++flag ) { - hist << " " << NumberToString(flag) << " - " + os << " " << NumberToString(flag) << " - " << ECGFlagToString(static_cast(flag)) << std::endl; } } - hist << " feasible - Is iterate feasible?" << std::endl; - hist << std::string(114,'-') << std::endl; + os << " feasible - Is iterate feasible?" << std::endl; + os << std::string(114,'-') << std::endl; } - hist << " "; - hist << std::setw(6) << std::left << "iter"; - hist << std::setw(15) << std::left << "value"; - hist << std::setw(15) << std::left << "gnorm"; - hist << std::setw(15) << std::left << "snorm"; - hist << std::setw(10) << std::left << "#fval"; - hist << std::setw(10) << std::left << "#grad"; + os << " "; + os << std::setw(6) << std::left << "iter"; + os << std::setw(15) << std::left << "value"; + os << std::setw(15) << std::left << "gnorm"; + os << std::setw(15) << std::left << "snorm"; + os << std::setw(10) << std::left << "#fval"; + os << std::setw(10) << std::left << "#grad"; if (maxit_ > 1) { - hist << std::setw(10) << std::left << "iterPDAS"; - hist << std::setw(10) << std::left << "flagPDAS"; - hist << std::setw(10) << std::left << "iterK"; + os << std::setw(10) << std::left << "iterPDAS"; + os << std::setw(10) << std::left << "flagPDAS"; + os << std::setw(10) << std::left << "iterK"; } else { - hist << std::setw(10) << std::left << "iterK"; - hist << std::setw(10) << std::left << "flagK"; + os << std::setw(10) << std::left << "iterK"; + os << std::setw(10) << std::left << "flagK"; } - hist << std::setw(10) << std::left << "feasible"; - hist << std::endl; - os << hist.str(); + os << std::setw(10) << std::left << "feasible"; + os << std::endl; + os.flags(osFlags); } template void PrimalDualActiveSetAlgorithm::writeName( std::ostream& os ) const { - std::stringstream hist; + std::ios_base::fmtflags osFlags(os.flags()); if (!useSecantHessVec_) { - hist << std::endl << "Primal Dual Active Set Newton's Method (Type B, Bound Constraints)" << std::endl; + os << std::endl << "Primal Dual Active Set Newton's Method (Type B, Bound Constraints)" << std::endl; } else { - hist << std::endl << "Primal Dual Active Set Quasi-Newton Method with " + os << std::endl << "Primal Dual Active Set Quasi-Newton Method with " << secantName_ << " Hessian approximation" << std::endl; } - os << hist.str(); + os.flags(osFlags); } template void PrimalDualActiveSetAlgorithm::writeOutput( std::ostream& os, bool write_header ) const { - std::stringstream hist; - hist << std::scientific << std::setprecision(6); + std::ios_base::fmtflags osFlags(os.flags()); + os << std::scientific << std::setprecision(6); if ( state_->iter == 0 ) writeName(os); if ( write_header ) writeHeader(os); if ( state_->iter == 0 ) { - hist << " "; - hist << std::setw(6) << std::left << state_->iter; - hist << std::setw(15) << std::left << state_->value; - hist << std::setw(15) << std::left << state_->gnorm; - hist << std::setw(15) << std::left << "---"; - hist << std::setw(10) << std::left << state_->nfval; - hist << std::setw(10) << std::left << state_->ngrad; - hist << std::setw(10) << std::left << "---"; - hist << std::setw(10) << std::left << "---"; + os << " "; + os << std::setw(6) << std::left << state_->iter; + os << std::setw(15) << std::left << state_->value; + os << std::setw(15) << std::left << state_->gnorm; + os << std::setw(15) << std::left << "---"; + os << std::setw(10) << std::left << state_->nfval; + os << std::setw(10) << std::left << state_->ngrad; + os << std::setw(10) << std::left << "---"; + os << std::setw(10) << std::left << "---"; if (maxit_ > 1) { - hist << std::setw(10) << std::left << "---"; + os << std::setw(10) << std::left << "---"; } if ( feasible_ ) { - hist << std::setw(10) << std::left << "YES"; + os << std::setw(10) << std::left << "YES"; } else { - hist << std::setw(10) << std::left << "NO"; + os << std::setw(10) << std::left << "NO"; } - hist << std::endl; + os << std::endl; } else { - hist << " "; - hist << std::setw(6) << std::left << state_->iter; - hist << std::setw(15) << std::left << state_->value; - hist << std::setw(15) << std::left << state_->gnorm; - hist << std::setw(15) << std::left << state_->snorm; - hist << std::setw(10) << std::left << state_->nfval; - hist << std::setw(10) << std::left << state_->ngrad; + os << " "; + os << std::setw(6) << std::left << state_->iter; + os << std::setw(15) << std::left << state_->value; + os << std::setw(15) << std::left << state_->gnorm; + os << std::setw(15) << std::left << state_->snorm; + os << std::setw(10) << std::left << state_->nfval; + os << std::setw(10) << std::left << state_->ngrad; if (maxit_ > 1) { - hist << std::setw(10) << std::left << iter_; - hist << std::setw(10) << std::left << flag_; - hist << std::setw(10) << std::left << totalKrylov_; + os << std::setw(10) << std::left << iter_; + os << std::setw(10) << std::left << flag_; + os << std::setw(10) << std::left << totalKrylov_; } else { - hist << std::setw(10) << std::left << iterKrylov_; - hist << std::setw(10) << std::left << flagKrylov_; + os << std::setw(10) << std::left << iterKrylov_; + os << std::setw(10) << std::left << flagKrylov_; } if ( feasible_ ) { - hist << std::setw(10) << std::left << "YES"; + os << std::setw(10) << std::left << "YES"; } else { - hist << std::setw(10) << std::left << "NO"; + os << std::setw(10) << std::left << "NO"; } - hist << std::endl; + os << std::endl; } - os << hist.str(); + os.flags(osFlags); } } // namespace TypeB diff --git a/packages/rol/src/algorithm/TypeB/ROL_TypeB_QuasiNewtonAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeB/ROL_TypeB_QuasiNewtonAlgorithm_Def.hpp index 94235d029f12..695f4aeb8ebd 100644 --- a/packages/rol/src/algorithm/TypeB/ROL_TypeB_QuasiNewtonAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeB/ROL_TypeB_QuasiNewtonAlgorithm_Def.hpp @@ -239,81 +239,81 @@ void QuasiNewtonAlgorithm::run( Vector &x, template void QuasiNewtonAlgorithm::writeHeader( std::ostream& os ) const { - std::stringstream hist; + std::ios_base::fmtflags osFlags(os.flags()); if (verbosity_ > 1) { - hist << std::string(114,'-') << std::endl; - hist << "Line-Search Projected Quasi-Newton with " << secantName_ << " Hessian approximation"; - hist << " status output definitions" << std::endl << std::endl; - hist << " iter - Number of iterates (steps taken)" << std::endl; - hist << " value - Objective function value" << std::endl; - hist << " gnorm - Norm of the gradient" << std::endl; - hist << " snorm - Norm of the step (update to optimization vector)" << std::endl; - hist << " alpha - Line search step length" << std::endl; - hist << " #fval - Cumulative number of times the objective function was evaluated" << std::endl; - hist << " #grad - Cumulative number of times the gradient was computed" << std::endl; - hist << " #proj - Cumulative number of times the projection was computed" << std::endl; - hist << " ls_#fval - Number of the times the objective function was evaluated during the line search" << std::endl; - hist << " sp_iter - Number iterations to compute quasi-Newton step" << std::endl; - hist << std::string(114,'-') << std::endl; + os << std::string(114,'-') << std::endl; + os << "Line-Search Projected Quasi-Newton with " << secantName_ << " Hessian approximation"; + os << " status output definitions" << std::endl << std::endl; + os << " iter - Number of iterates (steps taken)" << std::endl; + os << " value - Objective function value" << std::endl; + os << " gnorm - Norm of the gradient" << std::endl; + os << " snorm - Norm of the step (update to optimization vector)" << std::endl; + os << " alpha - Line search step length" << std::endl; + os << " #fval - Cumulative number of times the objective function was evaluated" << std::endl; + os << " #grad - Cumulative number of times the gradient was computed" << std::endl; + os << " #proj - Cumulative number of times the projection was computed" << std::endl; + os << " ls_#fval - Number of the times the objective function was evaluated during the line search" << std::endl; + os << " sp_iter - Number iterations to compute quasi-Newton step" << std::endl; + os << std::string(114,'-') << std::endl; } - hist << " "; - hist << std::setw(6) << std::left << "iter"; - hist << std::setw(15) << std::left << "value"; - hist << std::setw(15) << std::left << "gnorm"; - hist << std::setw(15) << std::left << "snorm"; - hist << std::setw(15) << std::left << "alpha"; - hist << std::setw(10) << std::left << "#fval"; - hist << std::setw(10) << std::left << "#grad"; - hist << std::setw(10) << std::left << "#proj"; - hist << std::setw(10) << std::left << "#ls_fval"; - hist << std::setw(10) << std::left << "sp_iter"; - hist << std::endl; - os << hist.str(); + os << " "; + os << std::setw(6) << std::left << "iter"; + os << std::setw(15) << std::left << "value"; + os << std::setw(15) << std::left << "gnorm"; + os << std::setw(15) << std::left << "snorm"; + os << std::setw(15) << std::left << "alpha"; + os << std::setw(10) << std::left << "#fval"; + os << std::setw(10) << std::left << "#grad"; + os << std::setw(10) << std::left << "#proj"; + os << std::setw(10) << std::left << "#ls_fval"; + os << std::setw(10) << std::left << "sp_iter"; + os << std::endl; + os.flags(osFlags); } template void QuasiNewtonAlgorithm::writeName( std::ostream& os ) const { - std::stringstream hist; - hist << std::endl << "Line-Search Projected Quasi-Newton (Type B, Bound Constraints)" << std::endl; - os << hist.str(); + std::ios_base::fmtflags osFlags(os.flags()); + os << std::endl << "Line-Search Projected Quasi-Newton (Type B, Bound Constraints)" << std::endl; + os.flags(osFlags); } template void QuasiNewtonAlgorithm::writeOutput( std::ostream& os, bool write_header ) const { - std::stringstream hist; - hist << std::scientific << std::setprecision(6); + std::ios_base::fmtflags osFlags(os.flags()); + os << std::scientific << std::setprecision(6); if ( state_->iter == 0 ) writeName(os); if ( write_header ) writeHeader(os); if ( state_->iter == 0 ) { - hist << " "; - hist << std::setw(6) << std::left << state_->iter; - hist << std::setw(15) << std::left << state_->value; - hist << std::setw(15) << std::left << state_->gnorm; - hist << std::setw(15) << std::left << "---"; - hist << std::setw(15) << std::left << "---"; - hist << std::setw(10) << std::left << state_->nfval; - hist << std::setw(10) << std::left << state_->ngrad; - hist << std::setw(10) << std::left << state_->nproj; - hist << std::setw(10) << std::left << "---"; - hist << std::setw(10) << std::left << "---"; - hist << std::endl; + os << " "; + os << std::setw(6) << std::left << state_->iter; + os << std::setw(15) << std::left << state_->value; + os << std::setw(15) << std::left << state_->gnorm; + os << std::setw(15) << std::left << "---"; + os << std::setw(15) << std::left << "---"; + os << std::setw(10) << std::left << state_->nfval; + os << std::setw(10) << std::left << state_->ngrad; + os << std::setw(10) << std::left << state_->nproj; + os << std::setw(10) << std::left << "---"; + os << std::setw(10) << std::left << "---"; + os << std::endl; } else { - hist << " "; - hist << std::setw(6) << std::left << state_->iter; - hist << std::setw(15) << std::left << state_->value; - hist << std::setw(15) << std::left << state_->gnorm; - hist << std::setw(15) << std::left << state_->snorm; - hist << std::setw(15) << std::left << state_->searchSize; - hist << std::setw(10) << std::left << state_->nfval; - hist << std::setw(10) << std::left << state_->ngrad; - hist << std::setw(10) << std::left << state_->nproj; - hist << std::setw(10) << std::left << ls_nfval_; - hist << std::setw(10) << std::left << spgIter_; - hist << std::endl; + os << " "; + os << std::setw(6) << std::left << state_->iter; + os << std::setw(15) << std::left << state_->value; + os << std::setw(15) << std::left << state_->gnorm; + os << std::setw(15) << std::left << state_->snorm; + os << std::setw(15) << std::left << state_->searchSize; + os << std::setw(10) << std::left << state_->nfval; + os << std::setw(10) << std::left << state_->ngrad; + os << std::setw(10) << std::left << state_->nproj; + os << std::setw(10) << std::left << ls_nfval_; + os << std::setw(10) << std::left << spgIter_; + os << std::endl; } - os << hist.str(); + os.flags(osFlags); } } // namespace TypeB diff --git a/packages/rol/src/algorithm/TypeB/ROL_TypeB_SpectralGradientAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeB/ROL_TypeB_SpectralGradientAlgorithm_Def.hpp index 6a6b11f8ef48..3a4682c766d7 100644 --- a/packages/rol/src/algorithm/TypeB/ROL_TypeB_SpectralGradientAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeB/ROL_TypeB_SpectralGradientAlgorithm_Def.hpp @@ -210,77 +210,77 @@ void SpectralGradientAlgorithm::run( Vector &x, template void SpectralGradientAlgorithm::writeHeader( std::ostream& os ) const { - std::stringstream hist; + std::ios_base::fmtflags osFlags(os.flags()); if (verbosity_ > 1) { - hist << std::string(109,'-') << std::endl; - hist << "Spectral projected gradient descent"; - hist << " status output definitions" << std::endl << std::endl; - hist << " iter - Number of iterates (steps taken)" << std::endl; - hist << " value - Objective function value" << std::endl; - hist << " gnorm - Norm of the gradient" << std::endl; - hist << " snorm - Norm of the step (update to optimization vector)" << std::endl; - hist << " alpha - Line search step length" << std::endl; - hist << " lambda - Spectral step length" << std::endl; - hist << " #fval - Cumulative number of times the objective function was evaluated" << std::endl; - hist << " #grad - Cumulative number of times the gradient was computed" << std::endl; - hist << " #proj - Cumulative number of times the projection was computed" << std::endl; - hist << std::string(109,'-') << std::endl; + os << std::string(109,'-') << std::endl; + os << "Spectral projected gradient descent"; + os << " status output definitions" << std::endl << std::endl; + os << " iter - Number of iterates (steps taken)" << std::endl; + os << " value - Objective function value" << std::endl; + os << " gnorm - Norm of the gradient" << std::endl; + os << " snorm - Norm of the step (update to optimization vector)" << std::endl; + os << " alpha - Line search step length" << std::endl; + os << " lambda - Spectral step length" << std::endl; + os << " #fval - Cumulative number of times the objective function was evaluated" << std::endl; + os << " #grad - Cumulative number of times the gradient was computed" << std::endl; + os << " #proj - Cumulative number of times the projection was computed" << std::endl; + os << std::string(109,'-') << std::endl; } - hist << " "; - hist << std::setw(6) << std::left << "iter"; - hist << std::setw(15) << std::left << "value"; - hist << std::setw(15) << std::left << "gnorm"; - hist << std::setw(15) << std::left << "snorm"; - hist << std::setw(15) << std::left << "alpha"; - hist << std::setw(15) << std::left << "lambda"; - hist << std::setw(10) << std::left << "#fval"; - hist << std::setw(10) << std::left << "#grad"; - hist << std::setw(10) << std::left << "#proj"; - hist << std::endl; - os << hist.str(); + os << " "; + os << std::setw(6) << std::left << "iter"; + os << std::setw(15) << std::left << "value"; + os << std::setw(15) << std::left << "gnorm"; + os << std::setw(15) << std::left << "snorm"; + os << std::setw(15) << std::left << "alpha"; + os << std::setw(15) << std::left << "lambda"; + os << std::setw(10) << std::left << "#fval"; + os << std::setw(10) << std::left << "#grad"; + os << std::setw(10) << std::left << "#proj"; + os << std::endl; + os.flags(osFlags); } template void SpectralGradientAlgorithm::writeName( std::ostream& os ) const { - std::stringstream hist; - hist << std::endl << "Projected Spectral Gradient Method (Type B, Bound Constraints)" << std::endl; - os << hist.str(); + std::ios_base::fmtflags osFlags(os.flags()); + os << std::endl << "Projected Spectral Gradient Method (Type B, Bound Constraints)" << std::endl; + os.flags(osFlags); } template void SpectralGradientAlgorithm::writeOutput( std::ostream& os, bool write_header ) const { - std::stringstream hist; - hist << std::scientific << std::setprecision(6); + std::ios_base::fmtflags osFlags(os.flags()); + os << std::scientific << std::setprecision(6); if ( state_->iter == 0 ) writeName(os); if ( write_header ) writeHeader(os); if ( state_->iter == 0 ) { - hist << " "; - hist << std::setw(6) << std::left << state_->iter; - hist << std::setw(15) << std::left << state_->value; - hist << std::setw(15) << std::left << state_->gnorm; - hist << std::setw(15) << std::left << "---"; - hist << std::setw(15) << std::left << "---"; - hist << std::setw(15) << std::left << lambda_; - hist << std::setw(10) << std::left << state_->nfval; - hist << std::setw(10) << std::left << state_->ngrad; - hist << std::setw(10) << std::left << state_->nproj; - hist << std::endl; + os << " "; + os << std::setw(6) << std::left << state_->iter; + os << std::setw(15) << std::left << state_->value; + os << std::setw(15) << std::left << state_->gnorm; + os << std::setw(15) << std::left << "---"; + os << std::setw(15) << std::left << "---"; + os << std::setw(15) << std::left << lambda_; + os << std::setw(10) << std::left << state_->nfval; + os << std::setw(10) << std::left << state_->ngrad; + os << std::setw(10) << std::left << state_->nproj; + os << std::endl; } else { - hist << " "; - hist << std::setw(6) << std::left << state_->iter; - hist << std::setw(15) << std::left << state_->value; - hist << std::setw(15) << std::left << state_->gnorm; - hist << std::setw(15) << std::left << state_->snorm; - hist << std::setw(15) << std::left << state_->searchSize; - hist << std::setw(15) << std::left << lambda_; - hist << std::setw(10) << std::left << state_->nfval; - hist << std::setw(10) << std::left << state_->ngrad; - hist << std::setw(10) << std::left << state_->nproj; - hist << std::endl; + os << " "; + os << std::setw(6) << std::left << state_->iter; + os << std::setw(15) << std::left << state_->value; + os << std::setw(15) << std::left << state_->gnorm; + os << std::setw(15) << std::left << state_->snorm; + os << std::setw(15) << std::left << state_->searchSize; + os << std::setw(15) << std::left << lambda_; + os << std::setw(10) << std::left << state_->nfval; + os << std::setw(10) << std::left << state_->ngrad; + os << std::setw(10) << std::left << state_->nproj; + os << std::endl; } - os << hist.str(); + os.flags(osFlags); } } // namespace TypeB diff --git a/packages/rol/src/algorithm/TypeB/ROL_TypeB_TrustRegionSPGAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeB/ROL_TypeB_TrustRegionSPGAlgorithm_Def.hpp index 34d5f699f80e..38677ebd20fb 100644 --- a/packages/rol/src/algorithm/TypeB/ROL_TypeB_TrustRegionSPGAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeB/ROL_TypeB_TrustRegionSPGAlgorithm_Def.hpp @@ -914,95 +914,95 @@ void TrustRegionSPGAlgorithm::dproj(Vector &x, template void TrustRegionSPGAlgorithm::writeHeader( std::ostream& os ) const { - std::stringstream hist; + std::ios_base::fmtflags osFlags(os.flags()); if (verbosity_ > 1) { - hist << std::string(114,'-') << std::endl; - hist << " SPG trust-region method status output definitions" << std::endl << std::endl; - hist << " iter - Number of iterates (steps taken)" << std::endl; - hist << " value - Objective function value" << std::endl; - hist << " gnorm - Norm of the gradient" << std::endl; - hist << " snorm - Norm of the step (update to optimization vector)" << std::endl; - hist << " delta - Trust-Region radius" << std::endl; - hist << " #fval - Number of times the objective function was evaluated" << std::endl; - hist << " #grad - Number of times the gradient was computed" << std::endl; - hist << " #hess - Number of times the Hessian was applied" << std::endl; - hist << " #proj - Number of times the projection was computed" << std::endl; - hist << std::endl; - hist << " tr_flag - Trust-Region flag" << std::endl; + os << std::string(114,'-') << std::endl; + os << " SPG trust-region method status output definitions" << std::endl << std::endl; + os << " iter - Number of iterates (steps taken)" << std::endl; + os << " value - Objective function value" << std::endl; + os << " gnorm - Norm of the gradient" << std::endl; + os << " snorm - Norm of the step (update to optimization vector)" << std::endl; + os << " delta - Trust-Region radius" << std::endl; + os << " #fval - Number of times the objective function was evaluated" << std::endl; + os << " #grad - Number of times the gradient was computed" << std::endl; + os << " #hess - Number of times the Hessian was applied" << std::endl; + os << " #proj - Number of times the projection was computed" << std::endl; + os << std::endl; + os << " tr_flag - Trust-Region flag" << std::endl; for( int flag = TRUtils::SUCCESS; flag != TRUtils::UNDEFINED; ++flag ) { - hist << " " << NumberToString(flag) << " - " + os << " " << NumberToString(flag) << " - " << TRUtils::ETRFlagToString(static_cast(flag)) << std::endl; } - hist << std::endl; - hist << " iterSPG - Number of Spectral Projected Gradient iterations" << std::endl << std::endl; - hist << " flagSPG - Trust-Region Truncated CG flag" << std::endl; - hist << " 0 - Converged" << std::endl; - hist << " 1 - Iteration Limit Exceeded" << std::endl; - hist << std::string(114,'-') << std::endl; + os << std::endl; + os << " iterSPG - Number of Spectral Projected Gradient iterations" << std::endl << std::endl; + os << " flagSPG - Trust-Region Truncated CG flag" << std::endl; + os << " 0 - Converged" << std::endl; + os << " 1 - Iteration Limit Exceeded" << std::endl; + os << std::string(114,'-') << std::endl; } - hist << " "; - hist << std::setw(6) << std::left << "iter"; - hist << std::setw(15) << std::left << "value"; - hist << std::setw(15) << std::left << "gnorm"; - hist << std::setw(15) << std::left << "snorm"; - hist << std::setw(15) << std::left << "delta"; - hist << std::setw(10) << std::left << "#fval"; - hist << std::setw(10) << std::left << "#grad"; - hist << std::setw(10) << std::left << "#hess"; - hist << std::setw(10) << std::left << "#proj"; - hist << std::setw(10) << std::left << "tr_flag"; - hist << std::setw(10) << std::left << "iterSPG"; - hist << std::setw(10) << std::left << "flagSPG"; - hist << std::endl; - os << hist.str(); + os << " "; + os << std::setw(6) << std::left << "iter"; + os << std::setw(15) << std::left << "value"; + os << std::setw(15) << std::left << "gnorm"; + os << std::setw(15) << std::left << "snorm"; + os << std::setw(15) << std::left << "delta"; + os << std::setw(10) << std::left << "#fval"; + os << std::setw(10) << std::left << "#grad"; + os << std::setw(10) << std::left << "#hess"; + os << std::setw(10) << std::left << "#proj"; + os << std::setw(10) << std::left << "tr_flag"; + os << std::setw(10) << std::left << "iterSPG"; + os << std::setw(10) << std::left << "flagSPG"; + os << std::endl; + os.flags(osFlags); } template void TrustRegionSPGAlgorithm::writeName( std::ostream& os ) const { - std::stringstream hist; - hist << std::endl << "SPG Trust-Region Method (Type B, Bound Constraints)" << std::endl; - os << hist.str(); + std::ios_base::fmtflags osFlags(os.flags()); + os << std::endl << "SPG Trust-Region Method (Type B, Bound Constraints)" << std::endl; + os.flags(osFlags); } template void TrustRegionSPGAlgorithm::writeOutput( std::ostream& os, bool write_header ) const { - std::stringstream hist; - hist << std::scientific << std::setprecision(6); + std::ios_base::fmtflags osFlags(os.flags()); + os << std::scientific << std::setprecision(6); if ( state_->iter == 0 ) writeName(os); if ( write_header ) writeHeader(os); if ( state_->iter == 0 ) { - hist << " "; - hist << std::setw(6) << std::left << state_->iter; - hist << std::setw(15) << std::left << state_->value; - hist << std::setw(15) << std::left << state_->gnorm; - hist << std::setw(15) << std::left << "---"; - hist << std::setw(15) << std::left << state_->searchSize; - hist << std::setw(10) << std::left << state_->nfval; - hist << std::setw(10) << std::left << state_->ngrad; - hist << std::setw(10) << std::left << nhess_; - hist << std::setw(10) << std::left << state_->nproj; - hist << std::setw(10) << std::left << "---"; - hist << std::setw(10) << std::left << "---"; - hist << std::setw(10) << std::left << "---"; - hist << std::endl; + os << " "; + os << std::setw(6) << std::left << state_->iter; + os << std::setw(15) << std::left << state_->value; + os << std::setw(15) << std::left << state_->gnorm; + os << std::setw(15) << std::left << "---"; + os << std::setw(15) << std::left << state_->searchSize; + os << std::setw(10) << std::left << state_->nfval; + os << std::setw(10) << std::left << state_->ngrad; + os << std::setw(10) << std::left << nhess_; + os << std::setw(10) << std::left << state_->nproj; + os << std::setw(10) << std::left << "---"; + os << std::setw(10) << std::left << "---"; + os << std::setw(10) << std::left << "---"; + os << std::endl; } else { - hist << " "; - hist << std::setw(6) << std::left << state_->iter; - hist << std::setw(15) << std::left << state_->value; - hist << std::setw(15) << std::left << state_->gnorm; - hist << std::setw(15) << std::left << state_->snorm; - hist << std::setw(15) << std::left << state_->searchSize; - hist << std::setw(10) << std::left << state_->nfval; - hist << std::setw(10) << std::left << state_->ngrad; - hist << std::setw(10) << std::left << nhess_; - hist << std::setw(10) << std::left << state_->nproj; - hist << std::setw(10) << std::left << TRflag_; - hist << std::setw(10) << std::left << SPiter_; - hist << std::setw(10) << std::left << SPflag_; - hist << std::endl; + os << " "; + os << std::setw(6) << std::left << state_->iter; + os << std::setw(15) << std::left << state_->value; + os << std::setw(15) << std::left << state_->gnorm; + os << std::setw(15) << std::left << state_->snorm; + os << std::setw(15) << std::left << state_->searchSize; + os << std::setw(10) << std::left << state_->nfval; + os << std::setw(10) << std::left << state_->ngrad; + os << std::setw(10) << std::left << nhess_; + os << std::setw(10) << std::left << state_->nproj; + os << std::setw(10) << std::left << TRflag_; + os << std::setw(10) << std::left << SPiter_; + os << std::setw(10) << std::left << SPflag_; + os << std::endl; } - os << hist.str(); + os.flags(osFlags); } } // namespace TypeB diff --git a/packages/rol/src/algorithm/TypeU/ROL_TypeU_LineSearchAlgorithm.hpp b/packages/rol/src/algorithm/TypeU/ROL_TypeU_LineSearchAlgorithm.hpp index 00134e2aab8f..ed81db4a60f7 100644 --- a/packages/rol/src/algorithm/TypeU/ROL_TypeU_LineSearchAlgorithm.hpp +++ b/packages/rol/src/algorithm/TypeU/ROL_TypeU_LineSearchAlgorithm.hpp @@ -143,6 +143,7 @@ class LineSearchAlgorithm : public Algorithm { void initialize(const Vector &x, const Vector &g, Objective &obj, std::ostream &outStream = std::cout); + using TypeU::Algorithm::run; void run( Vector &x, const Vector &g, Objective &obj, diff --git a/packages/rol/src/function/dynamic/ROL_ReducedDynamicObjective.hpp b/packages/rol/src/function/dynamic/ROL_ReducedDynamicObjective.hpp index c8dbe0a09d7e..a3098e30285d 100644 --- a/packages/rol/src/function/dynamic/ROL_ReducedDynamicObjective.hpp +++ b/packages/rol/src/function/dynamic/ROL_ReducedDynamicObjective.hpp @@ -269,6 +269,28 @@ class ReducedDynamicObjective : public Objective { } } + void update(const Vector &x, UpdateType type, int iter = -1) { + if (useSketch_) { + stateSketch_->update(type); + adjointSketch_->update(type); + if (useHessian_) stateSensSketch_->update(type); + } + for (size_type i = 0; i < uhist_.size(); ++i) uhist_[i]->zero(); + val_ = static_cast(0); + isValueComputed_ = false; + isStateComputed_ = false; + isAdjointComputed_ = false; + + if (iter >= 0 && iter%freq_==0 && print_) { + std::stringstream name; + name << "optvector." << iter << ".txt"; + std::ofstream file; + file.open(name.str()); + x.print(file); + file.close(); + } + } + Real value( const Vector &x, Real &tol ) { if (!isValueComputed_) { int eflag(0); diff --git a/packages/rol/src/function/sketching/ROL_Sketch.hpp b/packages/rol/src/function/sketching/ROL_Sketch.hpp index 64bddf2ec1a1..f68c8e66a581 100644 --- a/packages/rol/src/function/sketching/ROL_Sketch.hpp +++ b/packages/rol/src/function/sketching/ROL_Sketch.hpp @@ -47,6 +47,7 @@ #include "ROL_Vector.hpp" #include "ROL_LinearAlgebra.hpp" #include "ROL_LAPACK.hpp" +#include "ROL_UpdateType.hpp" #include "ROL_Types.hpp" #include #include @@ -363,6 +364,21 @@ class Sketch { reset(); } + void update(UpdateType type) { + switch(type) { + case UpdateType::Initial: + case UpdateType::Accept: + case UpdateType::Trial: + case UpdateType::Revert: + case UpdateType::Temp: + flagP_ = false; flagQ_ = false; flagC_ = false; + reset(); + break; + default: + break; + } + } + int advance(const Real nu, Vector &h, const int col, const Real eta = 1.0) { // Check to see if col is less than ncol_ if ( col >= ncol_ || col < 0 ) { diff --git a/packages/rol/test/algorithm/TypeP/CMakeLists.txt b/packages/rol/test/algorithm/TypeP/CMakeLists.txt index a1f308fb6e18..c0a93e5727ac 100644 --- a/packages/rol/test/algorithm/TypeP/CMakeLists.txt +++ b/packages/rol/test/algorithm/TypeP/CMakeLists.txt @@ -53,6 +53,15 @@ TRIBITS_ADD_EXECUTABLE_AND_TEST( ADD_DIR_TO_NAME ) +TRIBITS_ADD_EXECUTABLE_AND_TEST( + CompareTypeU + SOURCES test_07.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + TRIBITS_COPY_FILES_TO_BINARY_DIR( TypePTestDataCopy SOURCE_FILES From ff0b4fc9fd2ac7f5ec17c80d975f867d573eda15 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Thu, 8 Jun 2023 17:12:00 -0600 Subject: [PATCH 48/65] Fixed screwed up CMakeList that I recently committed. --- packages/rol/example/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/rol/example/CMakeLists.txt b/packages/rol/example/CMakeLists.txt index 455edd1462f4..5c58be7b2fb9 100644 --- a/packages/rol/example/CMakeLists.txt +++ b/packages/rol/example/CMakeLists.txt @@ -23,7 +23,6 @@ ADD_SUBDIRECTORY(dense-hessian) ADD_SUBDIRECTORY(stream-buffer) ADD_SUBDIRECTORY(oed) ADD_SUBDIRECTORY(lincon-test) -ADD_SUBDIRECTORY(shardes) IF(${PACKAGE_NAME}_ENABLE_Sacado) ADD_SUBDIRECTORY(sacado) From c924eeb5bb24a0dcfcd0fa84a5ac7d0cb619e9c3 Mon Sep 17 00:00:00 2001 From: Drew Kouri Date: Thu, 8 Jun 2023 17:19:29 -0600 Subject: [PATCH 49/65] Fixed some other CMake issues from my last commit and added missing test. --- .../PDE-OPT/navier-stokes/CMakeLists.txt | 6 - packages/rol/test/algorithm/TypeP/test_07.cpp | 198 ++++++++++++++++++ 2 files changed, 198 insertions(+), 6 deletions(-) create mode 100644 packages/rol/test/algorithm/TypeP/test_07.cpp diff --git a/packages/rol/example/PDE-OPT/navier-stokes/CMakeLists.txt b/packages/rol/example/PDE-OPT/navier-stokes/CMakeLists.txt index d0e32f490fa7..138990ae9eac 100644 --- a/packages/rol/example/PDE-OPT/navier-stokes/CMakeLists.txt +++ b/packages/rol/example/PDE-OPT/navier-stokes/CMakeLists.txt @@ -41,12 +41,6 @@ IF(${PROJECT_NAME}_ENABLE_Intrepid AND ADD_DIR_TO_NAME ) - TRIBITS_ADD_EXECUTABLE( - example_06 - SOURCES example_06.cpp - ADD_DIR_TO_NAME - ) - TRIBITS_ADD_TEST( example_01 ARGS PrintItAll diff --git a/packages/rol/test/algorithm/TypeP/test_07.cpp b/packages/rol/test/algorithm/TypeP/test_07.cpp new file mode 100644 index 000000000000..5f47c96b16d4 --- /dev/null +++ b/packages/rol/test/algorithm/TypeP/test_07.cpp @@ -0,0 +1,198 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +/*! \file test_07.cpp + \brief Validate that the proximal gradient algorithm reverts to + linesearch gradient descent when the nonsmooth term is zero. +*/ + +#include "ROL_TypeP_ProxGradientAlgorithm.hpp" +#include "ROL_TypeU_LineSearchAlgorithm.hpp" +#include "ROL_StdObjective.hpp" +#include "ROL_l1Objective.hpp" +#include "ROL_Stream.hpp" +#include "Teuchos_GlobalMPISession.hpp" + +template +class QuadraticTypeP_Test01 : public ROL::StdObjective { +private: + int dim_; + std::vector a_, b_; + +public: + QuadraticTypeP_Test01(int dim) : dim_(dim) { + a_.resize(dim); + b_.resize(dim); + for (int i = 0; i < dim; ++i) { + a_[i] = static_cast(5)*static_cast(rand())/static_cast(RAND_MAX); + b_[i] = static_cast(20)*static_cast(rand())/static_cast(RAND_MAX) - static_cast(10); + } + } + + Real value(const std::vector &x, Real &tol) { + Real val(0); + for (int i = 0; i < dim_; ++i) + val += static_cast(0.5)*a_[i]*x[i]*x[i] + b_[i]*x[i]; + return val; + } + + void gradient(std::vector &g, const std::vector &x, Real &tol) { + for (int i = 0; i < dim_; ++i) + g[i] = a_[i]*x[i] + b_[i]; + } + + void hessVec(std::vector &hv, const std::vector &v, const std::vector &x, Real &tol) { + for (int i = 0; i < dim_; ++i) + hv[i] = a_[i]*v[i]; + } + + void getSolution(std::vector &x, const std::vector &wts, const std::vector &y) const { + for (int i = 0; i < dim_; ++i) + x[i] = (std::min(wts[i], std::max(-wts[i], a_[i]*y[i] + b_[i])) - b_[i]) / a_[i]; + } +}; + +typedef double RealT; + +int main(int argc, char *argv[]) { + + Teuchos::GlobalMPISession mpiSession(&argc, &argv); + + // This little trick lets us print to std::cout only if a + // (dummy) command-line argument is provided. + int iprint = argc - 1; + ROL::Ptr outStream; + ROL::nullstream bhs; // outputs nothing + if (iprint > 0) + outStream = ROL::makePtrFromRef(std::cout); + else + outStream = ROL::makePtrFromRef(bhs); + + int errorFlag = 0; + + try { + RealT tol = 1e2*std::sqrt(ROL::ROL_EPSILON()); + + ROL::ParameterList list; + list.sublist("General").set("Output Level",iprint); + list.sublist("Step").set("Type","Line Search"); + list.sublist("Step").sublist("Line Search").set("User Defined Initial Step Size",true); + list.sublist("Step").sublist("Line Search").set("Initial Step Size",0.75); + list.sublist("Step").sublist("Line Search").set("Maximum Step Size",1e8); + list.sublist("Step").sublist("Line Search").set("Use Adaptive Step Size Selection",false); + list.sublist("Step").sublist("Line Search").set("Use Previous Step Length as Initial Guess",false); + list.sublist("Status Test").set("Gradient Tolerance",1e-7); + list.sublist("Status Test").set("Constraint Tolerance",1e-8); + list.sublist("Status Test").set("Step Tolerance",1e-12); + list.sublist("Status Test").set("Iteration Limit", 10000); + + int dim = 5; + ROL::Ptr> sol, wts, y; + ROL::Ptr> sobj; + ROL::Ptr> nobj; + ROL::Ptr> algo; + std::vector data; + RealT err(0); + + *outStream << std::endl << "Random Diagonal LASSO Test Problem" << std::endl << std::endl; + ROL::Ptr> wtsP = ROL::makePtr>(dim); + ROL::Ptr> yP = ROL::makePtr>(dim); + wts = ROL::makePtr>(wtsP); + y = ROL::makePtr>(yP); + sol = ROL::makePtr>(dim); + //wts->randomize(static_cast(0),static_cast(1)); + wts->zero(); + y->randomize(static_cast(-5),static_cast(5)); + sol->zero(); + + nobj = ROL::makePtr>(wts,y); + sobj = ROL::makePtr>(dim); + + // Check derivatives of smooth function + ROL::Ptr> xd = sol->clone(); + xd->randomize(-1.0,1.0); + ROL::Ptr> yd = sol->clone(); + yd->randomize(-1.0,1.0); + ROL::Ptr> zd = sol->clone(); + zd->randomize(-1.0,1.0); + sobj->checkGradient(*xd,*yd,true,*outStream); + sobj->checkHessVec(*xd,*yd,true,*outStream); + sobj->checkHessSym(*xd,*yd,*zd,true,*outStream); + + algo = ROL::makePtr>(list); + algo->run(*sol,*sobj,*nobj,*outStream); + + ROL::ParameterList plist; + plist.sublist("General").set("Output Level",iprint); + plist.sublist("Step").sublist("Line Search").set("User Defined Initial Step Size",true); + plist.sublist("Step").sublist("Line Search").set("Initial Step Size",0.75); + plist.sublist("Step").sublist("Line Search").sublist("Descent Method").set("Type","Steepest Descent"); + plist.sublist("Step").sublist("Line Search").sublist("Line-Search Method").set("Type","Backtracking"); + plist.sublist("Status Test").set("Gradient Tolerance",1e-7); + plist.sublist("Status Test").set("Constraint Tolerance",1e-8); + plist.sublist("Status Test").set("Step Tolerance",1e-12); + plist.sublist("Status Test").set("Iteration Limit", 10000); + ROL::TypeU::LineSearchAlgorithm algoLS(plist); + ROL::Ptr> solLS = sol->clone(); + solLS->zero(); + algoLS.run(*solLS,*sobj,*outStream); + solLS->axpy(static_cast(-1),*sol); + + err = solLS->norm(); + *outStream << std::endl; + *outStream << " Absolute Error: " << err << std::endl; + *outStream << " Relative Error: " << err / sol->norm() << std::endl << std::endl; + errorFlag += (err > tol ? 1 : 0); + } + catch (std::logic_error& err) { + *outStream << err.what() << "\n"; + errorFlag = -1000; + }; // end try + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return 0; +} From 4a848fa2486620f7c8134c75ee2ef7122e8c6850 Mon Sep 17 00:00:00 2001 From: Denis Ridzal Date: Sat, 10 Jun 2023 17:28:09 -0600 Subject: [PATCH 50/65] Changed tolerances to prevent test failures. This example could serve as a prototype for handling machine-dependent gradient tolerances and solution verification tolerances. --- packages/rol/test/algorithm/TypeP/test_01.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/rol/test/algorithm/TypeP/test_01.cpp b/packages/rol/test/algorithm/TypeP/test_01.cpp index e94ee65ca0ea..feaf0beb5957 100644 --- a/packages/rol/test/algorithm/TypeP/test_01.cpp +++ b/packages/rol/test/algorithm/TypeP/test_01.cpp @@ -109,7 +109,7 @@ int main(int argc, char *argv[]) { int errorFlag = 0; try { - RealT tol = 1e2*std::sqrt(ROL::ROL_EPSILON()); + RealT tol = std::sqrt(ROL::ROL_EPSILON()); ROL::ParameterList list; list.sublist("General").set("Output Level",iprint); @@ -117,11 +117,11 @@ int main(int argc, char *argv[]) { list.sublist("Step").sublist("Line Search").set("Initial Step Size",1e0); list.sublist("Step").sublist("Line Search").set("Maximum Step Size",1e8); list.sublist("Step").sublist("Line Search").set("Use Adaptive Step Size Selection",true); - list.sublist("Status Test").set("Gradient Tolerance",1e-7); - list.sublist("Status Test").set("Constraint Tolerance",1e-8); - list.sublist("Status Test").set("Step Tolerance",1e-12); + list.sublist("Status Test").set("Gradient Tolerance",tol); + list.sublist("Status Test").set("Constraint Tolerance",1e-1*tol); + list.sublist("Status Test").set("Step Tolerance",1e-4*tol); list.sublist("Status Test").set("Iteration Limit", 10000); - + int dim = 5; ROL::Ptr> sol, wts, y; ROL::Ptr> sobj; @@ -172,7 +172,7 @@ int main(int argc, char *argv[]) { } *outStream << std::endl; *outStream << " Max-Error = " << err << std::endl; - errorFlag += (err > tol ? 1 : 0); + errorFlag += (err > 100*tol ? 1 : 0); } catch (std::logic_error& err) { *outStream << err.what() << "\n"; From 3aeb5153531ad5ea4d1092e5e12635c0a615a2e6 Mon Sep 17 00:00:00 2001 From: Denis Ridzal Date: Sat, 10 Jun 2023 17:51:28 -0600 Subject: [PATCH 51/65] Adjusting tolerances once more. --- packages/rol/test/algorithm/TypeP/test_01.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/rol/test/algorithm/TypeP/test_01.cpp b/packages/rol/test/algorithm/TypeP/test_01.cpp index feaf0beb5957..ad3ccfd09902 100644 --- a/packages/rol/test/algorithm/TypeP/test_01.cpp +++ b/packages/rol/test/algorithm/TypeP/test_01.cpp @@ -110,6 +110,7 @@ int main(int argc, char *argv[]) { try { RealT tol = std::sqrt(ROL::ROL_EPSILON()); + RealT errtol = 1e3*tol; ROL::ParameterList list; list.sublist("General").set("Output Level",iprint); @@ -117,9 +118,9 @@ int main(int argc, char *argv[]) { list.sublist("Step").sublist("Line Search").set("Initial Step Size",1e0); list.sublist("Step").sublist("Line Search").set("Maximum Step Size",1e8); list.sublist("Step").sublist("Line Search").set("Use Adaptive Step Size Selection",true); - list.sublist("Status Test").set("Gradient Tolerance",tol); - list.sublist("Status Test").set("Constraint Tolerance",1e-1*tol); + list.sublist("Status Test").set("Gradient Tolerance",1e1*tol); list.sublist("Status Test").set("Step Tolerance",1e-4*tol); + list.sublist("Status Test").set("Use Relative Tolerances",true); list.sublist("Status Test").set("Iteration Limit", 10000); int dim = 5; @@ -172,7 +173,8 @@ int main(int argc, char *argv[]) { } *outStream << std::endl; *outStream << " Max-Error = " << err << std::endl; - errorFlag += (err > 100*tol ? 1 : 0); + *outStream << " Error Tol = " << errtol << std::endl; + errorFlag += (err > errtol ? 1 : 0); } catch (std::logic_error& err) { *outStream << err.what() << "\n"; From 1e6f576975a749847f7755f061cf1c6805158781 Mon Sep 17 00:00:00 2001 From: srberna Date: Tue, 23 May 2023 10:41:17 -0600 Subject: [PATCH 52/65] Update build to force COMPLEX_DOUBLE and enable FLOAT --- packages/framework/ini-files/config-specs.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/framework/ini-files/config-specs.ini b/packages/framework/ini-files/config-specs.ini index d4db3fa8bfa1..a96e2ff62cb1 100644 --- a/packages/framework/ini-files/config-specs.ini +++ b/packages/framework/ini-files/config-specs.ini @@ -1824,7 +1824,8 @@ use PACKAGE-ENABLES|NO-PACKAGE-ENABLES use COMMON opt-set-cmake-var MPI_EXEC_PRE_NUMPROCS_FLAGS STRING : --bind-to;none -opt-set-cmake-var Trilinos_ENABLE_COMPLEX_DOUBLE BOOL : ON +opt-set-cmake-var Trilinos_ENABLE_COMPLEX_DOUBLE BOOL FORCE : ON +opt-set-cmake-var Trilinos_ENABLE_FLOAT BOOL FORCE : ON opt-set-cmake-var Teko_DISABLE_LSCSTABALIZED_TPETRA_ALPAH_INV_D BOOL : ON opt-set-cmake-var KokkosKernels_blas_serial_MPI_1_DISABLE BOOL : ON opt-set-cmake-var ROL_example_PDE-OPT_helmholtz_example_02_MPI_1_DISABLE BOOL : ON From 2a5ef22402fce816acc0ccd99aa29074fc67a436 Mon Sep 17 00:00:00 2001 From: srberna Date: Tue, 30 May 2023 10:50:54 -0600 Subject: [PATCH 53/65] Revert "Update build to force COMPLEX_DOUBLE and enable FLOAT" This reverts commit 6a2f7e4c6c48e0bb67db2ce6ef5317c9a9bf59b0. --- packages/framework/ini-files/config-specs.ini | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/framework/ini-files/config-specs.ini b/packages/framework/ini-files/config-specs.ini index a96e2ff62cb1..d4db3fa8bfa1 100644 --- a/packages/framework/ini-files/config-specs.ini +++ b/packages/framework/ini-files/config-specs.ini @@ -1824,8 +1824,7 @@ use PACKAGE-ENABLES|NO-PACKAGE-ENABLES use COMMON opt-set-cmake-var MPI_EXEC_PRE_NUMPROCS_FLAGS STRING : --bind-to;none -opt-set-cmake-var Trilinos_ENABLE_COMPLEX_DOUBLE BOOL FORCE : ON -opt-set-cmake-var Trilinos_ENABLE_FLOAT BOOL FORCE : ON +opt-set-cmake-var Trilinos_ENABLE_COMPLEX_DOUBLE BOOL : ON opt-set-cmake-var Teko_DISABLE_LSCSTABALIZED_TPETRA_ALPAH_INV_D BOOL : ON opt-set-cmake-var KokkosKernels_blas_serial_MPI_1_DISABLE BOOL : ON opt-set-cmake-var ROL_example_PDE-OPT_helmholtz_example_02_MPI_1_DISABLE BOOL : ON From f7fc59438e752a9bdd86137e57e3c7ecbfc54b98 Mon Sep 17 00:00:00 2001 From: srberna Date: Tue, 30 May 2023 10:59:41 -0600 Subject: [PATCH 54/65] Update for new Sierra code requirements. CMake variables Trilinos_ENABLE_DOUBLE and Trilinos_ENABLE_COMPLEX_DOUBLE are set to OFF and Trilinos_ENABLE_FLOAT and Trilinos_ENABLE_COMPLEX_FLOAT are set to ON. --- packages/framework/ini-files/config-specs.ini | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/framework/ini-files/config-specs.ini b/packages/framework/ini-files/config-specs.ini index d4db3fa8bfa1..826eea7f3918 100644 --- a/packages/framework/ini-files/config-specs.ini +++ b/packages/framework/ini-files/config-specs.ini @@ -1853,6 +1853,14 @@ use rhel7_sems-gnu-8.3.0-openmpi-1.10.1-serial_debug_shared_no-kokkos-arch_no-as use BUILD-TYPE|DEBUG-COVERAGE-GNU use PACKAGE-ENABLES|ALL +[rhel7_sems-gnu-8.3.0-openmpi-1.10.1-serial_debug_shared_no-kokkos-arch_no-asan_complex-float_no-fpic_mpi_no-pt_no-rdc_no-uvm_deprecated-on_no-package-enables] +#uses sems-archive modules +use rhel7_sems-gnu-8.3.0-openmpi-1.10.1-serial_debug_shared_no-kokkos-arch_no-asan_no-complex_no-fpic_mpi_no-pt_no-rdc_no-uvm_deprecated-on_no-package-enables +opt-set-cmake-var Trilinos_ENABLE_DOUBLE BOOL FORCE : OFF +opt-set-cmake-var Trilinos_ENABLE_COMPLEX_DOUBLE BOOL FORCE : OFF +opt-set-cmake-var Trilinos_ENABLE_FLOAT BOOL FORCE : ON +opt-set-cmake-var Trilinos_ENABLE_COMPLEX_FLOAT BOOL FORCE : ON + [rhel7_sems-gnu-8.3.0-serial_release-debug_shared_no-kokkos-arch_no-asan_no-complex_no-fpic_no-mpi_no-pt_no-rdc_no-uvm_deprecated-on_no-package-enables] #uses sems-archive modules use RHEL7_SEMS_COMPILER|GNU From 33b75da3a083369e1321d2abe56b3a549d9d3cbd Mon Sep 17 00:00:00 2001 From: Sylvain Bernard Date: Mon, 5 Jun 2023 13:02:39 -0600 Subject: [PATCH 55/65] Add float and double options for complex builds --- packages/framework/ini-files/supported-config-flags.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/framework/ini-files/supported-config-flags.ini b/packages/framework/ini-files/supported-config-flags.ini index cf221eae7dd8..ac592227cb21 100644 --- a/packages/framework/ini-files/supported-config-flags.ini +++ b/packages/framework/ini-files/supported-config-flags.ini @@ -209,6 +209,8 @@ use-asan: SELECT_ONE use-complex: SELECT_ONE no-complex complex + complex-float + complex-double # Whether or not to turn on position independent code. use-fpic: SELECT_ONE From c4571a742d0937c08fc6ef8b7589de4c3dcd112e Mon Sep 17 00:00:00 2001 From: Chris Siefert Date: Mon, 12 Jun 2023 13:07:33 -0600 Subject: [PATCH 56/65] Tpetra: Improving std::move()-ability of BlockMultiVector --- .../tpetra/core/test/Block/Issue11931.cpp | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 packages/tpetra/core/test/Block/Issue11931.cpp diff --git a/packages/tpetra/core/test/Block/Issue11931.cpp b/packages/tpetra/core/test/Block/Issue11931.cpp new file mode 100644 index 000000000000..6cc70ccae24c --- /dev/null +++ b/packages/tpetra/core/test/Block/Issue11931.cpp @@ -0,0 +1,112 @@ +/* +// @HEADER +// *********************************************************************** +// +// Tpetra: Templated Linear Algebra Services Package +// Copyright (2008) Sandia Corporation +// +// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, +// the U.S. Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// ************************************************************************ +// @HEADER +*/ + +#include "Tpetra_TestingUtilities.hpp" +#include "Tpetra_BlockVector.hpp" +#include "Tpetra_BlockView.hpp" +#include "Teuchos_SerialDenseMatrix.hpp" +#include "Teuchos_LAPACK.hpp" +#include "Teuchos_TypeNameTraits.hpp" + + +namespace { // anonymous + + using Kokkos::ALL; + using Kokkos::subview; + using Tpetra::TestingUtilities::getDefaultComm; + using Teuchos::Comm; + using Teuchos::outArg; + using Teuchos::RCP; + using Teuchos::REDUCE_MIN; + using Teuchos::reduceAll; + using Teuchos::TypeNameTraits; + using std::endl; + + + TEUCHOS_UNIT_TEST_TEMPLATE_4_DECL( BlockVector, Issue11931, Scalar, LO, GO, Node ) { + // This particular issued exposed the fact that BlockVector did not std::move + // correctly, due to an issue with the internal pointMap + + RCP > comm = Tpetra::getDefaultComm (); + using BV = Tpetra::BlockVector; + using map_t = Tpetra::Map; + + const int numGlobalEntries = 15*comm->getSize(); + RCP Map = Teuchos::rcp(new map_t(numGlobalEntries, 0, comm)); + + + int block_size = 5; + + // To test this, we make a BlockVector, std::move it to a second one + // and then have the first guy go out of scope. + RCP Vec2; + { + BV Vec1 (*Map,block_size); + Vec2 = Teuchos::rcp(new BV(std::move(Vec1))); + } + + Tpetra::global_size_t block_map_size = Vec2->getMap()->getGlobalNumElements(); + Tpetra::global_size_t point_map_size = Vec2->getVectorView().getMap()->getGlobalNumElements(); + TEST_EQUALITY_CONST( block_map_size * block_size, point_map_size ); + + } + + + + + +// +// INSTANTIATIONS +// + +#define UNIT_TEST_GROUP( SCALAR, LO, GO, NODE ) \ + TEUCHOS_UNIT_TEST_TEMPLATE_4_INSTANT( BlockVector, Issue11931, SCALAR, LO, GO, NODE ) + + + TPETRA_ETI_MANGLING_TYPEDEFS() + + TPETRA_INSTANTIATE_SLGN_NO_ORDINAL_SCALAR( UNIT_TEST_GROUP ) + +} // namespace (anonymous) + + From c9e0176488050d4e978d2247c7e42c9cb2f46208 Mon Sep 17 00:00:00 2001 From: Chris Siefert Date: Mon, 12 Jun 2023 13:08:38 -0600 Subject: [PATCH 57/65] Tpetra: Improving std::move()-ability of BlockMultiVector --- .../core/src/Tpetra_BlockMultiVector_decl.hpp | 16 ++++- .../core/src/Tpetra_BlockMultiVector_def.hpp | 69 +++++++++++++++---- .../tpetra/core/test/Block/CMakeLists.txt | 11 +++ 3 files changed, 81 insertions(+), 15 deletions(-) diff --git a/packages/tpetra/core/src/Tpetra_BlockMultiVector_decl.hpp b/packages/tpetra/core/src/Tpetra_BlockMultiVector_decl.hpp index b081c4863388..51543d89a71f 100644 --- a/packages/tpetra/core/src/Tpetra_BlockMultiVector_decl.hpp +++ b/packages/tpetra/core/src/Tpetra_BlockMultiVector_decl.hpp @@ -320,15 +320,25 @@ class BlockMultiVector : /// This is a class ("static") method so that you can make and reuse /// a point Map for creating different BlockMultiVector instances, /// using the more efficient four-argument constructor. + /// static map_type makePointMap (const map_type& meshMap, const LO blockSize); + /// \brief Create and return the point Map corresponding to the + /// given mesh Map and block size. + /// + /// This is a class ("static") method so that you can make and reuse + /// a point Map for creating different BlockMultiVector instances, + /// using the more efficient four-argument constructor. + static Teuchos::RCP + makePointMapRCP (const map_type& meshMap, const LO blockSize); + /// \brief Get this BlockMultiVector's (previously computed) point Map. /// /// It is always valid to call this method. A BlockMultiVector /// always has a point Map. We do not compute the point Map lazily. - map_type getPointMap () const { - return pointMap_; + const map_type getPointMap () const { + return *pointMap_; } //! Get the number of degrees of freedom per mesh point. @@ -619,7 +629,7 @@ class BlockMultiVector : private: //! The point Map (describing the distribution of degrees of freedom). - map_type pointMap_; + Teuchos::RCP pointMap_; protected: //! The Tpetra::MultiVector used to represent the data. diff --git a/packages/tpetra/core/src/Tpetra_BlockMultiVector_def.hpp b/packages/tpetra/core/src/Tpetra_BlockMultiVector_def.hpp index 5f4020a02b98..214ea6720d6a 100644 --- a/packages/tpetra/core/src/Tpetra_BlockMultiVector_def.hpp +++ b/packages/tpetra/core/src/Tpetra_BlockMultiVector_def.hpp @@ -87,8 +87,8 @@ BlockMultiVector (const map_type& meshMap, const LO numVecs) : dist_object_type (Teuchos::rcp (new map_type (meshMap))), // shallow copy meshMap_ (meshMap), - pointMap_ (makePointMap (meshMap, blockSize)), - mv_ (Teuchos::rcpFromRef (pointMap_), numVecs), // nonowning RCP is OK, since pointMap_ won't go away + pointMap_ (makePointMapRCP (meshMap, blockSize)), + mv_ (pointMap_, numVecs), // nonowning RCP is OK, since pointMap_ won't go away blockSize_ (blockSize) {} @@ -100,8 +100,8 @@ BlockMultiVector (const map_type& meshMap, const LO numVecs) : dist_object_type (Teuchos::rcp (new map_type (meshMap))), // shallow copy meshMap_ (meshMap), - pointMap_ (pointMap), - mv_ (Teuchos::rcpFromRef (pointMap_), numVecs), + pointMap_ (new map_type(pointMap)), + mv_ (pointMap_, numVecs), blockSize_ (blockSize) {} @@ -156,9 +156,8 @@ BlockMultiVector (const mv_type& X_mv, // At this point, mv_ has been assigned, so we can ignore X_mv. Teuchos::RCP pointMap = mv_.getMap (); - if (! pointMap.is_null ()) { - pointMap_ = *pointMap; // Map::operator= also does a shallow copy - } + pointMap_ = pointMap; + } template @@ -169,7 +168,7 @@ BlockMultiVector (const BlockMultiVector& X, const size_t offset) : dist_object_type (Teuchos::rcp (new map_type (newMeshMap))), // shallow copy meshMap_ (newMeshMap), - pointMap_ (newPointMap), + pointMap_ (new map_type(newPointMap)), mv_ (X.mv_, newPointMap, offset * X.getBlockSize ()), // MV "offset view" constructor blockSize_ (X.getBlockSize ()) {} @@ -181,7 +180,7 @@ BlockMultiVector (const BlockMultiVector& X, const size_t offset) : dist_object_type (Teuchos::rcp (new map_type (newMeshMap))), // shallow copy meshMap_ (newMeshMap), - pointMap_ (makePointMap (newMeshMap, X.getBlockSize ())), + pointMap_ (makePointMapRCP (newMeshMap, X.getBlockSize ())), mv_ (X.mv_, pointMap_, offset * X.getBlockSize ()), // MV "offset view" constructor blockSize_ (X.getBlockSize ()) {} @@ -198,7 +197,7 @@ typename BlockMultiVector::map_type BlockMultiVector:: makePointMap (const map_type& meshMap, const LO blockSize) { - typedef Tpetra::global_size_t GST; +typedef Tpetra::global_size_t GST; typedef typename Teuchos::ArrayView::size_type size_type; const GST gblNumMeshMapInds = @@ -213,7 +212,7 @@ makePointMap (const map_type& meshMap, const LO blockSize) if (meshMap.isContiguous ()) { return map_type (gblNumPointMapInds, lclNumPointMapInds, indexBase, - meshMap.getComm ()); + meshMap.getComm ()); } else { // "Hilbert's Hotel" trick: multiply each process' GIDs by @@ -233,11 +232,57 @@ makePointMap (const map_type& meshMap, const LO blockSize) } } return map_type (gblNumPointMapInds, lclPointGblInds (), indexBase, - meshMap.getComm ()); + meshMap.getComm ()); + } } +template +Teuchos::RCP::map_type> +BlockMultiVector:: +makePointMapRCP (const map_type& meshMap, const LO blockSize) +{ +typedef Tpetra::global_size_t GST; + typedef typename Teuchos::ArrayView::size_type size_type; + + const GST gblNumMeshMapInds = + static_cast (meshMap.getGlobalNumElements ()); + const size_t lclNumMeshMapIndices = + static_cast (meshMap.getLocalNumElements ()); + const GST gblNumPointMapInds = + gblNumMeshMapInds * static_cast (blockSize); + const size_t lclNumPointMapInds = + lclNumMeshMapIndices * static_cast (blockSize); + const GO indexBase = meshMap.getIndexBase (); + + if (meshMap.isContiguous ()) { + return Teuchos::rcp(new map_type (gblNumPointMapInds, lclNumPointMapInds, indexBase, + meshMap.getComm ())); + } + else { + // "Hilbert's Hotel" trick: multiply each process' GIDs by + // blockSize, and fill in. That ensures correctness even if the + // mesh Map is overlapping. + Teuchos::ArrayView lclMeshGblInds = meshMap.getLocalElementList (); + const size_type lclNumMeshGblInds = lclMeshGblInds.size (); + Teuchos::Array lclPointGblInds (lclNumPointMapInds); + for (size_type g = 0; g < lclNumMeshGblInds; ++g) { + const GO meshGid = lclMeshGblInds[g]; + const GO pointGidStart = indexBase + + (meshGid - indexBase) * static_cast (blockSize); + const size_type offset = g * static_cast (blockSize); + for (LO k = 0; k < blockSize; ++k) { + const GO pointGid = pointGidStart + static_cast (k); + lclPointGblInds[offset + static_cast (k)] = pointGid; + } + } + return Teuchos::rcp(new map_type (gblNumPointMapInds, lclPointGblInds (), indexBase, + meshMap.getComm ())); + + } +} + template void BlockMultiVector:: diff --git a/packages/tpetra/core/test/Block/CMakeLists.txt b/packages/tpetra/core/test/Block/CMakeLists.txt index 64f8bdf29dc2..aeeea6f465d6 100644 --- a/packages/tpetra/core/test/Block/CMakeLists.txt +++ b/packages/tpetra/core/test/Block/CMakeLists.txt @@ -26,6 +26,17 @@ TRIBITS_ADD_EXECUTABLE_AND_TEST( STANDARD_PASS_OUTPUT ) +TRIBITS_ADD_EXECUTABLE_AND_TEST( + Issue11931 + SOURCES + Issue11931.cpp + ${TEUCHOS_STD_UNIT_TEST_MAIN} + COMM serial mpi + STANDARD_PASS_OUTPUT + ) + + + TRIBITS_COPY_FILES_TO_BINARY_DIR(TpetraCore_BlockCrsMatrix_cp SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} SOURCE_FILES blockA.mm blockA-complex.mm From 51e55d800451f051d646b8caa0ba08b59e5f5f51 Mon Sep 17 00:00:00 2001 From: Chris Siefert Date: Mon, 12 Jun 2023 15:07:52 -0600 Subject: [PATCH 58/65] Tpetra: Carl's fixes --- packages/tpetra/core/src/Tpetra_BlockMultiVector_decl.hpp | 2 +- packages/tpetra/core/src/Tpetra_BlockMultiVector_def.hpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/tpetra/core/src/Tpetra_BlockMultiVector_decl.hpp b/packages/tpetra/core/src/Tpetra_BlockMultiVector_decl.hpp index 51543d89a71f..a74c82cae4e4 100644 --- a/packages/tpetra/core/src/Tpetra_BlockMultiVector_decl.hpp +++ b/packages/tpetra/core/src/Tpetra_BlockMultiVector_decl.hpp @@ -324,7 +324,7 @@ class BlockMultiVector : static map_type makePointMap (const map_type& meshMap, const LO blockSize); - /// \brief Create and return the point Map corresponding to the + /// \brief Create and return an owning RCP to the point Map corresponding to the /// given mesh Map and block size. /// /// This is a class ("static") method so that you can make and reuse diff --git a/packages/tpetra/core/src/Tpetra_BlockMultiVector_def.hpp b/packages/tpetra/core/src/Tpetra_BlockMultiVector_def.hpp index 214ea6720d6a..b8e9a2ca90d8 100644 --- a/packages/tpetra/core/src/Tpetra_BlockMultiVector_def.hpp +++ b/packages/tpetra/core/src/Tpetra_BlockMultiVector_def.hpp @@ -212,7 +212,7 @@ typedef Tpetra::global_size_t GST; if (meshMap.isContiguous ()) { return map_type (gblNumPointMapInds, lclNumPointMapInds, indexBase, - meshMap.getComm ()); + meshMap.getComm ()); } else { // "Hilbert's Hotel" trick: multiply each process' GIDs by @@ -232,7 +232,7 @@ typedef Tpetra::global_size_t GST; } } return map_type (gblNumPointMapInds, lclPointGblInds (), indexBase, - meshMap.getComm ()); + meshMap.getComm ()); } } From 73c410ad19e71a9282a54fec5bf7a56df6c3cfe9 Mon Sep 17 00:00:00 2001 From: Christian Glusa Date: Tue, 13 Jun 2023 12:00:41 -0600 Subject: [PATCH 59/65] MueLu RefMaxwell: Accept "aggregation: phase3 avoid singletons" --- packages/muelu/src/Operators/MueLu_RefMaxwell_def.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/muelu/src/Operators/MueLu_RefMaxwell_def.hpp b/packages/muelu/src/Operators/MueLu_RefMaxwell_def.hpp index 2980f4f3155c..92af9eb4cd3f 100644 --- a/packages/muelu/src/Operators/MueLu_RefMaxwell_def.hpp +++ b/packages/muelu/src/Operators/MueLu_RefMaxwell_def.hpp @@ -1227,6 +1227,8 @@ namespace MueLu { UncoupledAggFact->SetParameter("aggregation: max agg size",Teuchos::ParameterEntry(maxAggSize)); bool matchMLbehavior = parameterList_.get("aggregation: match ML phase2a",MasterList::getDefault("aggregation: match ML phase2a")); UncoupledAggFact->SetParameter("aggregation: match ML phase2a",Teuchos::ParameterEntry(matchMLbehavior)); + bool avoidSingletons = parameterList_.get("aggregation: phase3 avoid singletons",MasterList::getDefault("aggregation: phase3 avoid singletons")); + UncoupledAggFact->SetParameter("aggregation: phase3 avoid singletons",Teuchos::ParameterEntry(avoidSingletons)); coarseMapFact->SetFactory("Aggregates", UncoupledAggFact); From 39d54d22cfa82c973eaaa7ffaf82e949ecbbebe8 Mon Sep 17 00:00:00 2001 From: Chris Siefert Date: Tue, 13 Jun 2023 15:25:17 -0600 Subject: [PATCH 60/65] MueLu: Enabling better dumps for Maxwell1 --- packages/muelu/src/MueCentral/MueLu_FactoryManager_def.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/muelu/src/MueCentral/MueLu_FactoryManager_def.hpp b/packages/muelu/src/MueCentral/MueLu_FactoryManager_def.hpp index 8a378475f6ab..8161f0c02635 100644 --- a/packages/muelu/src/MueCentral/MueLu_FactoryManager_def.hpp +++ b/packages/muelu/src/MueCentral/MueLu_FactoryManager_def.hpp @@ -227,6 +227,11 @@ namespace MueLu { if (varName == "pcoarsen: element to node map") return GetFactory("P"); #endif + // FIXME: These are user data, but we might want to print them + if (varName == "NodeMatrix") return NoFactory::getRCP(); + if (varName == "NodeAggMatrix") return NoFactory::getRCP(); + + TEUCHOS_TEST_FOR_EXCEPTION(true, MueLu::Exceptions::RuntimeError, "MueLu::FactoryManager::GetDefaultFactory(): No default factory available for building '" + varName + "'."); } } From 543855cf09df8bfd095e9c71fe3f1e1699bab9ae Mon Sep 17 00:00:00 2001 From: "Roscoe A. Bartlett" Date: Tue, 13 Jun 2023 16:54:20 -0600 Subject: [PATCH 61/65] KokkosKernels: Don't list include for non-existant 'batched' build dir (#11966) See the embedded comment. This fixes the generated KokkosKernelsTargets.cmake file in the build dir when tests are not enabled. NOTE: This is a very non-conventional CMake build system. Your never see CMakeLists.txt files that are included with include(). These should always be pulled in using add_subdirectory(). If you want to just include() some CMake code, you call it `.cmake` and then include() it. --- packages/kokkos-kernels/batched/CMakeLists.txt | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/kokkos-kernels/batched/CMakeLists.txt b/packages/kokkos-kernels/batched/CMakeLists.txt index 2816620e875c..7ab6afb2422c 100644 --- a/packages/kokkos-kernels/batched/CMakeLists.txt +++ b/packages/kokkos-kernels/batched/CMakeLists.txt @@ -16,6 +16,15 @@ IF (NOT KokkosKernels_ENABLE_COMPONENT_BLAS) LIST(APPEND SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/batched/KokkosBatched_Util.cpp) ENDIF() -# Adding unit-tests -KOKKOSKERNELS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/batched) -KOKKOSKERNELS_INCLUDE_DIRECTORIES(REQUIRED_DURING_INSTALLATION_TESTING ${CMAKE_CURRENT_SOURCE_DIR}/batched) +IF(KokkosKernels_ENABLE_TESTS OR KokkosKernels_ENABLE_TESTS_AND_PERFSUITE) + # Adding unit-tests + KOKKOSKERNELS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/batched) + KOKKOSKERNELS_INCLUDE_DIRECTORIES(REQUIRED_DURING_INSTALLATION_TESTING + ${CMAKE_CURRENT_SOURCE_DIR}/batched) +ENDIF() +# NOTE: Above, the build directory 'batched' is not created unless unit tests +# are actually enabled (which are actually included from the base-level +# CMakeLists.txt file). And the KokkosKernelsTargets.cmake file that gets +# generated from this CMake package in the build dir will be broken if these +# are listed in the `INTERFACE_INCLUDE_DIRECTORIES` property when the build +# `batched` is not created (see Trilinos PR #11966). From 6dccc16aa04e2e7d4cd8c370959731f5723d1557 Mon Sep 17 00:00:00 2001 From: Chris Siefert Date: Wed, 14 Jun 2023 08:49:17 -0600 Subject: [PATCH 62/65] Update MueLu_FactoryManager_def.hpp --- packages/muelu/src/MueCentral/MueLu_FactoryManager_def.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/muelu/src/MueCentral/MueLu_FactoryManager_def.hpp b/packages/muelu/src/MueCentral/MueLu_FactoryManager_def.hpp index 8161f0c02635..de8acda5f9c7 100644 --- a/packages/muelu/src/MueCentral/MueLu_FactoryManager_def.hpp +++ b/packages/muelu/src/MueCentral/MueLu_FactoryManager_def.hpp @@ -227,7 +227,7 @@ namespace MueLu { if (varName == "pcoarsen: element to node map") return GetFactory("P"); #endif - // FIXME: These are user data, but we might want to print them + // NOTE: These are user data, but we might want to print them, so they need a default factory if (varName == "NodeMatrix") return NoFactory::getRCP(); if (varName == "NodeAggMatrix") return NoFactory::getRCP(); From d2825e9fd5ad91110952659c3a518687fbbdfe78 Mon Sep 17 00:00:00 2001 From: Samuel Browne Date: Wed, 14 Jun 2023 10:41:38 -0600 Subject: [PATCH 63/65] Add a spec for all packages + complex User Support Ticket(s) or Story Referenced: TRILFRAME-378 --- packages/framework/ini-files/config-specs.ini | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/framework/ini-files/config-specs.ini b/packages/framework/ini-files/config-specs.ini index 826eea7f3918..c1045b5d4d36 100644 --- a/packages/framework/ini-files/config-specs.ini +++ b/packages/framework/ini-files/config-specs.ini @@ -1861,6 +1861,11 @@ opt-set-cmake-var Trilinos_ENABLE_COMPLEX_DOUBLE BOOL FO opt-set-cmake-var Trilinos_ENABLE_FLOAT BOOL FORCE : ON opt-set-cmake-var Trilinos_ENABLE_COMPLEX_FLOAT BOOL FORCE : ON +[rhel7_sems-gnu-8.3.0-openmpi-1.10.1-serial_debug_shared_no-kokkos-arch_no-asan_complex-float_no-fpic_mpi_no-pt_no-rdc_no-uvm_deprecated-on_all] +#uses sems-archive modules +use rhel7_sems-gnu-8.3.0-openmpi-1.10.1-serial_debug_shared_no-kokkos-arch_no-asan_complex-float_no-fpic_mpi_no-pt_no-rdc_no-uvm_deprecated-on_no-package-enables +use PACKAGE-ENABLES|ALL + [rhel7_sems-gnu-8.3.0-serial_release-debug_shared_no-kokkos-arch_no-asan_no-complex_no-fpic_no-mpi_no-pt_no-rdc_no-uvm_deprecated-on_no-package-enables] #uses sems-archive modules use RHEL7_SEMS_COMPILER|GNU From 7c630d7673f35a7ee1648fdefe7826017c30bfcf Mon Sep 17 00:00:00 2001 From: "Roscoe A. Bartlett" Date: Wed, 14 Jun 2023 19:59:33 -0600 Subject: [PATCH 64/65] Make work with missing commonTools/build_stats (#11976) This is also a TriBITS Trilinos package so if it is not enabled, then it gets excluded. I am not sure this is the right thing to do but for now, it fixes the immediate problem reported in #11976. --- CMakeLists.txt | 4 +++- cmake/CallbackSetupExtraOptions.cmake | 13 +++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1837715afd29..9771dbb3b620 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -125,7 +125,9 @@ SET(${PROJECT_NAME}_ENABLE_EXPORT_MAKEFILES OFF CACHE BOOL # Do all of the processing for this Tribits project TRIBITS_PROJECT() -INSTALL_BUILD_STATS_SCRIPTS() +if (COMMAND INSTALL_BUILD_STATS_SCRIPTS) + INSTALL_BUILD_STATS_SCRIPTS() +endif() # Install TriBITS so that other projects can use it. ADVANCED_SET(${PROJECT_NAME}_INSTALL_TriBITS ON CACHE BOOL diff --git a/cmake/CallbackSetupExtraOptions.cmake b/cmake/CallbackSetupExtraOptions.cmake index 445faffd6438..6e908cb6edef 100644 --- a/cmake/CallbackSetupExtraOptions.cmake +++ b/cmake/CallbackSetupExtraOptions.cmake @@ -88,7 +88,12 @@ ENDMACRO() # Set up for build stats # -include("${Trilinos_SOURCE_DIR}/commonTools/build_stats/BuildStatsWrappers.cmake") -generate_build_stats_wrappers() -remove_build_stats_file_on_configure() -remove_build_stats_timing_files_on_fresh_configure() +set(buildStatsWrappersFile + "${Trilinos_SOURCE_DIR}/commonTools/build_stats/BuildStatsWrappers.cmake") +if (EXISTS "${buildStatsWrappersFile}") + include("${Trilinos_SOURCE_DIR}/commonTools/build_stats/BuildStatsWrappers.cmake") + generate_build_stats_wrappers() + remove_build_stats_file_on_configure() + remove_build_stats_timing_files_on_fresh_configure() +endif() + From 40e37d9a19157c4a396db0dadc1148937744228f Mon Sep 17 00:00:00 2001 From: "Roscoe A. Bartlett" Date: Wed, 14 Jun 2023 19:58:06 -0600 Subject: [PATCH 65/65] TriBITS: Temp fix for configuring from reduced tarball (#11976) This is a temp fix the TriBITS that makes building from a reduced tarball work. --- .../TribitsReadDepsFilesCreateDepsGraph.cmake | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/cmake/tribits/core/package_arch/TribitsReadDepsFilesCreateDepsGraph.cmake b/cmake/tribits/core/package_arch/TribitsReadDepsFilesCreateDepsGraph.cmake index 4c193adeff75..0118495e4ea7 100644 --- a/cmake/tribits/core/package_arch/TribitsReadDepsFilesCreateDepsGraph.cmake +++ b/cmake/tribits/core/package_arch/TribitsReadDepsFilesCreateDepsGraph.cmake @@ -182,8 +182,18 @@ macro(tribits_read_all_package_deps_files_create_deps_graph) set(${PROJECT_NAME}_DEFINED_INTERNAL_PACKAGES "") # Packages and subpackages foreach(TRIBITS_PACKAGE IN LISTS ${PROJECT_NAME}_DEFINED_INTERNAL_TOPLEVEL_PACKAGES) - tribits_read_toplevel_package_deps_files_add_to_graph(${TRIBITS_PACKAGE} - ${${TRIBITS_PACKAGE}_REL_SOURCE_DIR}) + set(absPackageSrcDir "${PROJECT_SOURCE_DIR}/${${TRIBITS_PACKAGE}_REL_SOURCE_DIR}") + set(packageDependenciesFile "${absPackageSrcDir}/cmake/Dependencies.cmake") + if ( (NOT EXISTS "${packageDependenciesFile}") + AND (NOT ${PROJECT_NAME}_ASSERT_DEFINED_DEPENDENCIES IN_LIST + ${PROJECT_NAME}_ASSERT_DEFINED_DEPENDENCIES_ERROR_VALUES_LIST) + ) + # ToDo: Print message about the package being missing depending on the + # value of ${PROJECT_NAME}_ASSERT_DEFINED_DEPENDENCIES! + else() + message("${TRIBITS_PACKAGE} package dependency file: '${packageDependenciesFile}' exists!") + tribits_read_toplevel_package_deps_files_add_to_graph(${TRIBITS_PACKAGE}) + endif() endforeach() list(LENGTH ${PROJECT_NAME}_DEFINED_INTERNAL_PACKAGES