diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index bee586b..88aec5c 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -28,6 +28,7 @@ set(KLOTSKI_CORE_SRC add_library(klotski_core STATIC ${KLOTSKI_CORE_SRC}) target_compile_options(klotski_core PRIVATE -fno-rtti -fno-exceptions) # option for `-fvisibility=hidden` target_include_directories(klotski_core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(klotski_core PRIVATE absl::flat_hash_map) add_library(klotski::core ALIAS klotski_core) # TODO: just for dev testing diff --git a/src/core/benchmark/group.cc b/src/core/benchmark/group.cc index 001a3e5..04e3a3c 100644 --- a/src/core/benchmark/group.cc +++ b/src/core/benchmark/group.cc @@ -94,7 +94,24 @@ static void RawCodeToTypeId(benchmark::State &state) { } -BENCHMARK(CommonCodeToTypeId)->Arg(8)->Arg(64)->Arg(256); -BENCHMARK(RawCodeToTypeId)->Arg(8)->Arg(64)->Arg(256); +static void GroupExtend(benchmark::State &state) { + + auto src = klotski::codec::RawCode::from_common_code(0x1A9BF0C00)->unwrap(); + + for (auto _ : state) { + + volatile auto ret = klotski::cases::group_extend_from_seed(src); + + // std::cout << ret.size() << std::endl; + } + + // state.SetItemsProcessed(state.iterations()); + +} + +// BENCHMARK(CommonCodeToTypeId)->Arg(8)->Arg(64)->Arg(256); +// BENCHMARK(RawCodeToTypeId)->Arg(8)->Arg(64)->Arg(256); + +BENCHMARK(GroupExtend)->Unit(benchmark::kMillisecond); BENCHMARK_MAIN(); diff --git a/src/core/group/group.h b/src/core/group/group.h index f900b89..92b8d97 100644 --- a/src/core/group/group.h +++ b/src/core/group/group.h @@ -78,6 +78,8 @@ constexpr uint32_t ALL_GROUP_NUM = 25422; uint32_t common_code_to_type_id(uint64_t common_code); uint32_t raw_code_to_type_id(uint64_t raw_code); +std::vector group_extend_from_seed(uint64_t raw_code); + class Group; // TODO: add constexpr diff --git a/src/core/group/internal/group.cc b/src/core/group/internal/group.cc index 7517503..0722e4e 100644 --- a/src/core/group/internal/group.cc +++ b/src/core/group/internal/group.cc @@ -1,5 +1,13 @@ #include "group/group.h" +#include + +#include +#include +#include +#include +#include + static KLSK_INLINE uint32_t type_id(const int n, const int n_2x1, const int n_1x1) { constexpr int offset[8] = {0, 15, 41, 74, 110, 145, 175, 196}; return offset[n] + (15 - n * 2) * n_2x1 + n_1x1; @@ -18,3 +26,83 @@ uint32_t klotski::cases::raw_code_to_type_id(const uint64_t raw_code) { const auto n_1x1 = std::popcount((raw_code >> 1) & raw_code & 0x0249249249249249) - n - 3; return type_id(n, n_2x1, n_1x1); } + +std::vector klotski::cases::group_extend_from_seed(uint64_t raw_code) { + + auto max_size = GroupUnion::create(raw_code_to_type_id(raw_code))->max_group_size(); + + // std::queue cache({raw_code}); + + uint64_t offset = 0; + std::vector results; + results.reserve(max_size); + results.emplace_back(raw_code); + + // uint64_t offset = 0; + // std::vector> results; + // results.reserve(max_size); + // results.emplace_back(raw_code, 0); + + absl::flat_hash_map cases; // + // absl::node_hash_map cases; // + // std::unordered_map cases; // + // std::map cases; // + // absl::btree_map cases; // + + cases.reserve(max_size); + cases.emplace(raw_code, 0); // without mask + + // std::cout << max_size << std::endl; + + auto core = klotski::core::Core( + [&results, &cases](auto code, auto mask) { // callback function + auto current = cases.find(code); + if (current != cases.end()) { + current->second |= mask; // update mask + // results[current->second].second |= mask; // update mask + return; + } + cases.emplace(code, mask); + // cases.emplace(code, results.size()); + + // cache.emplace(code); + results.emplace_back(code); + // cache.emplace(code, 0); + // results.emplace_back(code, 0); + } + ); + + while (offset != results.size()) { + auto tmp = results[offset]; + core.next_cases(tmp, cases.find(tmp)->second); + // core.next_cases(tmp, 0); + + // core.next_cases(tmp.first, tmp.second); + + ++offset; + } + + return results; + + // return {}; + + // while (!cache.empty()) { // until BFS without elements + // core.next_cases(cache.front(), cases.find(cache.front())->second); + // cache.pop(); // case dequeue + // } + + // std::vector result; + // result.reserve(cases.size()); + // for (auto &&tmp : cases) { // export group cases + // result.emplace_back(tmp.first); + // } + // return result; + + // std::vector result; + // result.reserve(results.size()); + // for (auto [code, _] : results) { + // result.emplace_back(code); + // } + // return result; + +} diff --git a/src/core/main.cc b/src/core/main.cc index e94d2d7..ceb71f2 100644 --- a/src/core/main.cc +++ b/src/core/main.cc @@ -25,37 +25,10 @@ using klotski::codec::SHORT_CODE_LIMIT; int main() { const auto start = clock(); - // std::cout << klotski::cases::common_code_to_type_id(0x1A9BF0C00) << std::endl; + auto raw_code = RawCode::from_common_code(0x1A9BF0C00)->unwrap(); + auto ret = klotski::cases::group_extend_from_seed(raw_code); - // uint32_t demo = 0b101001110110; - // 010110001001 - // 01001000100 - - // 00 -> 1 | 0 -> 0 - // 01 -> 1 | 1 -> 1 - // 10 -> 0 | 0 -> 0 - // 11 -> 0 | 1 -> 0 - - // uint32_t ret = ((~demo >> 1) & demo) & 0x55555555; - // - // std::cout << ret << std::endl; - // std::cout << std::popcount(ret) << std::endl; - - uint32_t range = 0xA9BF0C00; // n_01 = 1 / n_10 = 4 / n_11 = 4 - - // 10 10 10 01 10 11 11 11 00 00 11 00 00 00 00 00 - // 0 0 0 1 0 0 0 0 1 1 0 1 1 1 1 1 - // 0 0 0 1 0 1 1 1 0 0 1 0 0 0 0 0 - // 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 - - uint32_t k_01 = (~range >> 1) & range & 0x55555555; - uint32_t k_10 = (range >> 1) & ~range & 0x55555555; - uint32_t k_11 = (range >> 1) & range & 0x55555555; - - // std::cout << k_01 << std::endl; - std::cout << std::popcount(k_01) << std::endl; - std::cout << std::popcount(k_10) << std::endl; - std::cout << std::popcount(k_11) << std::endl; + std::cout << ret.size() << std::endl; // auto kk = GroupUnion::create(123).value(); // std::cout << kk.size() << std::endl; diff --git a/src/core_test/CMakeLists.txt b/src/core_test/CMakeLists.txt index dbe6ea6..a2933fe 100644 --- a/src/core_test/CMakeLists.txt +++ b/src/core_test/CMakeLists.txt @@ -65,6 +65,7 @@ add_test(NAME klotski_core COMMAND test_klotski_core) set(KLSK_TEST_GROUP_TMP_SRC group_tmp/group_union.cc + group_tmp/group_extend.cc ) add_executable(test_klotski_group_tmp ${KLSK_TEST_GROUP_TMP_SRC}) diff --git a/src/core_test/group_tmp/group_extend.cc b/src/core_test/group_tmp/group_extend.cc new file mode 100644 index 0000000..5b72aab --- /dev/null +++ b/src/core_test/group_tmp/group_extend.cc @@ -0,0 +1,22 @@ +#include +#include +#include +#include <__format/format_functions.h> + +TEST(Group, group_extend) { + auto src = klotski::codec::RawCode::from_common_code(0x1A9BF0C00)->unwrap(); + auto codes = klotski::cases::group_extend_from_seed(src); + + for (auto &code: codes) { + auto raw_code = klotski::codec::RawCode::create(code).value(); + code = raw_code.to_common_code().unwrap(); + } + std::sort(codes.begin(), codes.end()); + EXPECT_EQ(codes.size(), 25955); + + auto index = std::lower_bound(codes.begin(), codes.end(), 0x1A9BF0C00) - codes.begin(); + EXPECT_EQ(index, 7472); + + auto hash_ret = hash::xxh3(codes.data(), codes.size() * sizeof(uint64_t)); + EXPECT_EQ(hash_ret, 0x91BD28A749312A6D); +}