From 764d980b9b89b4e035a30067c0b78d2860b84b16 Mon Sep 17 00:00:00 2001 From: Shawn Ligocki Date: Mon, 29 Jul 2024 15:35:36 -0400 Subject: [PATCH 1/2] Add failing tests for drawWithoutReplacementSkip() with multiple skip values. --- cpp_version/test/utility_test.cpp | 188 ++++++++++++++++++++++++++---- 1 file changed, 167 insertions(+), 21 deletions(-) diff --git a/cpp_version/test/utility_test.cpp b/cpp_version/test/utility_test.cpp index c12d623da..b1bb7c79f 100644 --- a/cpp_version/test/utility_test.cpp +++ b/cpp_version/test/utility_test.cpp @@ -202,21 +202,28 @@ TEST(drawWithoutReplacementSkip, small_small1) { size_t num_samples = 4; size_t num_replicates = 10000; - size_t expected_count = num_samples * num_replicates / max; + size_t expected_count = num_samples * num_replicates / (max + 1 - skip.size()); for (size_t i = 0; i < num_replicates; ++i) { result.clear(); drawWithoutReplacementSkip(result, random_number_generator, max + 1, skip, num_samples); + EXPECT_EQ(num_samples, result.size()); for (auto& idx : result) { + EXPECT_LE(idx, max); ++counts[idx]; } } // Check if counts are expected +- 5% - for (auto& c : counts) { - EXPECT_NEAR(expected_count, c.second, expected_count * 0.05); + for (size_t c = 0; c <= max; ++c) { + if (std::find(skip.begin(), skip.end(), c) == skip.end()) { + // c should not be skipped + EXPECT_NEAR(expected_count, counts[c], expected_count * 0.05); + } else { + // c should be skipped + EXPECT_EQ(0, counts[c]); + } } - EXPECT_EQ(0, counts[skip[0]]); } TEST(drawWithoutReplacementSkip, small_small2) { @@ -232,21 +239,28 @@ TEST(drawWithoutReplacementSkip, small_small2) { size_t num_samples = 4; size_t num_replicates = 10000; - size_t expected_count = num_samples * num_replicates / max; + size_t expected_count = num_samples * num_replicates / (max + 1 - skip.size()); for (size_t i = 0; i < num_replicates; ++i) { result.clear(); drawWithoutReplacementSkip(result, random_number_generator, max + 1, skip, num_samples); + EXPECT_EQ(num_samples, result.size()); for (auto& idx : result) { + EXPECT_LE(idx, max); ++counts[idx]; } } // Check if counts are expected +- 5% - for (auto& c : counts) { - EXPECT_NEAR(expected_count, c.second, expected_count * 0.05); + for (size_t c = 0; c <= max; ++c) { + if (std::find(skip.begin(), skip.end(), c) == skip.end()) { + // c should not be skipped + EXPECT_NEAR(expected_count, counts[c], expected_count * 0.05); + } else { + // c should be skipped + EXPECT_EQ(0, counts[c]); + } } - EXPECT_EQ(0, counts[skip[0]]); } TEST(drawWithoutReplacementSkip, small_small3) { @@ -262,21 +276,102 @@ TEST(drawWithoutReplacementSkip, small_small3) { size_t num_samples = 4; size_t num_replicates = 10000; - size_t expected_count = num_samples * num_replicates / max; + size_t expected_count = num_samples * num_replicates / (max + 1 - skip.size()); for (size_t i = 0; i < num_replicates; ++i) { result.clear(); drawWithoutReplacementSkip(result, random_number_generator, max + 1, skip, num_samples); + EXPECT_EQ(num_samples, result.size()); for (auto& idx : result) { + EXPECT_LE(idx, max); ++counts[idx]; } } // Check if counts are expected +- 5% - for (auto& c : counts) { - EXPECT_NEAR(expected_count, c.second, expected_count * 0.05); + for (size_t c = 0; c <= max; ++c) { + if (std::find(skip.begin(), skip.end(), c) == skip.end()) { + // c should not be skipped + EXPECT_NEAR(expected_count, counts[c], expected_count * 0.05); + } else { + // c should be skipped + EXPECT_EQ(0, counts[c]); + } + } +} + +TEST(drawWithoutReplacementSkip, small_small4) { + + std::vector result; + std::mt19937_64 random_number_generator; + std::random_device random_device; + random_number_generator.seed(random_device()); + std::map counts; + + size_t max = 9; + std::vector skip = std::vector({7, 0, 1, 3}); + size_t num_samples = 4; + size_t num_replicates = 10000; + + size_t expected_count = num_samples * num_replicates / (max + 1 - skip.size()); + + for (size_t i = 0; i < num_replicates; ++i) { + result.clear(); + drawWithoutReplacementSkip(result, random_number_generator, max + 1, skip, num_samples); + EXPECT_EQ(num_samples, result.size()); + for (auto& idx : result) { + EXPECT_LE(idx, max); + ++counts[idx]; + } + } + + // Check if counts are expected +- 5% + for (size_t c = 0; c <= max; ++c) { + if (std::find(skip.begin(), skip.end(), c) == skip.end()) { + // c should not be skipped + EXPECT_NEAR(expected_count, counts[c], expected_count * 0.05); + } else { + // c should be skipped + EXPECT_EQ(0, counts[c]); + } + } +} + +TEST(drawWithoutReplacementSkip, small_small5) { + + std::vector result; + std::mt19937_64 random_number_generator; + std::random_device random_device; + random_number_generator.seed(random_device()); + std::map counts; + + size_t max = 9; + std::vector skip = std::vector({}); + size_t num_samples = 4; + size_t num_replicates = 10000; + + size_t expected_count = num_samples * num_replicates / (max + 1 - skip.size()); + + for (size_t i = 0; i < num_replicates; ++i) { + result.clear(); + drawWithoutReplacementSkip(result, random_number_generator, max + 1, skip, num_samples); + EXPECT_EQ(num_samples, result.size()); + for (auto& idx : result) { + EXPECT_LE(idx, max); + ++counts[idx]; + } + } + + // Check if counts are expected +- 5% + for (size_t c = 0; c <= max; ++c) { + if (std::find(skip.begin(), skip.end(), c) == skip.end()) { + // c should not be skipped + EXPECT_NEAR(expected_count, counts[c], expected_count * 0.05); + } else { + // c should be skipped + EXPECT_EQ(0, counts[c]); + } } - EXPECT_EQ(0, counts[skip[0]]); } TEST(drawWithoutReplacementSkip, small_large1) { @@ -292,21 +387,65 @@ TEST(drawWithoutReplacementSkip, small_large1) { size_t num_samples = 50; size_t num_replicates = 100000; - size_t expected_count = num_samples * num_replicates / max; + size_t expected_count = num_samples * num_replicates / (max + 1 - skip.size()); + + for (size_t i = 0; i < num_replicates; ++i) { + result.clear(); + drawWithoutReplacementSkip(result, random_number_generator, max + 1, skip, num_samples); + EXPECT_EQ(num_samples, result.size()); + for (auto& idx : result) { + EXPECT_LE(idx, max); + ++counts[idx]; + } + } + + // Check if counts are expected +- 5% + for (size_t c = 0; c <= max; ++c) { + if (std::find(skip.begin(), skip.end(), c) == skip.end()) { + // c should not be skipped + EXPECT_NEAR(expected_count, counts[c], expected_count * 0.05); + } else { + // c should be skipped + EXPECT_EQ(0, counts[c]); + } + } +} + +TEST(drawWithoutReplacementSkip, small_large2) { + + std::vector result; + std::mt19937_64 random_number_generator; + std::random_device random_device; + random_number_generator.seed(random_device()); + std::map counts; + + size_t max = 1000; + std::vector skip = std::vector({7, 1, 0, 138}); + size_t num_samples = 50; + size_t num_replicates = 100000; + + size_t expected_count = num_samples * num_replicates / (max + 1 - skip.size()); for (size_t i = 0; i < num_replicates; ++i) { result.clear(); drawWithoutReplacementSkip(result, random_number_generator, max + 1, skip, num_samples); + EXPECT_EQ(num_samples, result.size()); for (auto& idx : result) { + EXPECT_LE(idx, max); ++counts[idx]; } } - // Check if counts are expected +- 10% - for (auto& c : counts) { - EXPECT_NEAR(expected_count, c.second, expected_count * 0.1); + // Check if counts are expected +- 5% + for (size_t c = 0; c <= max; ++c) { + if (std::find(skip.begin(), skip.end(), c) == skip.end()) { + // c should not be skipped + EXPECT_NEAR(expected_count, counts[c], expected_count * 0.05); + } else { + // c should be skipped + EXPECT_EQ(0, counts[c]); + } } - EXPECT_EQ(0, counts[skip[0]]); } TEST(drawWithoutReplacementSkip, large_large1) { @@ -322,21 +461,28 @@ TEST(drawWithoutReplacementSkip, large_large1) { size_t num_samples = 500; size_t num_replicates = 10000; - size_t expected_count = num_samples * num_replicates / max; + size_t expected_count = num_samples * num_replicates / (max + 1 - skip.size()); for (size_t i = 0; i < num_replicates; ++i) { result.clear(); drawWithoutReplacementSkip(result, random_number_generator, max + 1, skip, num_samples); + EXPECT_EQ(num_samples, result.size()); for (auto& idx : result) { + EXPECT_LE(idx, max); ++counts[idx]; } } // Check if counts are expected +- 5% - for (auto& c : counts) { - EXPECT_NEAR(expected_count, c.second, expected_count * 0.05); + for (size_t c = 0; c <= max; ++c) { + if (std::find(skip.begin(), skip.end(), c) == skip.end()) { + // c should not be skipped + EXPECT_NEAR(expected_count, counts[c], expected_count * 0.05); + } else { + // c should be skipped + EXPECT_EQ(0, counts[c]); + } } - EXPECT_EQ(0, counts[skip[0]]); } TEST(mostFrequentClass, notEqual1) { From 9370df23cd97e896f045a063f0aaea2ec661b34b Mon Sep 17 00:00:00 2001 From: "Marvin N. Wright" Date: Thu, 22 Aug 2024 07:59:43 +0200 Subject: [PATCH 2/2] skip values in ascending order --- cpp_version/test/utility_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp_version/test/utility_test.cpp b/cpp_version/test/utility_test.cpp index b1bb7c79f..1b663d79e 100644 --- a/cpp_version/test/utility_test.cpp +++ b/cpp_version/test/utility_test.cpp @@ -309,7 +309,7 @@ TEST(drawWithoutReplacementSkip, small_small4) { std::map counts; size_t max = 9; - std::vector skip = std::vector({7, 0, 1, 3}); + std::vector skip = std::vector({0, 1, 3, 7}); size_t num_samples = 4; size_t num_replicates = 10000; @@ -420,7 +420,7 @@ TEST(drawWithoutReplacementSkip, small_large2) { std::map counts; size_t max = 1000; - std::vector skip = std::vector({7, 1, 0, 138}); + std::vector skip = std::vector({0, 1, 7, 138}); size_t num_samples = 50; size_t num_replicates = 100000;