.. _program_listing_file_include_parpeamici_hierarchicalOptimization.h: Program Listing for File hierarchicalOptimization.h =================================================== |exhale_lsh| :ref:`Return to documentation for file ` (``include/parpeamici/hierarchicalOptimization.h``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #ifndef HIERARCHICALOPTIMIZATION_H #define HIERARCHICALOPTIMIZATION_H #include #include #include #include #include namespace parpe { enum class ErrorModel { normal }; // TODO logNormal, Laplace class AnalyticalParameterProvider; class AnalyticalParameterHdf5Reader; class HierarchicalOptimizationProblemWrapper; class HierarchicalOptimizationWrapper; class HierarchicalOptimizationWrapper : public GradientFunction { public: HierarchicalOptimizationWrapper( AmiciSummedGradientFunction *wrapped_function, int numConditions = 0, int numObservables = 0); HierarchicalOptimizationWrapper( AmiciSummedGradientFunction *wrapped_function, const H5::H5File& file, const std::string& hdf5RootPath, int numConditions, int numObservables, ErrorModel errorModel); HierarchicalOptimizationWrapper( AmiciSummedGradientFunction *wrapped_function, std::unique_ptr scalingReader, std::unique_ptr offsetReader, std::unique_ptr sigmaReader, int numConditions, int numObservables, ErrorModel errorModel); using GradientFunction::evaluate; FunctionEvaluationStatus evaluate(gsl::span parameters, double& fval, gsl::span gradient, Logger* logger, double* cpuTime) const override; FunctionEvaluationStatus evaluate(gsl::span reducedParameters, double& fval, gsl::span gradient, std::vector& fullParameters, std::vector& fullGradient, Logger* logger, double* cpuTime) const; [[nodiscard]] std::vector getDefaultScalingFactors() const; [[nodiscard]] std::vector getDefaultOffsetParameters() const; [[nodiscard]] std::vector getDefaultSigmaParameters() const; [[nodiscard]] std::tuple>, std::vector>> getUnscaledModelOutputsAndSigmas( const gsl::span reducedParameters, Logger* logger, double* cpuTime) const; [[nodiscard]] std::vector computeAnalyticalScalings( std::vector> const& measurements, std::vector> const& modelOutputsUnscaled) const; void applyOptimalScalings( std::vector const& proportionalityFactors, std::vector>& modelOutputs) const; [[nodiscard]] std::vector computeAnalyticalOffsets( const std::vector>& measurements, std::vector>& modelOutputsUnscaled) const; [[nodiscard]] std::vector computeAnalyticalSigmas( std::vector> const& measurements, const std::vector>& modelOutputsScaled) const; void applyOptimalOffsets( std::vector const& offsetParameters, std::vector>& modelOutputs) const; void fillInAnalyticalSigmas( std::vector>& allSigmas, const std::vector& analyticalSigmas) const; virtual FunctionEvaluationStatus evaluateWithOptimalParameters( std::vector const& fullParameters, std::vector const& sigmas, std::vector> const& measurements, std::vector> const& modelOutputsScaled, std::vector > &fullSigmaMatrices, double& fval, const gsl::span gradient, std::vector& fullGradient, Logger* logger, double* cpuTime) const; [[nodiscard]] int numParameters() const override; [[nodiscard]] int numProportionalityFactors() const; [[nodiscard]] std::vector const& getProportionalityFactorIndices() const; [[nodiscard]] int numOffsetParameters() const; [[nodiscard]] int numSigmaParameters() const; [[nodiscard]] std::vector const& getOffsetParameterIndices() const; [[nodiscard]] std::vector const& getSigmaParameterIndices() const; [[nodiscard]] std::vector getAnalyticalParameterIndices() const; [[nodiscard]] AmiciSummedGradientFunction* getWrappedFunction() const; [[nodiscard]] std::vector getParameterIds() const override; private: void init(); AmiciSummedGradientFunction *wrapped_function_; std::unique_ptr scalingReader; std::unique_ptr offsetReader; std::unique_ptr sigmaReader; std::vector proportionalityFactorIndices; std::vector offsetParameterIndices; std::vector sigmaParameterIndices; int numConditions; int numObservables; ErrorModel errorModel = ErrorModel::normal; }; class HierarchicalOptimizationProblemWrapper : public OptimizationProblem { public: HierarchicalOptimizationProblemWrapper() = default; HierarchicalOptimizationProblemWrapper( std::unique_ptr problemToWrap, const MultiConditionDataProviderHDF5* dataProvider); HierarchicalOptimizationProblemWrapper( std::unique_ptr problemToWrap, std::unique_ptr costFun, std::unique_ptr logger); HierarchicalOptimizationProblemWrapper( HierarchicalOptimizationProblemWrapper const& other) = delete; void fillInitialParameters(gsl::span buffer) const override; void fillParametersMin(gsl::span buffer) const override; void fillParametersMax(gsl::span buffer) const override; void fillFilteredParams(std::vector const& fullParams, gsl::span buffer) const; OptimizationOptions const& getOptimizationOptions() const override { return wrapped_problem_->getOptimizationOptions(); } void setOptimizationOptions(OptimizationOptions const& options) override { wrapped_problem_->setOptimizationOptions(options); } // TODO: need to ensure that this will work with the reduced number of // parameters std::unique_ptr getReporter() const override; private: std::unique_ptr wrapped_problem_; }; class HierarchicalOptimizationReporter : public OptimizationReporter { public: HierarchicalOptimizationReporter( HierarchicalOptimizationWrapper* gradFun, std::unique_ptr rw, std::unique_ptr logger); using GradientFunction::evaluate; FunctionEvaluationStatus evaluate(gsl::span parameters, double& fval, gsl::span gradient, Logger* logger = nullptr, double* cpuTime = nullptr) const override; // bool starting(gsl::span initialParameters) const override; // TODO: always update final parameters bool iterationFinished( gsl::span parameters, double objectiveFunctionValue, gsl::span objectiveFunctionGradient) const override; bool afterCostFunctionCall( gsl::span parameters, double objectiveFunctionValue, gsl::span objectiveFunctionGradient) const override; void finished(double optimalCost, gsl::span parameters, int exitStatus) const override; std::vector const& getFinalParameters() const override; HierarchicalOptimizationWrapper* hierarchical_wrapper_ = nullptr; /* In addition to the vectors for the outer optimization problem, * we also keep the complete ones. */ mutable std::vector cached_full_parameters_; mutable std::vector cached_full_gradient_; // TODO should override other functions as well // TODO: in all functions, we need to check of the provided parameters or // function values match To cached ones, if we want to provide all together // to downstream }; void fillFilteredParams(std::vector const& valuesToFilter, const std::vector& sortedIndicesToExclude, gsl::span result); double getDefaultScalingFactor(amici::ParameterScaling scaling); double getDefaultOffsetParameter(amici::ParameterScaling scaling); double computeAnalyticalScalings( int scalingIdx, const std::vector>& modelOutputsUnscaled, const std::vector>& measurements, const AnalyticalParameterProvider& scalingReader, int numObservables); double computeAnalyticalOffsets( int offsetIdx, const std::vector>& modelOutputsUnscaled, const std::vector>& measurements, AnalyticalParameterProvider& offsetReader, int numObservables); double computeAnalyticalSigmas( int sigmaIdx, const std::vector>& modelOutputsScaled, const std::vector>& measurements, const AnalyticalParameterProvider& sigmaReader, int numObservables, double epsilonAbs = 1e-12, double epsilonRel = 0.01); void applyOptimalScaling(int scalingIdx, double scalingLin, std::vector>& modelOutputs, AnalyticalParameterProvider const& scalingReader, int numObservables); void applyOptimalOffset(int offsetIdx, double offsetLin, std::vector>& modelOutputs, AnalyticalParameterProvider const& offsetReader, int numObservables); std::vector spliceParameters(const gsl::span reducedParameters, const std::vector& proportionalityFactorIndices, const std::vector& offsetParameterIndices, const std::vector& sigmaParameterIndices, const std::vector& scalingFactors, const std::vector& offsetParameters, const std::vector& sigmaParameters); template std::vector removeInnerParameters(const gsl::span allParameters, const std::vector& proportionalityFactorIndices, const std::vector& offsetParameterIndices, const std::vector& sigmaParameterIndices) { std::vector outerParameters( allParameters.size() - proportionalityFactorIndices.size() - offsetParameterIndices.size() - sigmaParameterIndices.size()); int nextOuterIdx = 0; for(int idxFull = 0; idxFull < static_cast(allParameters.size()); ++idxFull) { // skip if current parameter is scaling/offset/sigma if(std::find(proportionalityFactorIndices.begin(), proportionalityFactorIndices.end(), idxFull) != std::end(proportionalityFactorIndices)) continue; if(std::find(offsetParameterIndices.begin(), offsetParameterIndices.end(), idxFull) != std::end(offsetParameterIndices)) continue; if(std::find(sigmaParameterIndices.begin(), sigmaParameterIndices.end(), idxFull) != std::end(sigmaParameterIndices)) continue; // otherwise copy outerParameters[nextOuterIdx] = allParameters[idxFull]; ++nextOuterIdx; } Ensures(nextOuterIdx == static_cast(outerParameters.size())); return outerParameters; } std::vector getOuterParameters(std::vector const& fullParameters, H5::H5File const& parameterFile, std::string const& parameterPath); double computeNegLogLikelihood( std::vector> const& measurements, std::vector> const& modelOutputsScaled, const std::vector>& sigmas); double computeNegLogLikelihood(std::vector const& measurements, std::vector const& modelOutputsScaled, const std::vector& sigmas); void checkGradientForAnalyticalParameters(std::vector const& gradient, std::vector const& analyticalIndices, double threshold); } // namespace parpe #endif // HIERARCHICALOPTIMIZATION_H