| 191 | } |
| 192 | |
| 193 | inline TSamples RemoveOutliers(const TSamples& s, double fraction) { |
| 194 | if (s.size() < 20) { |
| 195 | return s; |
| 196 | } |
| 197 | |
| 198 | const auto predictor = CalcModel(s); |
| 199 | |
| 200 | const auto errfunc = [&predictor](const TSample& p) -> double { |
| 201 | //return (1.0 + fabs(predictor(p.first) - p.second)) / (1.0 + fabs(p.second)); |
| 202 | //return fabs((predictor(p.first) - p.second)) / (1.0 + fabs(p.second)); |
| 203 | //return fabs((predictor(p.first) - p.second)) / (1.0 + p.first); |
| 204 | return fabs((predictor(p.first) - p.second)); |
| 205 | }; |
| 206 | |
| 207 | using TSampleWithError = std::pair<const TSample*, double>; |
| 208 | TVector<TSampleWithError> v; |
| 209 | |
| 210 | v.reserve(s.size()); |
| 211 | |
| 212 | for (const auto& p : s) { |
| 213 | v.emplace_back(&p, errfunc(p)); |
| 214 | } |
| 215 | |
| 216 | Sort(v.begin(), v.end(), [](const TSampleWithError& l, const TSampleWithError& r) -> bool { |
| 217 | return (l.second < r.second) || ((l.second == r.second) && (l.first < r.first)); |
| 218 | }); |
| 219 | |
| 220 | if (0) { |
| 221 | for (const auto& x : v) { |
| 222 | Cout << x.first->first << ", " << x.first->second << " -> " << x.second << Endl; |
| 223 | } |
| 224 | } |
| 225 | |
| 226 | TSamples ret; |
| 227 | |
| 228 | ret.reserve(v.size()); |
| 229 | |
| 230 | for (const auto i : xrange<size_t>(0, fraction * v.size())) { |
| 231 | ret.push_back(*v[i].first); |
| 232 | } |
| 233 | |
| 234 | return ret; |
| 235 | } |
| 236 | |
| 237 | template <class TMyTimer, class T> |
| 238 | static inline TResult RunTest(T&& func, double budget, ITestRunner& test) { |