Browse Source

update: enhance groups build

legacy
Dnomd343 2 years ago
parent
commit
c6a83a9aed
  1. 11
      src/klotski_core/ffi/tmain.cc
  2. 37
      src/klotski_core/group/build_cases.cc
  3. 18
      src/klotski_core/group/group.h
  4. 4
      test/group/build_cases.cc

11
src/klotski_core/ffi/tmain.cc

@ -19,6 +19,7 @@
#include "group.h" #include "group.h"
using klotski::Group; using klotski::Group;
using klotski::TypeId;
using klotski::AllCases; using klotski::AllCases;
using klotski::RawCode; using klotski::RawCode;
@ -33,10 +34,16 @@ using klotski::TYPE_ID_LIMIT;
void tmain() { void tmain() {
// printf("tmain start\n"); // printf("tmain start\n");
auto start = clock();
// Group::build_group(123, 233); // Group::build_group(123, 233);
auto seed = Group::group_seed(123, 233); Group::build_groups(TypeId(123));
std::cout << seed << std::endl;
std::cerr << (clock() - start) * 1000 / CLOCKS_PER_SEC << "ms" << std::endl;
// auto seed = Group::group_seed(123, 233);
// std::cout << seed << std::endl;
// Group::group_info(CommonCode(0x1A9BF0C00)); // Group::group_info(CommonCode(0x1A9BF0C00));

37
src/klotski_core/group/build_cases.cc

@ -5,6 +5,7 @@
#include "type_id.h" #include "type_id.h"
#include "common_code.h" #include "common_code.h"
#include "absl/container/flat_hash_map.h" #include "absl/container/flat_hash_map.h"
#include "absl/container/btree_set.h"
#include "type_id.h" #include "type_id.h"
#include "group_seeds.h" #include "group_seeds.h"
@ -14,8 +15,8 @@ namespace klotski {
using Common::check_range; using Common::check_range;
using Common::range_reverse; using Common::range_reverse;
std::vector<CommonCode> Group::all_cases(uint32_t type_id) { std::vector<CommonCode> Group::all_cases(const TypeId &type_id) {
auto tmp = TypeId(type_id).block_num(); auto tmp = type_id.block_num();
std::vector<uint32_t> ranges; // basic ranges of type_id std::vector<uint32_t> ranges; // basic ranges of type_id
BasicRanges::generate(ranges, { // generate target ranges BasicRanges::generate(ranges, { // generate target ranges
.n1 = 16 - tmp.n_1x1 - (tmp.n_1x2 + tmp.n_2x1) * 2, /// space -> 00 .n1 = 16 - tmp.n_1x1 - (tmp.n_1x2 + tmp.n_2x1) * 2, /// space -> 00
@ -28,7 +29,7 @@ std::vector<CommonCode> Group::all_cases(uint32_t type_id) {
} }
std::vector<CommonCode> all_cases; std::vector<CommonCode> all_cases;
all_cases.reserve(TYPE_ID_SIZE[type_id]); all_cases.reserve(TYPE_ID_SIZE[type_id.unwrap()]);
for (uint64_t head = 0; head < 15; ++head) { // address of 2x2 block for (uint64_t head = 0; head < 15; ++head) { // address of 2x2 block
/// head -> 0/1/2 / 4/5/6 / 8/9/10 / 12/13/14 /// head -> 0/1/2 / 4/5/6 / 8/9/10 / 12/13/14
if ((head & 0b11) == 0b11) { if ((head & 0b11) == 0b11) {
@ -46,12 +47,12 @@ std::vector<CommonCode> Group::all_cases(uint32_t type_id) {
return all_cases; return all_cases;
} }
std::vector<RawCode> Group::group_cases(const RawCode &raw_code) { absl::flat_hash_map<uint64_t, uint64_t> expansion(const RawCode &entry) {
std::queue<uint64_t> cache; std::queue<uint64_t> cache;
absl::flat_hash_map<uint64_t, uint64_t> cases; // <code, mask> absl::flat_hash_map<uint64_t, uint64_t> cases; // <code, mask>
cases.reserve(max_group_size(raw_code)); cases.reserve(Group::group_max_size(entry));
cases.emplace(raw_code.unwrap(), 0); // without mask cases.emplace(entry.unwrap(), 0); // without mask
cache.emplace(raw_code.unwrap()); cache.emplace(entry.unwrap());
auto core = Core( auto core = Core(
[&cache, &cases](auto &&code, auto &&mask) { // callback function [&cache, &cases](auto &&code, auto &&mask) { // callback function
@ -68,7 +69,11 @@ std::vector<RawCode> Group::group_cases(const RawCode &raw_code) {
core.next_cases(cache.front(), cases.find(cache.front())->second); core.next_cases(cache.front(), cases.find(cache.front())->second);
cache.pop(); // case dequeue cache.pop(); // case dequeue
} }
return cases;
}
std::vector<RawCode> Group::group_cases(const RawCode &raw_code) {
auto cases = expansion(raw_code);
auto result = std::vector<RawCode>(); auto result = std::vector<RawCode>();
result.reserve(cases.size()); result.reserve(cases.size());
for (auto &&tmp : cases) { // export group cases for (auto &&tmp : cases) { // export group cases
@ -77,7 +82,6 @@ std::vector<RawCode> Group::group_cases(const RawCode &raw_code) {
return result; return result;
} }
// TODO: test this function
std::vector<RawCode> Group::group_cases(const CommonCode &common_code) { std::vector<RawCode> Group::group_cases(const CommonCode &common_code) {
return group_cases(RawCode::from_common_code(common_code)); return group_cases(RawCode::from_common_code(common_code));
} }
@ -121,9 +125,10 @@ std::vector<CommonCode> Group::build_group(uint32_t type_id, uint32_t group_id)
return {}; // group_id out of range return {}; // group_id out of range
} }
std::vector<std::vector<CommonCode>> Group::build_groups(uint32_t type_id) { std::vector<std::vector<CommonCode>> Group::build_groups(const TypeId &type_id) {
auto all_cases = Group::all_cases(type_id); auto all_cases = Group::all_cases(type_id);
std::vector<std::vector<CommonCode>> groups; std::vector<std::vector<CommonCode>> groups;
auto min = std::min_element(all_cases.begin(), all_cases.end()); // search min CommonCode auto min = std::min_element(all_cases.begin(), all_cases.end()); // search min CommonCode
auto first_group = group_cases(min->to_raw_code()); // expand the first group auto first_group = group_cases(min->to_raw_code()); // expand the first group
groups.emplace_back(first_group.begin(), first_group.end()); groups.emplace_back(first_group.begin(), first_group.end());
@ -131,17 +136,15 @@ std::vector<std::vector<CommonCode>> Group::build_groups(uint32_t type_id) {
return groups; return groups;
} }
std::set<CommonCode> cases(all_cases.begin(), all_cases.end()); absl::btree_set<CommonCode> cases(all_cases.begin(), all_cases.end());
for (auto &&tmp : groups[0]) { for (auto &&tmp : *groups.begin()) {
cases.erase(tmp); // remove elements in first group cases.erase(tmp); // remove elements in first group
} }
while (!cases.empty()) { while (!cases.empty()) {
groups.emplace_back(); // create empty vector auto group = group_cases(cases.begin()->to_raw_code());
auto current_group = groups.end() - 1; // insert into latest groups.emplace_back(group.begin(), group.end()); // release new group
for (auto &&tmp : group_cases(cases.begin()->to_raw_code())) { for (auto &&tmp : *(groups.end() - 1)) {
auto common_code = tmp.to_common_code(); cases.erase(tmp); // remove selected cases
current_group->emplace_back(common_code); // insert into current group
cases.erase(common_code); // remove from global union
} }
} }

18
src/klotski_core/group/group.h

@ -89,14 +89,14 @@ public:
/// --------------------------------- cases expansion --------------------------------- /// --------------------------------- cases expansion ---------------------------------
/// Search for all cases of the specified type_id. /// Search for all cases of the specified type_id.
static std::vector<CommonCode> all_cases(uint32_t type_id); static std::vector<CommonCode> all_cases(const TypeId &type_id);
/// Search for all derivatives that a case can produce. /// Search for all derivatives that a case can produce.
static std::vector<RawCode> group_cases(const RawCode &raw_code); static std::vector<RawCode> group_cases(const RawCode &raw_code);
static std::vector<RawCode> group_cases(const CommonCode &common_code); static std::vector<RawCode> group_cases(const CommonCode &common_code);
/// Calculate all groups in the specified type_id. /// Calculate all groups in the specified type_id.
static std::vector<std::vector<CommonCode>> build_groups(uint32_t type_id); static std::vector<std::vector<CommonCode>> build_groups(const TypeId &type_id);
/// Calculate the specified group using type_id and group_id. /// Calculate the specified group using type_id and group_id.
static std::vector<CommonCode> build_group(uint32_t type_id, uint32_t group_id); static std::vector<CommonCode> build_group(uint32_t type_id, uint32_t group_id);
@ -124,13 +124,17 @@ public:
// TODO: update max_group_size in TYPE_ID_MAX_GROUP // TODO: update max_group_size in TYPE_ID_MAX_GROUP
// static uint32_t max_group_size(uint32_t type_id); static uint32_t group_max_size(const TypeId &type_id) {
static uint32_t max_group_size(const RawCode &raw_code) {
return 65535 * 8; return 65535 * 8;
}; }
// static uint32_t max_group_size(const CommonCode &common_code); static uint32_t group_max_size(const RawCode &raw_code) {
return group_max_size(TypeId(raw_code));
}
static uint32_t group_max_size(const CommonCode &common_code) {
return group_max_size(TypeId(common_code));
}
// TODO: group_num // TODO: group_num

4
test/group/build_cases.cc

@ -28,7 +28,7 @@ const char GROUP_INFO_MD5[] = "976bf22530085210e68a6a4e67053506";
TEST(Group, all_cases) { TEST(Group, all_cases) {
std::vector<std::vector<CommonCode>> all_cases; std::vector<std::vector<CommonCode>> all_cases;
for (uint32_t type_id = 0; type_id < TYPE_ID_LIMIT; ++type_id) { for (uint32_t type_id = 0; type_id < TYPE_ID_LIMIT; ++type_id) {
all_cases.emplace_back(Group::all_cases(type_id)); // build test data all_cases.emplace_back(Group::all_cases(TypeId(type_id))); // build test data
} }
std::vector<uint64_t> combine; std::vector<uint64_t> combine;
@ -99,7 +99,7 @@ TEST(Group, build_groups) {
for (uint16_t type_id = 0; type_id < klotski::TYPE_ID_LIMIT; ++type_id) { for (uint16_t type_id = 0; type_id < klotski::TYPE_ID_LIMIT; ++type_id) {
std::vector<uint32_t> group_sizes; std::vector<uint32_t> group_sizes;
std::vector<CommonCode> group_seeds; std::vector<CommonCode> group_seeds;
auto groups = Group::build_groups(type_id); auto groups = Group::build_groups(TypeId(type_id));
group_sizes.reserve(groups.size()); group_sizes.reserve(groups.size());
group_seeds.reserve(groups.size()); group_seeds.reserve(groups.size());

Loading…
Cancel
Save