|
27 | 27 | #include <model/CDataGatherer.h> |
28 | 28 | #include <model/CDetectionRule.h> |
29 | 29 | #include <model/CEventData.h> |
| 30 | +#include <model/CIndividualModel.h> |
30 | 31 | #include <model/CInterimBucketCorrector.h> |
31 | 32 | #include <model/CMetricModel.h> |
32 | 33 | #include <model/CMetricModelFactory.h> |
|
50 | 51 | #include <utility> |
51 | 52 | #include <vector> |
52 | 53 |
|
| 54 | +namespace ml { |
| 55 | +namespace model { |
| 56 | +class CIndividualModelTestHelper { |
| 57 | +public: |
| 58 | + static void setFeature(ml::model::CIndividualModel& model) { |
| 59 | + auto& feature = model.m_FeatureModels[0]; |
| 60 | + feature.s_Models.emplace_back(feature.s_NewModel->clone(0)); |
| 61 | + } |
| 62 | +}; |
| 63 | +} |
| 64 | +} |
| 65 | + |
53 | 66 | BOOST_AUTO_TEST_SUITE(CMetricModelTest) |
54 | 67 |
|
55 | 68 | using namespace ml; |
@@ -2349,4 +2362,77 @@ BOOST_FIXTURE_TEST_CASE(testIgnoreSamplingGivenDetectionRules, CTestFixture) { |
2349 | 2362 | modelNoSkipTime); |
2350 | 2363 | } |
2351 | 2364 |
|
| 2365 | +class MyFakeModel : public ml::maths::common::CModelStub { |
| 2366 | +public: |
| 2367 | + MyFakeModel(model_t::TDouble2Vec latLong) : m_LatLong(latLong) {} |
| 2368 | + |
| 2369 | + model_t::TDouble2Vec predict(core_t::TTime /*time*/, |
| 2370 | + const TSizeDoublePr1Vec& /*correlated*/, |
| 2371 | + TDouble2Vec /*hint*/) const override { |
| 2372 | + return m_LatLong; |
| 2373 | + } |
| 2374 | + |
| 2375 | + CModelStub* clone(std::size_t /*id*/) const override { |
| 2376 | + return new MyFakeModel(m_LatLong); |
| 2377 | + } |
| 2378 | + |
| 2379 | +private: |
| 2380 | + model_t::TDouble2Vec m_LatLong; |
| 2381 | +}; |
| 2382 | + |
| 2383 | +BOOST_FIXTURE_TEST_CASE(testLatLongNotMalformed, CTestFixture) { |
| 2384 | + // This test ensures that the latitudes and longitudes generated by the model are within the |
| 2385 | + // expected range. |
| 2386 | + |
| 2387 | + // initialize the model |
| 2388 | + core_t::TTime startTime{45}; |
| 2389 | + core_t::TTime bucketLength{5}; |
| 2390 | + model_t::TFeatureVec features{model_t::E_IndividualMeanLatLongByPerson}; |
| 2391 | + SModelParams params(bucketLength); |
| 2392 | + params.s_InitialDecayRateMultiplier = 1.0; |
| 2393 | + params.s_MaximumUpdatesPerBucket = 0.0; |
| 2394 | + size_t sampleCount{1}; |
| 2395 | + |
| 2396 | + this->makeModel(params, features, startTime, sampleCount); |
| 2397 | + |
| 2398 | + ml::model::CAnomalyDetectorModel::TFeatureMultivariatePriorSPtrPrVec newFeatureCorelateModelPriors; |
| 2399 | + ml::model::CAnomalyDetectorModel::TFeatureCorrelationsPtrPrVec featureCorrelatesModels; |
| 2400 | + ml::model::CAnomalyDetectorModel::TFeatureInfluenceCalculatorCPtrPrVecVec influenceCalculators; |
| 2401 | + |
| 2402 | + // generate random numbers for latitudes and longitudes in the range [-360, 360] |
| 2403 | + test::CRandomNumbers rng; |
| 2404 | + int numberOfTrials{100}; |
| 2405 | + std::vector<double> latitudes; |
| 2406 | + std::vector<double> longitudes; |
| 2407 | + rng.generateUniformSamples(-360.0, 360.0, numberOfTrials, latitudes); |
| 2408 | + rng.generateUniformSamples(-360.0, 360.0, numberOfTrials, longitudes); |
| 2409 | + |
| 2410 | + for (auto i = 0; i < numberOfTrials; ++i) { |
| 2411 | + ml::model::CAnomalyDetectorModel::TFeatureMathsModelSPtrPrVec newFeatureModels = { |
| 2412 | + std::make_pair(model_t::E_IndividualMeanLatLongByPerson, |
| 2413 | + std::make_shared<MyFakeModel>(model_t::TDouble2Vec( |
| 2414 | + {latitudes[i], longitudes[i]})))}; |
| 2415 | + ml::model::CMetricModel model{params, |
| 2416 | + m_Gatherer, |
| 2417 | + newFeatureModels, |
| 2418 | + newFeatureCorelateModelPriors, |
| 2419 | + std::move(featureCorrelatesModels), |
| 2420 | + influenceCalculators, |
| 2421 | + m_InterimBucketCorrector}; |
| 2422 | + CIndividualModelTestHelper::setFeature(model); |
| 2423 | + model_t::CResultType type(model_t::CResultType::E_Unconditional | |
| 2424 | + model_t::CResultType::E_Final); |
| 2425 | + core_t::TTime time{startTime}; |
| 2426 | + auto result = model.baselineBucketMean(features[0], 0, 0, type, NO_CORRELATES, time); |
| 2427 | + // ensure the result is withing the expected range |
| 2428 | + BOOST_REQUIRE_EQUAL(result.size(), 2); |
| 2429 | + // Check latitude in [-90, 90] |
| 2430 | + BOOST_TEST_REQUIRE(result[0] >= -90.0); |
| 2431 | + BOOST_TEST_REQUIRE(result[0] <= 90.0); |
| 2432 | + // Check longitude in [-180, 180] |
| 2433 | + BOOST_TEST_REQUIRE(result[1] >= -180.0); |
| 2434 | + BOOST_TEST_REQUIRE(result[1] <= 180.0); |
| 2435 | + } |
| 2436 | +} |
| 2437 | + |
2352 | 2438 | BOOST_AUTO_TEST_SUITE_END() |
0 commit comments