| 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
 | #include "unimodal.h"
#include "linear_regression.h"
#include <util/generic/map.h>
#include <util/generic/ymath.h>
namespace {
    double SimpleUnimodal(const double value) {
        if (value > 5) {
            return 0.;
        }
        return 1. / (value * value + 1.);
    }
    struct TOptimizationState {
        double Mode = 0.;
        double Normalizer = 1.;
        double RegressionFactor = 0.;
        double RegressionIntercept = 0.;
        double SSE = 0.;
        TOptimizationState(const TVector<double>& values) {
            SSE = InnerProduct(values, values);
        }
        double NoRegressionTransform(const double value) const {
            const double arg = (value - Mode) / Normalizer;
            return SimpleUnimodal(arg);
        }
        double RegressionTransform(const double value) const {
            return NoRegressionTransform(value) * RegressionFactor + RegressionIntercept;
        }
    };
}
double TGreedyParams::Point(const size_t step) const {
    Y_ASSERT(step <= StepsCount);
    const double alpha = (double)step / StepsCount;
    return LowerBound * (1 - alpha) + UpperBound * alpha;
}
double MakeUnimodal(TVector<double>& values, const TOptimizationParams& optimizationParams) {
    TOptimizationState state(values);
    TOptimizationState bestState = state;
    for (size_t modeStep = 0; modeStep <= optimizationParams.ModeParams.StepsCount; ++modeStep) {
        state.Mode = optimizationParams.ModeParams.Point(modeStep);
        for (size_t normalizerStep = 0; normalizerStep <= optimizationParams.NormalizerParams.StepsCount; ++normalizerStep) {
            state.Normalizer = optimizationParams.NormalizerParams.Point(normalizerStep);
            TSLRSolver solver;
            for (size_t i = 0; i < values.size(); ++i) {
                solver.Add(state.NoRegressionTransform(i), values[i]);
            }
            state.SSE = solver.SumSquaredErrors(optimizationParams.RegressionShrinkage);
            if (state.SSE >= bestState.SSE) {
                continue;
            }
            bestState = state;
            solver.Solve(bestState.RegressionFactor, bestState.RegressionIntercept, optimizationParams.RegressionShrinkage);
        }
    }
    for (size_t i = 0; i < values.size(); ++i) {
        values[i] = bestState.RegressionTransform(i);
    }
    const double residualSSE = bestState.SSE;
    const double totalSSE = InnerProduct(values, values);
    const double determination = 1. - residualSSE / totalSSE;
    return determination;
}
double MakeUnimodal(TVector<double>& values) {
    return MakeUnimodal(values, TOptimizationParams::Default(values));
}
double MakeUnimodal(TVector<double>& values, const TVector<double>& arguments, const TOptimizationParams& optimizationParams) {
    Y_ASSERT(values.size() == arguments.size());
    TMap<double, double> mapping;
    for (size_t i = 0; i < values.size(); ++i) {
        mapping[arguments[i]] = values[i];
    }
    TVector<double> preparedValues;
    preparedValues.reserve(mapping.size());
    for (auto&& argWithValue : mapping) {
        preparedValues.push_back(argWithValue.second);
    }
    const double result = MakeUnimodal(preparedValues, optimizationParams);
    size_t pos = 0;
    for (auto&& argWithValue : mapping) {
        argWithValue.second = preparedValues[pos++];
    }
    for (size_t i = 0; i < values.size(); ++i) {
        values[i] = mapping[arguments[i]];
    }
    return result;
}
double MakeUnimodal(TVector<double>& values, const TVector<double>& arguments) {
    return MakeUnimodal(values, arguments, TOptimizationParams::Default(values, arguments));
}
 |