File: Minimizer.cpp

package info (click to toggle)
ausaxs 1.1.8-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 72,592 kB
  • sloc: cpp: 49,853; ansic: 6,901; python: 730; makefile: 18
file content (121 lines) | stat: -rw-r--r-- 3,765 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// SPDX-License-Identifier: LGPL-3.0-or-later
// Author: Kristian Lytje

#include <mini/Minimizer.h>
#include <mini/detail/Evaluation.h>
#include <mini/detail/Parameter.h>
#include <mini/detail/FittedParameter.h>
#include <utility/Exceptions.h>
#include <settings/GeneralSettings.h>

#include <functional>

using namespace ausaxs;
using namespace ausaxs::mini;

Minimizer::Minimizer() = default;

Minimizer::~Minimizer() = default;

Minimizer::Minimizer(double(&f)(std::vector<double>)) {
    set_function(f);
}

Minimizer::Minimizer(std::function<double(std::vector<double>)>&& f) {
    set_function(std::move(f));
}

Result Minimizer::minimize() {
    if (!is_parameter_set()) {throw except::bad_order("Minimizer::minimize: No parameters were supplied.");}
    if (!is_function_set()) {throw except::bad_order("Minimizer::minimize: No function was set.");}

    clear_evaluated_points();
    return minimize_override();
}

void Minimizer::set_function(double(&f)(std::vector<double>)) {
    raw = std::bind(f, std::placeholders::_1);
    set_function(std::move(raw));
}

void Minimizer::set_function(std::function<double(std::vector<double>)>&& f) {
    raw = std::move(f);
    wrapper = [this] (std::vector<double> p) {
        double fval = raw(p);
        evaluations.evals.push_back(Evaluation(std::move(p), fval));
        fevals++;
        return fval;
    };

    function = wrapper;
}

bool Minimizer::empty() const noexcept {
    return !is_function_set() && !is_parameter_set();
}

void Minimizer::clear_parameters() noexcept {
    parameters.clear();
}

void Minimizer::record_evaluations(bool setting) {
    function = setting ? wrapper : raw;
}

void Minimizer::add_parameter(const Parameter& param) {
    if (!param.has_bounds() && !param.has_guess()) {
        throw except::invalid_argument("Minimizer::add_parameter: Parameter \"" + param.name + "\"must either have a limit or a guess value.");
    }
    parameters.push_back(param);
}

void Minimizer::clear_evaluated_points() noexcept {
    evaluations.evals.clear();
}

bool Minimizer::is_function_set() const noexcept {
    return bool(function); // functions are explicitly convertable to a bool which is true if a function has been set
}

bool Minimizer::is_parameter_set() const noexcept {
    return !parameters.empty();
}

mini::Landscape Minimizer::get_evaluated_points() const {
    if (evaluations.evals.empty()) {throw except::bad_order("Minimizer::get_evaluated_points: Cannot get evaluated points before a minimization call has been made.");}
    return evaluations;
}

mini::Landscape Minimizer::landscape(unsigned int bins) {
    if (parameters.empty()) {throw except::bad_order("Minimizer::landscape: No parameters were supplied.");}

    mini::Landscape l;
    auto bx = parameters[0].bounds.value();
    for (unsigned int i = 0; i < bins; i++) {
        double vx = bx.min + i*bx.span()/(bins-1);
        double fval;
        if (parameters.size() == 2) {
            auto by = parameters[1].bounds.value();
            for (unsigned int j = 0; j < bins; j++) {
                double vy = by.min + j*by.span()/(bins-1);
                fval = function({vx, vy});
                l.evals.emplace_back(Evaluation{{vx, vy}, fval});
            }
        } else {
            fval = function({vx});
            l.evals.emplace_back(Evaluation{{vx}, fval});
        }

        // sanity check
        if (std::isnan(fval) || std::isinf(fval)) {
            if (settings::general::verbose) {std::cout << "Warning in Minimizer::landscape: Function value is nan or inf and will be skipped." << std::endl;}
            l.evals.pop_back();
            continue;
        }
    }
    return l;
}

void Minimizer::set_max_evals(unsigned int max_evals) {
    this->max_evals = max_evals;
}