From c4966f2137c170759942e4394d3186bf173773c8 Mon Sep 17 00:00:00 2001 From: ewarchul Date: Sat, 29 Jun 2024 19:45:14 +0200 Subject: [PATCH] Fix happycat function and extend fuzzing time --- CMakeLists.txt | 3 +- Justfile | 14 ++-- example/main.cpp | 8 +-- .../benchmark/detail/problem/complex.hpp | 1 - .../cecxx/functions/multimodal/happycat.hpp | 2 +- src/legacy/affine_trans.cpp | 2 +- test/CMakeLists.txt | 1 - test/gtest/cec2017_oracle_test.cpp | 67 ++++++++++++------- test/helpers/cec_suite.hpp | 14 ++-- test/helpers/combinators.hpp | 12 ++-- test/oracle/cec2017.cpp | 2 +- 11 files changed, 73 insertions(+), 53 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d901d44..dba0d90 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,7 @@ set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") include(Package) include(config) + include(GNUInstallDirs) include(CMakePackageConfigHelpers) include(GenerateExportHeader) @@ -49,7 +50,6 @@ target_sources(cecxx PRIVATE ${SOURCES}) target_sources(cecxx PUBLIC FILE_SET HEADERS BASE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/include" FILES ${HEADERS}) target_compile_options(cecxx PRIVATE ${COMPILE_FLAGS}) target_compile_features(cecxx PRIVATE cxx_std_20) -#target_compile_definitions(cecxx PUBLIC DEFAULT_BENCHMARK_DATADIR="${BENCHMARK_DATA_STORAGE}") configure_file(defaults.hpp.in ${CMAKE_CURRENT_SOURCE_DIR}/include/cecxx/benchmark/defaults.hpp) generate_export_header(cecxx) @@ -60,7 +60,6 @@ write_basic_package_version_file("${PROJECT_BINARY_DIR}/cecxxConfigVersion.cmake ) include(CPack) -message("${BENCHMARK_DATA_STORAGE}") install(TARGETS cecxx EXPORT cecxxTargets FILE_SET HEADERS) install(EXPORT cecxxTargets NAMESPACE cecxx:: DESTINATION lib/cmake/cecxx) diff --git a/Justfile b/Justfile index b1ccf5a..bb15be4 100644 --- a/Justfile +++ b/Justfile @@ -1,7 +1,7 @@ set dotenv-load +alias i := init_build alias b := build -alias r := rebuild alias p := package alias e := exe alias t := test @@ -12,19 +12,21 @@ c_compiler := "${CC}" build_dir := "build-" + cxx_compiler ncores := `nproc` -build: clean + +# cd {{build_dir}} && CC={{c_compiler}} CXX={{cxx_compiler}} cmake -DWITH_TESTS=off .. + +init_build: clean mkdir -p {{build_dir}} - cd {{build_dir}} && CC={{c_compiler}} CXX={{cxx_compiler}} cmake -DFUZZTEST_FUZZING_MODE=on -DWITH_TESTS=on .. + cd {{build_dir}} && CC={{c_compiler}} CXX={{cxx_compiler}} cmake -DFUZZTEST_FUZZING_MODE=on -DWITH_TESTS=on -DWITH_EXAMPLES=on .. ln -fs {{build_dir}}/compile_commands.json compile_commands.json - cd {{build_dir}} && make -j {{ncores}} -rebuild: +build: cd {{build_dir}} && make -j {{ncores}} exe: ./{{build_dir}}/main -fuzz_duration := "2s" +fuzz_duration := "15s" test: #!/usr/bin/env bash set -euxo pipefail diff --git a/example/main.cpp b/example/main.cpp index a0d358a..6a60307 100644 --- a/example/main.cpp +++ b/example/main.cpp @@ -22,21 +22,19 @@ auto main() -> int { // Prepare input which resembles multidimensional array const auto input = std::vector>{ - rv::repeat(10.0) | rv::take(DIMENSION) | ranges::to_vector}; - - + rv::repeat(0.0) | rv::take(DIMENSION) | ranges::to_vector}; // Evaluate given input on each optimization problem from CEC2017 const auto start = std::chrono::system_clock::now(); - for (const auto &fn : rv::closed_iota(11, 11)) { + for (const auto &fn : rv::closed_iota(1, 30)) { auto output = cec2017_eval(fn, input); fmt::println("fn = {}, output = {:}", fn, output); } + fmt::println("Elapsed time: {}", std::chrono::duration_cast( std::chrono::system_clock::now() - start)); - return EXIT_SUCCESS; // Create a closure for 1st optimizaiton problem from CEC2017 const auto first_fn = [&eval = cec2017_eval](const auto &xs) { return eval(11, xs); diff --git a/include/cecxx/benchmark/detail/problem/complex.hpp b/include/cecxx/benchmark/detail/problem/complex.hpp index 8fa8ebf..e3ae8b1 100644 --- a/include/cecxx/benchmark/detail/problem/complex.hpp +++ b/include/cecxx/benchmark/detail/problem/complex.hpp @@ -5,7 +5,6 @@ #include "cecxx/benchmark/detail/context.hpp" namespace cecxx::benchmark::detail { - struct complex_problem_params { std::vector deltas{}; std::vector biases{}; diff --git a/include/cecxx/functions/multimodal/happycat.hpp b/include/cecxx/functions/multimodal/happycat.hpp index 27ad28c..4ffd13b 100644 --- a/include/cecxx/functions/multimodal/happycat.hpp +++ b/include/cecxx/functions/multimodal/happycat.hpp @@ -12,7 +12,7 @@ constexpr auto happycat(std::span input) -> f64 { constexpr auto alpha = 1.0 / 8.0; for (auto i = 0u; i < nrow; i++) { r2 += (input[i] - 1.0) * (input[i] - 1.0); - sum_z += input[i]; + sum_z += (input[i] - 1.0); } return std::pow(std::fabs(r2 - static_cast(nrow)), 2 * alpha) + (0.5 * r2 + sum_z) / static_cast(nrow) + 0.5; diff --git a/src/legacy/affine_trans.cpp b/src/legacy/affine_trans.cpp index 13331eb..6c7bb8d 100644 --- a/src/legacy/affine_trans.cpp +++ b/src/legacy/affine_trans.cpp @@ -9,7 +9,7 @@ namespace cecxx::benchmark::detail { void shufflefunc(std::span input, std::span output, std::span shuffle_vec) { for (auto i = 0u; i < output.size(); i++) { - auto idx = static_cast(std::max(shuffle_vec[i] - 1, 1L)); + auto idx = static_cast(std::max(shuffle_vec[i] - 1, 0L)); output[i] = input[idx]; } } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c7b4bb6..eb8285e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -11,7 +11,6 @@ include(GoogleTest) fuzztest_setup_fuzzing_flags() - add_compile_definitions(DATA_STORAGE_PATH="${CMAKE_SOURCE_DIR}/data") add_executable(cecxx-fuzz gtest/cec2017_oracle_test.cpp oracle/cec2017.cpp) diff --git a/test/gtest/cec2017_oracle_test.cpp b/test/gtest/cec2017_oracle_test.cpp index f9775d6..0c07750 100644 --- a/test/gtest/cec2017_oracle_test.cpp +++ b/test/gtest/cec2017_oracle_test.cpp @@ -1,67 +1,82 @@ +// clang-format off #include "gtest/gtest.h" #include "fuzztest/fuzztest.h" -#include "helpers/combinators.hpp" #include "fuzztest/googletest_fixture_adapter.h" #include "fuzztest/domain.h" +// clang-format on #include -#include "cecxx/evaluator.hpp" +#include "cecxx/benchmark/evaluator.hpp" + #include "cecxx/types.hpp" +#include "helpers/combinators.hpp" #include "helpers/cec_suite.hpp" #include "helpers/oracle.hpp" using namespace fuzztest; +using namespace cecxx::benchmark; -class CecFuzzTest10D : public PerFuzzTestFixtureAdapter> { - public: +constexpr auto MAX_ABS_ERROR = 1e-10; + +class CecFuzzTest10D : public PerFuzzTestFixtureAdapter< + CecTestFixture> { +public: void Cec2017ImplsAreEquiv(std::vector input, int problem_num) { const auto oracle_output = calculate_oracle_output(input, problem_num); - const auto cecxx_output = cec_evaluator(problem_num, std::vector>{input}); - const auto delta = std::abs(oracle_output - cecxx_output[0]); - EXPECT_TRUE(delta < 1); + const auto cecxx_output = + cec_evaluator(problem_num, std::vector>{input}); + EXPECT_NEAR(oracle_output, cecxx_output[0], MAX_ABS_ERROR); } }; FUZZ_TEST_F(CecFuzzTest10D, Cec2017ImplsAreEquiv) - .WithDomains(PositiveVectorOf(InRange(-1.0, 1.0)).WithSize(10), InCecProblemRange(cecxx::cec_edition_t::cec2017)); + .WithDomains(PositiveVectorOf(InRange(-1.0, 1.0)).WithSize(10), + InCecProblemRange(cec_edition_t::cec2017)); -class CecFuzzTest30D : public PerFuzzTestFixtureAdapter> { - public: +class CecFuzzTest30D : public PerFuzzTestFixtureAdapter< + CecTestFixture> { +public: void Cec2017ImplsAreEquiv(std::vector input, int problem_num) { const auto oracle_output = calculate_oracle_output(input, problem_num); - const auto cecxx_output = cec_evaluator(problem_num, std::vector>{input}); - const auto delta = std::abs(oracle_output - cecxx_output[0]); - EXPECT_TRUE(delta < 1); + const auto cecxx_output = + cec_evaluator(problem_num, std::vector>{input}); + EXPECT_NEAR(oracle_output, cecxx_output[0], MAX_ABS_ERROR); } }; FUZZ_TEST_F(CecFuzzTest30D, Cec2017ImplsAreEquiv) - .WithDomains(PositiveVectorOf(InRange(-1.0, 1.0)).WithSize(30), InCecProblemRange(cecxx::cec_edition_t::cec2017)); + .WithDomains(PositiveVectorOf(InRange(-1.0, 1.0)).WithSize(30), + InCecProblemRange(cec_edition_t::cec2017)); -class CecFuzzTest50D : public PerFuzzTestFixtureAdapter> { - public: +class CecFuzzTest50D : public PerFuzzTestFixtureAdapter< + CecTestFixture> { +public: void Cec2017ImplsAreEquiv(std::vector input, int problem_num) { const auto oracle_output = calculate_oracle_output(input, problem_num); - const auto cecxx_output = cec_evaluator(problem_num, std::vector>{input}); - const auto delta = std::abs(oracle_output - cecxx_output[0]); - EXPECT_TRUE(delta < 1); + const auto cecxx_output = + cec_evaluator(problem_num, std::vector>{input}); + + EXPECT_NEAR(oracle_output, cecxx_output[0], MAX_ABS_ERROR); } }; FUZZ_TEST_F(CecFuzzTest50D, Cec2017ImplsAreEquiv) - .WithDomains(PositiveVectorOf(InRange(-1.0, 1.0)).WithSize(50), InCecProblemRange(cecxx::cec_edition_t::cec2017)); + .WithDomains(PositiveVectorOf(InRange(-1.0, 1.0)).WithSize(50), + InCecProblemRange(cec_edition_t::cec2017)); -class CecFuzzTest100D : public PerFuzzTestFixtureAdapter> { - public: +class CecFuzzTest100D : public PerFuzzTestFixtureAdapter< + CecTestFixture> { +public: void Cec2017ImplsAreEquiv(std::vector input, int problem_num) { const auto oracle_output = calculate_oracle_output(input, problem_num); - const auto cecxx_output = cec_evaluator(problem_num, std::vector>{input}); - const auto delta = std::abs(oracle_output - cecxx_output[0]); - EXPECT_TRUE(delta < 10); + const auto cecxx_output = + cec_evaluator(problem_num, std::vector>{input}); + EXPECT_NEAR(oracle_output, cecxx_output[0], MAX_ABS_ERROR); } }; FUZZ_TEST_F(CecFuzzTest100D, Cec2017ImplsAreEquiv) - .WithDomains(PositiveVectorOf(InRange(-1.0, 1.0)).WithSize(100), InCecProblemRange(cecxx::cec_edition_t::cec2017)); + .WithDomains(PositiveVectorOf(InRange(-1.0, 1.0)).WithSize(100), + InCecProblemRange(cec_edition_t::cec2017)); diff --git a/test/helpers/cec_suite.hpp b/test/helpers/cec_suite.hpp index ee2b6e8..acb9bb8 100644 --- a/test/helpers/cec_suite.hpp +++ b/test/helpers/cec_suite.hpp @@ -1,9 +1,15 @@ #pragma once +// clang-format off #include "gtest/gtest.h" -#include "cecxx/evaluator.hpp" +// clang-format on -template struct CecTestFixture : public testing::Test { - CecTestFixture() : cec_evaluator{cecxx::evaluator(Edition, Dimension, DATA_STORAGE_PATH)} {} - cecxx::evaluator cec_evaluator; +#include "cecxx/benchmark/evaluator.hpp" + +template +struct CecTestFixture : public testing::Test { + CecTestFixture() + : cec_evaluator{cecxx::benchmark::evaluator(Edition, Dimension, + DATA_STORAGE_PATH)} {} + cecxx::benchmark::evaluator cec_evaluator; }; diff --git a/test/helpers/combinators.hpp b/test/helpers/combinators.hpp index 224266b..1ad8630 100644 --- a/test/helpers/combinators.hpp +++ b/test/helpers/combinators.hpp @@ -2,17 +2,19 @@ #include -#include "cecxx/types.hpp" +#include "cecxx/benchmark/edition.hpp" #include "fuzztest/domain.h" -template auto PositiveVectorOf(auto&& Rng) { +template auto PositiveVectorOf(auto &&Rng) { return fuzztest::ContainerOf(std::forward(Rng)); } -auto InCecProblemRange(cecxx::cec_edition_t edition) { +auto InCecProblemRange(cecxx::benchmark::cec_edition_t edition) { + using namespace cecxx::benchmark; switch (edition) { - case cecxx::cec_edition_t::cec2017: { - return fuzztest::Filter([](int x) { return x != 2; }, fuzztest::InRange(1, 28)); + case cec_edition_t::cec2017: { + return fuzztest::Filter([](int x) { return x != 2; }, + fuzztest::InRange(1, 30)); } } } diff --git a/test/oracle/cec2017.cpp b/test/oracle/cec2017.cpp index d297bbf..4a5146b 100644 --- a/test/oracle/cec2017.cpp +++ b/test/oracle/cec2017.cpp @@ -7,7 +7,7 @@ int ini_flag, n_flag, func_flag, *SS; auto STORAGE_PREFIX(const auto& format) -> std::string { using namespace std::string_literals; - return std::string{CEC_STORAGE} + "/cec2017/"s + format; + return std::string{DATA_STORAGE_PATH} + "/cec2017/"s + format; } long double fast_pow(long double x, int p) {