unimodal.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. #include "unimodal.h"
  2. #include "linear_regression.h"
  3. #include <util/generic/map.h>
  4. #include <util/generic/ymath.h>
  5. namespace {
  6. double SimpleUnimodal(const double value) {
  7. if (value > 5) {
  8. return 0.;
  9. }
  10. return 1. / (value * value + 1.);
  11. }
  12. struct TOptimizationState {
  13. double Mode = 0.;
  14. double Normalizer = 1.;
  15. double RegressionFactor = 0.;
  16. double RegressionIntercept = 0.;
  17. double SSE = 0.;
  18. TOptimizationState(const TVector<double>& values) {
  19. SSE = InnerProduct(values, values);
  20. }
  21. double NoRegressionTransform(const double value) const {
  22. const double arg = (value - Mode) / Normalizer;
  23. return SimpleUnimodal(arg);
  24. }
  25. double RegressionTransform(const double value) const {
  26. return NoRegressionTransform(value) * RegressionFactor + RegressionIntercept;
  27. }
  28. };
  29. }
  30. double TGreedyParams::Point(const size_t step) const {
  31. Y_ASSERT(step <= StepsCount);
  32. const double alpha = (double)step / StepsCount;
  33. return LowerBound * (1 - alpha) + UpperBound * alpha;
  34. }
  35. double MakeUnimodal(TVector<double>& values, const TOptimizationParams& optimizationParams) {
  36. TOptimizationState state(values);
  37. TOptimizationState bestState = state;
  38. for (size_t modeStep = 0; modeStep <= optimizationParams.ModeParams.StepsCount; ++modeStep) {
  39. state.Mode = optimizationParams.ModeParams.Point(modeStep);
  40. for (size_t normalizerStep = 0; normalizerStep <= optimizationParams.NormalizerParams.StepsCount; ++normalizerStep) {
  41. state.Normalizer = optimizationParams.NormalizerParams.Point(normalizerStep);
  42. TSLRSolver solver;
  43. for (size_t i = 0; i < values.size(); ++i) {
  44. solver.Add(state.NoRegressionTransform(i), values[i]);
  45. }
  46. state.SSE = solver.SumSquaredErrors(optimizationParams.RegressionShrinkage);
  47. if (state.SSE >= bestState.SSE) {
  48. continue;
  49. }
  50. bestState = state;
  51. solver.Solve(bestState.RegressionFactor, bestState.RegressionIntercept, optimizationParams.RegressionShrinkage);
  52. }
  53. }
  54. for (size_t i = 0; i < values.size(); ++i) {
  55. values[i] = bestState.RegressionTransform(i);
  56. }
  57. const double residualSSE = bestState.SSE;
  58. const double totalSSE = InnerProduct(values, values);
  59. const double determination = 1. - residualSSE / totalSSE;
  60. return determination;
  61. }
  62. double MakeUnimodal(TVector<double>& values) {
  63. return MakeUnimodal(values, TOptimizationParams::Default(values));
  64. }
  65. double MakeUnimodal(TVector<double>& values, const TVector<double>& arguments, const TOptimizationParams& optimizationParams) {
  66. Y_ASSERT(values.size() == arguments.size());
  67. TMap<double, double> mapping;
  68. for (size_t i = 0; i < values.size(); ++i) {
  69. mapping[arguments[i]] = values[i];
  70. }
  71. TVector<double> preparedValues;
  72. preparedValues.reserve(mapping.size());
  73. for (auto&& argWithValue : mapping) {
  74. preparedValues.push_back(argWithValue.second);
  75. }
  76. const double result = MakeUnimodal(preparedValues, optimizationParams);
  77. size_t pos = 0;
  78. for (auto&& argWithValue : mapping) {
  79. argWithValue.second = preparedValues[pos++];
  80. }
  81. for (size_t i = 0; i < values.size(); ++i) {
  82. values[i] = mapping[arguments[i]];
  83. }
  84. return result;
  85. }
  86. double MakeUnimodal(TVector<double>& values, const TVector<double>& arguments) {
  87. return MakeUnimodal(values, arguments, TOptimizationParams::Default(values, arguments));
  88. }