Browse Source

feat: Group expands from seed

legacy
Dnomd343 7 months ago
parent
commit
6e49a2d57d
  1. 1
      src/core/CMakeLists.txt
  2. 21
      src/core/benchmark/group.cc
  3. 2
      src/core/group/group.h
  4. 88
      src/core/group/internal/group.cc
  5. 33
      src/core/main.cc
  6. 1
      src/core_test/CMakeLists.txt
  7. 22
      src/core_test/group_tmp/group_extend.cc

1
src/core/CMakeLists.txt

@ -28,6 +28,7 @@ set(KLOTSKI_CORE_SRC
add_library(klotski_core STATIC ${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_compile_options(klotski_core PRIVATE -fno-rtti -fno-exceptions) # option for `-fvisibility=hidden`
target_include_directories(klotski_core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) 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) add_library(klotski::core ALIAS klotski_core)
# TODO: just for dev testing # TODO: just for dev testing

21
src/core/benchmark/group.cc

@ -94,7 +94,24 @@ static void RawCodeToTypeId(benchmark::State &state) {
} }
BENCHMARK(CommonCodeToTypeId)->Arg(8)->Arg(64)->Arg(256); static void GroupExtend(benchmark::State &state) {
BENCHMARK(RawCodeToTypeId)->Arg(8)->Arg(64)->Arg(256);
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(); BENCHMARK_MAIN();

2
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 common_code_to_type_id(uint64_t common_code);
uint32_t raw_code_to_type_id(uint64_t raw_code); uint32_t raw_code_to_type_id(uint64_t raw_code);
std::vector<uint64_t> group_extend_from_seed(uint64_t raw_code);
class Group; class Group;
// TODO: add constexpr // TODO: add constexpr

88
src/core/group/internal/group.cc

@ -1,5 +1,13 @@
#include "group/group.h" #include "group/group.h"
#include <queue>
#include <absl/container/btree_map.h>
#include <absl/container/btree_set.h>
#include <absl/container/flat_hash_map.h>
#include <absl/container/node_hash_map.h>
#include <core/core.h>
static KLSK_INLINE uint32_t type_id(const int n, const int n_2x1, const int n_1x1) { 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}; constexpr int offset[8] = {0, 15, 41, 74, 110, 145, 175, 196};
return offset[n] + (15 - n * 2) * n_2x1 + n_1x1; 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; const auto n_1x1 = std::popcount((raw_code >> 1) & raw_code & 0x0249249249249249) - n - 3;
return type_id(n, n_2x1, n_1x1); return type_id(n, n_2x1, n_1x1);
} }
std::vector<uint64_t> 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<uint64_t> cache({raw_code});
uint64_t offset = 0;
std::vector<uint64_t> results;
results.reserve(max_size);
results.emplace_back(raw_code);
// uint64_t offset = 0;
// std::vector<std::pair<uint64_t, uint64_t>> results;
// results.reserve(max_size);
// results.emplace_back(raw_code, 0);
absl::flat_hash_map<uint64_t, uint64_t> cases; // <code, mask>
// absl::node_hash_map<uint64_t, uint64_t> cases; // <code, mask>
// std::unordered_map<uint64_t, uint64_t> cases; // <code, mask>
// std::map<uint64_t, uint64_t> cases; // <code, mask>
// absl::btree_map<uint64_t, uint64_t> cases; // <code, mask>
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<uint64_t> result;
// result.reserve(cases.size());
// for (auto &&tmp : cases) { // export group cases
// result.emplace_back(tmp.first);
// }
// return result;
// std::vector<uint64_t> result;
// result.reserve(results.size());
// for (auto [code, _] : results) {
// result.emplace_back(code);
// }
// return result;
}

33
src/core/main.cc

@ -25,37 +25,10 @@ using klotski::codec::SHORT_CODE_LIMIT;
int main() { int main() {
const auto start = clock(); 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; std::cout << ret.size() << std::endl;
// 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;
// auto kk = GroupUnion::create(123).value(); // auto kk = GroupUnion::create(123).value();
// std::cout << kk.size() << std::endl; // std::cout << kk.size() << std::endl;

1
src/core_test/CMakeLists.txt

@ -65,6 +65,7 @@ add_test(NAME klotski_core COMMAND test_klotski_core)
set(KLSK_TEST_GROUP_TMP_SRC set(KLSK_TEST_GROUP_TMP_SRC
group_tmp/group_union.cc group_tmp/group_union.cc
group_tmp/group_extend.cc
) )
add_executable(test_klotski_group_tmp ${KLSK_TEST_GROUP_TMP_SRC}) add_executable(test_klotski_group_tmp ${KLSK_TEST_GROUP_TMP_SRC})

22
src/core_test/group_tmp/group_extend.cc

@ -0,0 +1,22 @@
#include <hash.h>
#include <group/group.h>
#include <gtest/gtest.h>
#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);
}
Loading…
Cancel
Save