From 05b1f284a5dbca083d35f95b628ab42993d2a3c1 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Wed, 15 Nov 2023 10:30:16 -0500 Subject: [PATCH 1/6] Fix callbacks to respect the return values of Evaluate() and other calls. --- .../ensmallen_bits/callbacks/callbacks.hpp | 227 ++++++++++++------ include/ensmallen_bits/callbacks/traits.hpp | 140 ++++++++--- 2 files changed, 254 insertions(+), 113 deletions(-) diff --git a/include/ensmallen_bits/callbacks/callbacks.hpp b/include/ensmallen_bits/callbacks/callbacks.hpp index ee1f89b33..27a14102a 100644 --- a/include/ensmallen_bits/callbacks/callbacks.hpp +++ b/include/ensmallen_bits/callbacks/callbacks.hpp @@ -67,9 +67,7 @@ class Callback typename MatType> static typename std::enable_if< callbacks::traits::HasBeginOptimizationSignature< - // Check for boolean return values anyway, for older ensmallen callbacks. - // (The return value is ignored.) - CallbackType, OptimizerType, FunctionType, MatType>::hasBool, + CallbackType, OptimizerType, FunctionType, MatType>::value, void>::type BeginOptimizationFunction(CallbackType& callback, OptimizerType& optimizer, @@ -85,25 +83,8 @@ class Callback typename FunctionType, typename MatType> static typename std::enable_if< - callbacks::traits::HasBeginOptimizationSignature< - CallbackType, OptimizerType, FunctionType, MatType>::hasVoid, - void>::type - BeginOptimizationFunction(CallbackType& callback, - OptimizerType& optimizer, - FunctionType& function, - MatType& coordinates) - { - const_cast(callback).BeginOptimization(optimizer, function, - coordinates); - } - - template - static typename std::enable_if< - callbacks::traits::HasBeginOptimizationSignature< - CallbackType, OptimizerType, FunctionType, MatType>::hasNone, + !callbacks::traits::HasBeginOptimizationSignature< + CallbackType, OptimizerType, FunctionType, MatType>::value, void>::type BeginOptimizationFunction(CallbackType& /* callback */, OptimizerType& /* optimizer */, @@ -175,7 +156,8 @@ class Callback typename OptimizerType, typename FunctionType, typename MatType> - static typename std::enable_if::value, void>::type EndOptimizationFunction(CallbackType& /* callback */, @@ -234,7 +216,7 @@ class Callback typename FunctionType, typename MatType> static typename std::enable_if::value, + CallbackType, OptimizerType, FunctionType, MatType>::hasBool, bool>::type EvaluateFunction(CallbackType& callback, OptimizerType& optimizer, @@ -242,16 +224,34 @@ class Callback const MatType& coordinates, const double objective) { - return (const_cast(callback).Evaluate( - optimizer, function, coordinates, objective), false); + return const_cast(callback).Evaluate(optimizer, function, + coordinates, objective); } template - static typename std::enable_if::value, + static typename std::enable_if::hasVoid, + bool>::type + EvaluateFunction(CallbackType& callback, + OptimizerType& optimizer, + FunctionType& function, + const MatType& coordinates, + const double objective) + { + const_cast(callback).Evaluate(optimizer, function, + coordinates, objective); + return false; + } + + template + static typename std::enable_if::hasNone, bool>::type EvaluateFunction(CallbackType& /* callback */, OptimizerType& /* optimizer */, @@ -304,7 +304,7 @@ class Callback typename MatType> static typename std::enable_if< callbacks::traits::HasEvaluateConstraintSignature< - CallbackType, OptimizerType, FunctionType, MatType>::value, + CallbackType, OptimizerType, FunctionType, MatType>::hasBool, bool>::type EvaluateConstraintFunction(CallbackType& callback, OptimizerType& optimizer, @@ -313,8 +313,8 @@ class Callback const size_t constraint, const double constraintValue) { - return (const_cast(callback).EvaluateConstraint( - optimizer, function, coordinates, constraint, constraintValue), false); + return const_cast(callback).EvaluateConstraint( + optimizer, function, coordinates, constraint, constraintValue); } template static typename std::enable_if< - !callbacks::traits::HasEvaluateConstraintSignature< - CallbackType, OptimizerType, FunctionType, MatType>::value, + callbacks::traits::HasEvaluateConstraintSignature< + CallbackType, OptimizerType, FunctionType, MatType>::hasVoid, + bool>::type + EvaluateConstraintFunction(CallbackType& callback, + OptimizerType& optimizer, + FunctionType& function, + const MatType& coordinates, + const size_t constraint, + const double constraintValue) + { + const_cast(callback).EvaluateConstraint( + optimizer, function, coordinates, constraint, constraintValue); + return false; + } + + template + static typename std::enable_if< + callbacks::traits::HasEvaluateConstraintSignature< + CallbackType, OptimizerType, FunctionType, MatType>::hasNone, bool>::type EvaluateConstraintFunction(CallbackType& /* callback */, OptimizerType& /* optimizer */, @@ -380,7 +400,7 @@ class Callback typename MatType, typename GradType> static typename std::enable_if::value, + CallbackType, OptimizerType, FunctionType, MatType, GradType>::hasBool, bool>::type GradientFunction(CallbackType& callback, OptimizerType& optimizer, @@ -388,8 +408,8 @@ class Callback const MatType& coordinates, GradType& gradient) { - return (const_cast(callback).Gradient( - optimizer, function, coordinates, gradient), false); + return const_cast(callback).Gradient(optimizer, function, + coordinates, gradient); } template - static typename std::enable_if::value, + static typename std::enable_if::hasVoid, + bool>::type + GradientFunction(CallbackType& callback, + OptimizerType& optimizer, + FunctionType& function, + const MatType& coordinates, + GradType& gradient) + { + const_cast(callback).Gradient( + optimizer, function, coordinates, gradient); + return false; + } + + template + static typename std::enable_if::hasNone, bool>::type GradientFunction(CallbackType& /* callback */, OptimizerType& /* optimizer */, @@ -451,7 +490,27 @@ class Callback typename GradType> static typename std::enable_if< callbacks::traits::HasGradientConstraintSignature< - CallbackType, OptimizerType, FunctionType, MatType, GradType>::value, + CallbackType, OptimizerType, FunctionType, MatType, GradType>::hasBool, + bool>::type + GradientConstraintFunction(CallbackType& callback, + OptimizerType& optimizer, + FunctionType& function, + const MatType& coordinates, + const size_t constraint, + GradType& gradient) + { + return const_cast(callback).GradientConstraint(optimizer, + function, coordinates, constraint, gradient); + } + + template + static typename std::enable_if< + callbacks::traits::HasGradientConstraintSignature< + CallbackType, OptimizerType, FunctionType, MatType, GradType>::hasVoid, bool>::type GradientConstraintFunction(CallbackType& callback, OptimizerType& optimizer, @@ -460,8 +519,9 @@ class Callback const size_t constraint, GradType& gradient) { - return (const_cast(callback).GradientConstraint( - optimizer, function, coordinates, constraint, gradient), false); + const_cast(callback).GradientConstraint( + optimizer, function, coordinates, constraint, gradient); + return false; } template static typename std::enable_if< - !callbacks::traits::HasGradientConstraintSignature< - CallbackType, OptimizerType, FunctionType, MatType, GradType>::value, + callbacks::traits::HasGradientConstraintSignature< + CallbackType, OptimizerType, FunctionType, MatType, GradType>::hasNone, bool>::type GradientConstraintFunction(CallbackType& /* callback */, OptimizerType& /* optimizer */, @@ -563,7 +623,24 @@ class Callback typename FunctionType, typename MatType> static typename std::enable_if::value, bool>::type + CallbackType, OptimizerType, FunctionType, MatType>::hasBool, bool>::type + BeginEpochFunction(CallbackType& callback, + OptimizerType& optimizer, + FunctionType& function, + const MatType& coordinates, + const size_t epoch, + const double objective) + { + return const_cast(callback).BeginEpoch( + optimizer, function, coordinates, epoch, objective); + } + + template + static typename std::enable_if::hasVoid, bool>::type BeginEpochFunction(CallbackType& callback, OptimizerType& optimizer, FunctionType& function, @@ -571,16 +648,17 @@ class Callback const size_t epoch, const double objective) { - return (const_cast(callback).BeginEpoch( - optimizer, function, coordinates, epoch, objective), false); + const_cast(callback).BeginEpoch( + optimizer, function, coordinates, epoch, objective); + return false; } template - static typename std::enable_if::value, bool>::type + static typename std::enable_if::hasNone, bool>::type BeginEpochFunction(CallbackType& /* callback */, OptimizerType& /* optimizer */, FunctionType& /* function */, @@ -768,6 +846,32 @@ class Callback MatType& /* coordinates */) { return false; } + /** + * Iterate over the callbacks and invoke the StepTaken() callback if it + * exists. + * + * @param optimizer The optimizer used to update the function. + * @param function Function to optimize. + * @param coordinates Starting point. + * @param callbacks The callbacks container. + */ + template + static bool StepTaken(OptimizerType& optimizer, + FunctionType& function, + MatType& coordinates, + CallbackTypes&... callbacks) + { + // This will return immediately once a callback returns true. + bool result = false; + (void)std::initializer_list{ result = + result || Callback::StepTakenFunction(callbacks, optimizer, + function, coordinates)... }; + return result; + } + /** * Invoke the GenerationalStepTaken() callback if it exists. * Specialization for MultiObjective case. @@ -819,7 +923,6 @@ class Callback { const_cast(callback).GenerationalStepTaken( optimizer, function, coordinates, objectives, frontIndices); - return false; } @@ -841,32 +944,6 @@ class Callback IndicesType& /* frontIndices */) { return false; } - /** - * Iterate over the callbacks and invoke the StepTaken() callback if it - * exists. - * - * @param optimizer The optimizer used to update the function. - * @param function Function to optimize. - * @param coordinates Starting point. - * @param callbacks The callbacks container. - */ - template - static bool StepTaken(OptimizerType& optimizer, - FunctionType& function, - MatType& coordinates, - CallbackTypes&... callbacks) - { - // This will return immediately once a callback returns true. - bool result = false; - (void)std::initializer_list{ result = - result || Callback::StepTakenFunction(callbacks, optimizer, - function, coordinates)... }; - return result; - } - /** * Iterate over the callbacks and invoke the GenerationalStepTaken() callback if it * exists. diff --git a/include/ensmallen_bits/callbacks/traits.hpp b/include/ensmallen_bits/callbacks/traits.hpp index 0d226116d..03188be56 100644 --- a/include/ensmallen_bits/callbacks/traits.hpp +++ b/include/ensmallen_bits/callbacks/traits.hpp @@ -239,23 +239,11 @@ template struct HasBeginOptimizationSignature { - const static bool hasBool = + const static bool value = HasBeginOptimization::template BeginOptimizationBoolForm>::value && - !HasBeginOptimization::template BeginOptimizationVoidForm>::value; - - const static bool hasVoid = - !HasBeginOptimization::template BeginOptimizationBoolForm>::value && + FunctionType, MatType>::template BeginOptimizationBoolForm>::value || HasBeginOptimization::template BeginOptimizationVoidForm>::value; - - const static bool hasNone = - !HasBeginOptimization::template BeginOptimizationBoolForm>::value && - !HasBeginOptimization::template BeginOptimizationVoidForm>::value; + FunctionType, MatType>::template BeginOptimizationVoidForm>::value; }; //! Utility struct, check if either void Evaluate() or bool Evaluate() @@ -266,11 +254,23 @@ template struct HasEvaluateSignature { - const static bool value = + const static bool hasBool = HasEvaluate::template EvaluateBoolForm>::value || + FunctionType, MatType>::template EvaluateBoolForm>::value && + !HasEvaluate::template EvaluateVoidForm>::value; + + const static bool hasVoid = + !HasEvaluate::template EvaluateBoolForm>::value && HasEvaluate::template EvaluateVoidForm>::value; + + const static bool hasNone = + !HasEvaluate::template EvaluateBoolForm>::value && + !HasEvaluate::template EvaluateVoidForm>::value; }; //! Utility struct, check if either void EvaluateConstraint() or @@ -281,11 +281,23 @@ template struct HasEvaluateConstraintSignature { - const static bool value = + const static bool hasBool = HasEvaluateConstraint::template EvaluateConstraintBoolForm>::value || + FunctionType, MatType>::template EvaluateConstraintBoolForm>::value && + !HasEvaluateConstraint::template EvaluateConstraintVoidForm>::value; + + const static bool hasVoid = + !HasEvaluateConstraint::template EvaluateConstraintBoolForm>::value && HasEvaluateConstraint::template EvaluateConstraintVoidForm>::value; + + const static bool hasNone = + !HasEvaluateConstraint::template EvaluateConstraintBoolForm>::value && + !HasEvaluateConstraint::template EvaluateConstraintVoidForm>::value; }; //! Utility struct, check if either void Gradient() or bool Gradient() @@ -297,17 +309,41 @@ template struct HasGradientSignature { - const static bool value = - HasGradient::template GradientBoolForm>::value || HasGradient::template GradientBoolModifiableForm>::value || - HasGradient::template + GradientBoolModifiableForm>::value) && + (!HasGradient::template GradientVoidForm>::value || + !HasGradient::template + GradientVoidModifiableForm>::value); + + const static bool hasVoid = + (!HasGradient::template GradientBoolForm>::value || + !HasGradient::template + GradientBoolModifiableForm>::value) && + (HasGradient::template GradientVoidForm>::value || HasGradient::template GradientVoidModifiableForm>::value; + FunctionType, MatType, Gradient>::template + GradientVoidModifiableForm>::value); + + const static bool hasNone = + !HasGradient::template GradientBoolForm>::value && + !HasGradient::template + GradientBoolModifiableForm>::value && + !HasGradient::template GradientVoidForm>::value && + !HasGradient::template + GradientVoidModifiableForm>::value; }; //! Utility struct, check if either void GradientConstraint() or @@ -319,13 +355,29 @@ template struct HasGradientConstraintSignature { - const static bool value = + const static bool hasBool = HasGradientConstraint::template GradientConstraintBoolForm>::value || + FunctionType, MatType, Gradient>::template + GradientConstraintBoolForm>::value && + !HasGradientConstraint::template + GradientConstraintVoidForm>::value; + + const static bool hasVoid = + !HasGradientConstraint::template + GradientConstraintBoolForm>::value && HasGradientConstraint::template GradientConstraintVoidForm>::value; + FunctionType, MatType, Gradient>::template + GradientConstraintVoidForm>::value; + + const static bool hasNone = + !HasGradientConstraint::template + GradientConstraintBoolForm>::value && + !HasGradientConstraint::template + GradientConstraintVoidForm>::value; }; //! Utility struct, check if either void EndOptimization() or @@ -338,9 +390,9 @@ struct HasEndOptimizationSignature { const static bool value = HasEndOptimization::template EndOptimizationBoolForm>::value || + FunctionType, MatType>::template EndOptimizationBoolForm>::value || HasEndOptimization::template EndOptimizationVoidForm>::value; + FunctionType, MatType>::template EndOptimizationVoidForm>::value; }; //! Utility struct, check if either void BeginEpoch() or bool BeginEpoch() @@ -351,11 +403,23 @@ template struct HasBeginEpochSignature { - const static bool value = + const static bool hasBool = HasBeginEpoch::template BeginEpochBoolForm>::value || + FunctionType, MatType>::template BeginEpochBoolForm>::value && + !HasBeginEpoch::template BeginEpochVoidForm>::value; + + const static bool hasVoid = + !HasBeginEpoch::template BeginEpochBoolForm>::value && HasBeginEpoch::template BeginEpochVoidForm>::value; + FunctionType, MatType>::template BeginEpochVoidForm>::value; + + const static bool hasNone = + !HasBeginEpoch::template BeginEpochBoolForm>::value && + !HasBeginEpoch::template BeginEpochVoidForm>::value; }; //! Utility struct, check if either void EndEpoch() or bool EndEpoch() @@ -402,13 +466,13 @@ struct HasStepTakenSignature !HasStepTaken::template StepTakenBoolForm>::value && HasStepTaken::template StepTakenVoidForm>::value; + FunctionType, MatType>::template StepTakenVoidForm>::value; const static bool hasNone = !HasStepTaken::template StepTakenBoolForm>::value && !HasStepTaken::template StepTakenVoidForm>::value; + FunctionType, MatType>::template StepTakenVoidForm>::value; }; //! A utility struct for Typed Forms required in From 74beb984f2d723905103ef983d80b97bcde0ddd6 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Wed, 15 Nov 2023 10:30:35 -0500 Subject: [PATCH 2/6] Adapt all callbacks to return bools instead of void. --- .../callbacks/early_stop_at_min_loss.hpp | 15 ++-- .../callbacks/grad_clip_by_norm.hpp | 3 +- .../callbacks/grad_clip_by_value.hpp | 3 +- .../ensmallen_bits/callbacks/print_loss.hpp | 3 +- .../ensmallen_bits/callbacks/progress_bar.hpp | 14 +++- .../ensmallen_bits/callbacks/query_front.hpp | 80 ++++++++++--------- include/ensmallen_bits/callbacks/report.hpp | 21 +++-- .../callbacks/store_best_coordinates.hpp | 3 +- 8 files changed, 82 insertions(+), 60 deletions(-) diff --git a/include/ensmallen_bits/callbacks/early_stop_at_min_loss.hpp b/include/ensmallen_bits/callbacks/early_stop_at_min_loss.hpp index d0ecf1eb2..dd1c82d0e 100644 --- a/include/ensmallen_bits/callbacks/early_stop_at_min_loss.hpp +++ b/include/ensmallen_bits/callbacks/early_stop_at_min_loss.hpp @@ -33,8 +33,8 @@ class EarlyStopAtMinLossType * been reached or no improvement has been made (Default: 10). */ EarlyStopAtMinLossType(const size_t patienceIn = 10) : - callbackUsed(false), - patience(patienceIn), + callbackUsed(false), + patience(patienceIn), bestObjective(std::numeric_limits::max()), steps(0) { /* Nothing to do here */ } @@ -50,10 +50,10 @@ class EarlyStopAtMinLossType EarlyStopAtMinLossType( std::function func, const size_t patienceIn = 10) - : callbackUsed(true), - patience(patienceIn), + : callbackUsed(true), + patience(patienceIn), bestObjective(std::numeric_limits::max()), - steps(0), + steps(0), localFunc(func) { // Nothing to do here @@ -78,7 +78,7 @@ class EarlyStopAtMinLossType if (callbackUsed) { objective = localFunc(coordinates); - } + } if (objective < bestObjective) { @@ -98,7 +98,8 @@ class EarlyStopAtMinLossType } private: - //! False if the first constructor is called, true if the user passed a lambda. + //! False if the first constructor is called, true if the user passed a + //! lambda. bool callbackUsed; //! The number of epochs to wait before terminating the optimization process. diff --git a/include/ensmallen_bits/callbacks/grad_clip_by_norm.hpp b/include/ensmallen_bits/callbacks/grad_clip_by_norm.hpp index 4ead4fa63..a1ea3886e 100644 --- a/include/ensmallen_bits/callbacks/grad_clip_by_norm.hpp +++ b/include/ensmallen_bits/callbacks/grad_clip_by_norm.hpp @@ -40,7 +40,7 @@ class GradClipByNorm * @param gradient Matrix that holds the gradient. */ template - void Gradient(OptimizerType& /* optimizer */, + bool Gradient(OptimizerType& /* optimizer */, FunctionType& /* function */, const MatType& /* coordinates */, MatType& gradient) @@ -48,6 +48,7 @@ class GradClipByNorm const double gradientNorm = arma::norm(gradient); if (gradientNorm > maxNorm) gradient = maxNorm * gradient / gradientNorm; + return false; } private: diff --git a/include/ensmallen_bits/callbacks/grad_clip_by_value.hpp b/include/ensmallen_bits/callbacks/grad_clip_by_value.hpp index 06d3f0cb5..86c9b4b10 100644 --- a/include/ensmallen_bits/callbacks/grad_clip_by_value.hpp +++ b/include/ensmallen_bits/callbacks/grad_clip_by_value.hpp @@ -39,12 +39,13 @@ class GradClipByValue * @param gradient Matrix that holds the gradient. */ template - void Gradient(OptimizerType& /* optimizer */, + bool Gradient(OptimizerType& /* optimizer */, FunctionType& /* function */, const MatType& /* coordinates */, MatType& gradient) { gradient = arma::clamp(gradient, lower, upper); + return false; } private: diff --git a/include/ensmallen_bits/callbacks/print_loss.hpp b/include/ensmallen_bits/callbacks/print_loss.hpp index f1803c584..bc21b90ba 100644 --- a/include/ensmallen_bits/callbacks/print_loss.hpp +++ b/include/ensmallen_bits/callbacks/print_loss.hpp @@ -38,13 +38,14 @@ class PrintLoss * @param objective Objective value of the current point. */ template - void EndEpoch(OptimizerType& /* optimizer */, + bool EndEpoch(OptimizerType& /* optimizer */, FunctionType& /* function */, const MatType& /* coordinates */, const size_t /* epoch */, const double objective) { output << objective << std::endl; + return false; } private: diff --git a/include/ensmallen_bits/callbacks/progress_bar.hpp b/include/ensmallen_bits/callbacks/progress_bar.hpp index 6732a6962..414ad70c7 100644 --- a/include/ensmallen_bits/callbacks/progress_bar.hpp +++ b/include/ensmallen_bits/callbacks/progress_bar.hpp @@ -98,7 +98,7 @@ class ProgressBar * @param objective Objective value of the current point. */ template - void BeginEpoch(OptimizerType& /* optimizer */, + bool BeginEpoch(OptimizerType& /* optimizer */, FunctionType& /* function */, const MatType& /* coordinates */, const size_t epochIn, @@ -113,6 +113,8 @@ class ProgressBar epoch = epochIn; newEpoch = true; + + return false; } /** @@ -124,7 +126,7 @@ class ProgressBar * @param objective Objective value of the current point. */ template - void StepTaken(OptimizerType& /* optimizer */, + bool StepTaken(OptimizerType& /* optimizer */, FunctionType& /* function */, const MatType& /* coordinates */) { @@ -163,6 +165,8 @@ class ProgressBar output.flush(); stepTimer.tic(); + + return false; } /** @@ -174,13 +178,14 @@ class ProgressBar * @param objectiveIn Objective value of the current point. */ template - void Evaluate(OptimizerType& optimizer, + bool Evaluate(OptimizerType& optimizer, FunctionType& /* function */, const MatType& /* coordinates */, const double objectiveIn) { objective += objectiveIn / optimizer.BatchSize(); steps++; + return false; } /** @@ -193,7 +198,7 @@ class ProgressBar * @param objective Objective value of the current point. */ template - void EndEpoch(OptimizerType& /* optimizer */, + bool EndEpoch(OptimizerType& /* optimizer */, FunctionType& /* function */, const MatType& /* coordinates */, const size_t /* epoch */, @@ -221,6 +226,7 @@ class ProgressBar output << "] " << progress << "% - " << epochTimerElapsed << "s/epoch; " << stepTime << "ms/step; loss: " << objective << "\n"; output.flush(); + return false; } private: diff --git a/include/ensmallen_bits/callbacks/query_front.hpp b/include/ensmallen_bits/callbacks/query_front.hpp index 7ca875052..9d5631827 100644 --- a/include/ensmallen_bits/callbacks/query_front.hpp +++ b/include/ensmallen_bits/callbacks/query_front.hpp @@ -24,52 +24,56 @@ class QueryFront * Set up the query front callback class with the specified inputs. * * @param queryRate The frequency at which the Pareto Front is queried. - * @param paretoFrontArray A reference to a vector of cube to store the queried fronts. + * @param paretoFrontArray A reference to a vector of cube to store the + * queried fronts. */ - QueryFront(const size_t queryRate, std::vector& paretoFrontArray) : - queryRate(queryRate), - paretoFrontArray(paretoFrontArray), - genCounter(0) - { /* Nothing to do here */ } + QueryFront(const size_t queryRate, + std::vector& paretoFrontArray) : + queryRate(queryRate), + paretoFrontArray(paretoFrontArray), + genCounter(0) + { /* Nothing to do here */ } - /** - * Callback function called at the end of a single generational run. - * - * @param optimizer The optimizer used to update the function. - * @param function Function to optimize. - * @param coordinates Starting point. - * @param objectives The set of calculated objectives so far. - * @param frontIndices The indices of the members belonging to Pareto Front. - */ - template - void GenerationalStepTaken(OptimizerType& opt, - FunctionType& /* function */, - const MatType& /* coordinates */, - const ObjectivesVecType& objectives, - const IndicesType& frontIndices) - { - arma::cube currentParetoFront{}; + /** + * Callback function called at the end of a single generational run. + * + * @param optimizer The optimizer used to update the function. + * @param function Function to optimize. + * @param coordinates Starting point. + * @param objectives The set of calculated objectives so far. + * @param frontIndices The indices of the members belonging to Pareto Front. + */ + template + bool GenerationalStepTaken(OptimizerType& opt, + FunctionType& /* function */, + const MatType& /* coordinates */, + const ObjectivesVecType& objectives, + const IndicesType& frontIndices) + { + arma::cube currentParetoFront{}; - if (genCounter % queryRate == 0) + if (genCounter % queryRate == 0) + { + currentParetoFront.resize(objectives[0].n_rows, objectives[0].n_cols, + frontIndices[0].size()); + for (size_t solutionIdx = 0; solutionIdx < frontIndices[0].size(); + ++solutionIdx) { - currentParetoFront.resize(objectives[0].n_rows, objectives[0].n_cols, - frontIndices[0].size()); - for (size_t solutionIdx = 0; solutionIdx < frontIndices[0].size(); ++solutionIdx) - { - currentParetoFront.slice(solutionIdx) = - arma::conv_to::from(objectives[frontIndices[0][solutionIdx]]); - } - - paretoFrontArray.emplace_back(std::move(currentParetoFront)); + currentParetoFront.slice(solutionIdx) = arma::conv_to::from( + objectives[frontIndices[0][solutionIdx]]); } - ++genCounter; + paretoFrontArray.emplace_back(std::move(currentParetoFront)); } + ++genCounter; + return false; + } + private: //! The rate of query. diff --git a/include/ensmallen_bits/callbacks/report.hpp b/include/ensmallen_bits/callbacks/report.hpp index ad58eb48a..8bd7848ea 100644 --- a/include/ensmallen_bits/callbacks/report.hpp +++ b/include/ensmallen_bits/callbacks/report.hpp @@ -239,13 +239,14 @@ class Report * @param objective Objective value of the current point. */ template - void BeginEpoch(OptimizerType& /* optimizer */, + bool BeginEpoch(OptimizerType& /* optimizer */, FunctionType& /* function */, const MatType& /* coordinates */, const size_t /* epoch */, const double /* objective */) { epochCalls++; + return false; } /** @@ -258,7 +259,7 @@ class Report * @param objective Objective value of the current point. */ template - void EndEpoch(OptimizerType& optimizer, + bool EndEpoch(OptimizerType& optimizer, FunctionType& /* function */, const MatType& /* coordinates */, const size_t /* epoch */, @@ -282,6 +283,7 @@ class Report gradientsNorm.push_back(gradientNorm); SaveStepSize(optimizer); + return false; } /** @@ -293,7 +295,7 @@ class Report * @param objective Objective value of the current point. */ template - void StepTaken(OptimizerType& optimizer, + bool StepTaken(OptimizerType& optimizer, FunctionType& /* function */, const MatType& /* coordinates */) { @@ -307,6 +309,7 @@ class Report SaveStepSize(optimizer); } + return false; } /** @@ -318,13 +321,14 @@ class Report * @param objectiveIn Objective value of the current point. */ template - void Evaluate(OptimizerType& /* optimizer */, + bool Evaluate(OptimizerType& /* optimizer */, FunctionType& /* function */, const MatType& /* coordinates */, const double objectiveIn) { objective = objectiveIn; evaluateCalls++; + return false; } /** @@ -337,7 +341,7 @@ class Report * @param objectiveIn Objective value of the current point. */ template - void EvaluateConstraint(OptimizerType& /* optimizer */, + bool EvaluateConstraint(OptimizerType& /* optimizer */, FunctionType& /* function */, const MatType& /* coordinates */, const size_t /* constraint */, @@ -345,6 +349,7 @@ class Report { objective += objectiveIn; evaluateCalls++; + return false; } /** @@ -356,7 +361,7 @@ class Report * @param gradientIn Matrix that holds the gradient. */ template - void Gradient(OptimizerType& /* optimizer */, + bool Gradient(OptimizerType& /* optimizer */, FunctionType& /* function */, const MatType& /* coordinates */, const MatType& gradientIn) @@ -364,6 +369,7 @@ class Report hasGradient = true; gradientNorm = arma::norm(gradientIn); gradientCalls++; + return false; } /** @@ -376,13 +382,14 @@ class Report * @param gradient Matrix that holds the gradient; */ template - void GradientConstraint(OptimizerType& optimizer, + bool GradientConstraint(OptimizerType& optimizer, FunctionType& function, const MatType& coordinates, const size_t /* constraint */, const MatType& gradient) { Gradient(optimizer, function, coordinates, gradient); + return false; } private: diff --git a/include/ensmallen_bits/callbacks/store_best_coordinates.hpp b/include/ensmallen_bits/callbacks/store_best_coordinates.hpp index 9353b9aef..4b97b0f4e 100644 --- a/include/ensmallen_bits/callbacks/store_best_coordinates.hpp +++ b/include/ensmallen_bits/callbacks/store_best_coordinates.hpp @@ -40,7 +40,7 @@ class StoreBestCoordinates * @param objective Objective value of the current point. */ template - void Evaluate(OptimizerType& /* optimizer */, + bool Evaluate(OptimizerType& /* optimizer */, FunctionType& /* function */, const MatType& coordinates, const double objective) @@ -50,6 +50,7 @@ class StoreBestCoordinates bestObjective = objective; bestCoordinates = coordinates; } + return false; } //! Get the best coordinates. From e21a3c57ae66ffb9747af271047bb2d7ee816934 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Thu, 23 Nov 2023 13:00:10 -0500 Subject: [PATCH 3/6] Use constexpr instead of const. --- include/ensmallen_bits/callbacks/traits.hpp | 52 ++++++++++----------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/include/ensmallen_bits/callbacks/traits.hpp b/include/ensmallen_bits/callbacks/traits.hpp index 03188be56..5ffd6eb8d 100644 --- a/include/ensmallen_bits/callbacks/traits.hpp +++ b/include/ensmallen_bits/callbacks/traits.hpp @@ -239,7 +239,7 @@ template struct HasBeginOptimizationSignature { - const static bool value = + constexpr static bool value = HasBeginOptimization::template BeginOptimizationBoolForm>::value || HasBeginOptimization struct HasEvaluateSignature { - const static bool hasBool = + constexpr static bool hasBool = HasEvaluate::template EvaluateBoolForm>::value && !HasEvaluate::template EvaluateVoidForm>::value; - const static bool hasVoid = + constexpr static bool hasVoid = !HasEvaluate::template EvaluateBoolForm>::value && HasEvaluate::template EvaluateVoidForm>::value; - const static bool hasNone = + constexpr static bool hasNone = !HasEvaluate::template EvaluateBoolForm>::value && !HasEvaluate struct HasEvaluateConstraintSignature { - const static bool hasBool = + constexpr static bool hasBool = HasEvaluateConstraint::template EvaluateConstraintBoolForm>::value && !HasEvaluateConstraint::template EvaluateConstraintVoidForm>::value; - const static bool hasVoid = + constexpr static bool hasVoid = !HasEvaluateConstraint::template EvaluateConstraintBoolForm>::value && HasEvaluateConstraint::template EvaluateConstraintVoidForm>::value; - const static bool hasNone = + constexpr static bool hasNone = !HasEvaluateConstraint::template EvaluateConstraintBoolForm>::value && !HasEvaluateConstraint struct HasGradientSignature { - const static bool hasBool = + constexpr static bool hasBool = (HasGradient::template GradientBoolForm>::value || HasGradient::template GradientVoidModifiableForm>::value); - const static bool hasVoid = + constexpr static bool hasVoid = (!HasGradient::template GradientBoolForm>::value || !HasGradient::template GradientVoidModifiableForm>::value); - const static bool hasNone = + constexpr static bool hasNone = !HasGradient::template GradientBoolForm>::value && !HasGradient struct HasGradientConstraintSignature { - const static bool hasBool = + constexpr static bool hasBool = HasGradientConstraint::template GradientConstraintBoolForm>::value && @@ -363,7 +363,7 @@ struct HasGradientConstraintSignature FunctionType, MatType, Gradient>::template GradientConstraintVoidForm>::value; - const static bool hasVoid = + constexpr static bool hasVoid = !HasGradientConstraint::template GradientConstraintBoolForm>::value && @@ -371,7 +371,7 @@ struct HasGradientConstraintSignature FunctionType, MatType, Gradient>::template GradientConstraintVoidForm>::value; - const static bool hasNone = + constexpr static bool hasNone = !HasGradientConstraint::template GradientConstraintBoolForm>::value && @@ -388,7 +388,7 @@ template struct HasEndOptimizationSignature { - const static bool value = + constexpr static bool value = HasEndOptimization::template EndOptimizationBoolForm>::value || HasEndOptimization struct HasBeginEpochSignature { - const static bool hasBool = + constexpr static bool hasBool = HasBeginEpoch::template BeginEpochBoolForm>::value && !HasBeginEpoch::template BeginEpochVoidForm>::value; - const static bool hasVoid = + constexpr static bool hasVoid = !HasBeginEpoch::template BeginEpochBoolForm>::value && HasBeginEpoch::template BeginEpochVoidForm>::value; - const static bool hasNone = + constexpr static bool hasNone = !HasBeginEpoch::template BeginEpochBoolForm>::value && !HasBeginEpoch struct HasEndEpochSignature { - const static bool hasBool = + constexpr static bool hasBool = HasEndEpoch::template EndEpochBoolForm>::value && !HasEndEpoch::template EndEpochVoidForm>::value; - const static bool hasVoid = + constexpr static bool hasVoid = !HasEndEpoch::template EndEpochBoolForm>::value && HasEndEpoch::template EndEpochVoidForm>::value; - const static bool hasNone = + constexpr static bool hasNone = !HasEndEpoch::template EndEpochBoolForm>::value && !HasEndEpoch struct HasStepTakenSignature { - const static bool hasBool = + constexpr static bool hasBool = HasStepTaken::template StepTakenBoolForm>::value && !HasStepTaken::template StepTakenVoidForm>::value; - const static bool hasVoid = + constexpr static bool hasVoid = !HasStepTaken::template StepTakenBoolForm>::value && HasStepTaken::template StepTakenVoidForm>::value; - const static bool hasNone = + constexpr static bool hasNone = !HasStepTaken::template StepTakenBoolForm>::value && !HasStepTaken struct HasGenerationalStepTakenSignature { - const static bool hasBool = + constexpr static bool hasBool = HasGenerationalStepTaken:: template GenerationalStepTakenBoolForm>::value && @@ -522,7 +522,7 @@ template:: template GenerationalStepTakenVoidForm>::value; - const static bool hasVoid = + constexpr static bool hasVoid = !HasGenerationalStepTaken:: template GenerationalStepTakenBoolForm>::value && @@ -530,7 +530,7 @@ template:: template GenerationalStepTakenVoidForm>::value; - const static bool hasNone = + constexpr static bool hasNone = !HasGenerationalStepTaken:: template GenerationalStepTakenBoolForm>::value && From 7c8491fa9b8d9a4dbd34b7026f37f77d0e420bac Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Thu, 23 Nov 2023 23:49:57 -0500 Subject: [PATCH 4/6] Fix static code analysis issue for static functions. --- tests/cd_test.cpp | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/tests/cd_test.cpp b/tests/cd_test.cpp index 1e83a47d0..222f5c6eb 100644 --- a/tests/cd_test.cpp +++ b/tests/cd_test.cpp @@ -87,19 +87,17 @@ TEST_CASE("GreedyDescentTest", "[CDTest]") SparseTestFunction f; - GreedyDescent descentPolicy; - - REQUIRE(descentPolicy.DescentFeature(0, point, f) == 2); + REQUIRE(GreedyDescent::DescentFeature(0, point, f) == 2); // Changing the point under consideration, so that the maximum gradient is at // index 1. point(1) = 10; - REQUIRE(descentPolicy.DescentFeature(0, point, f) == 1); + REQUIRE(GreedyDescent::DescentFeature(0, point, f) == 1); } /** @@ -118,11 +116,9 @@ TEST_CASE("CyclicDescentTest", "[CDTest]") DummyFunction dummy; - CyclicDescent descentPolicy; - for (size_t i = 0; i < 15; ++i) { - REQUIRE(descentPolicy.DescentFeature( + REQUIRE(CyclicDescent::DescentFeature( i, arma::mat(), dummy) == (i % features)); } } @@ -143,13 +139,11 @@ TEST_CASE("RandomDescentTest", "[CDTest]") DummyFunction dummy; - CyclicDescent descentPolicy; - for (size_t i = 0; i < 100; ++i) { - size_t j = descentPolicy.DescentFeature(i, arma::mat(), dummy); + size_t j = CyclicDescent::DescentFeature(i, arma::mat(), dummy); REQUIRE(j < features); REQUIRE(j >= 0); } From 666b47db4d4669d5ae5d384ba34996a74119b8ef Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Fri, 24 Nov 2023 09:17:19 -0500 Subject: [PATCH 5/6] Upgrade Visual Studio images to try and fix Windows build. --- .appveyor.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index c8df0bd71..2651ad762 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -4,10 +4,6 @@ environment: BLAS_LIBRARY_DLL: "%APPVEYOR_BUILD_FOLDER%/OpenBLAS.0.2.14.1/lib/native/lib/x64/libopenblas.dll" matrix: - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - VSVER: Visual Studio 14 2015 Win64 - MSBUILD: C:\Program Files (x86)\MSBuild\14.0\bin\MSBuild.exe - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 VSVER: Visual Studio 15 2017 Win64 MSBUILD: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\MSBuild.exe @@ -16,6 +12,10 @@ environment: VSVER: Visual Studio 16 2019 MSBUILD: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 + VSVER: Visual Studio 17 2022 + MSBUILD: C:\Program Files (x86)\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe + configuration: Release install: From d361b86b7d1e421e69cd9a16498d56c799e74cf8 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Fri, 24 Nov 2023 10:36:09 -0500 Subject: [PATCH 6/6] Another guess at MSBuild.exe location. --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index 2651ad762..3dc36bb3c 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -14,7 +14,7 @@ environment: - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 VSVER: Visual Studio 17 2022 - MSBUILD: C:\Program Files (x86)\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe + MSBUILD: C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe configuration: Release