Browse Source

refactor: using `RawCode` instead of `uint64_t`

master
Dnomd343 3 weeks ago
parent
commit
5133793cb9
  1. 2
      src/core/CMakeLists.txt
  2. 11
      src/core/fast_cal/fast_cal.h
  3. 46
      src/core/fast_cal/internal/fast_cal.cc
  4. 18
      src/core/fast_cal/internal/fast_cal.inl
  5. 16
      src/core/group/internal/extend.cc
  6. 14
      src/core/main.cc
  7. 6
      src/core/mover/internal/mover.cc
  8. 6
      src/core/mover/mover.h

2
src/core/CMakeLists.txt

@ -20,7 +20,7 @@ set(KLOTSKI_CORE_SRC
mover/internal/mover.cc mover/internal/mover.cc
fast_cal/internal/demo.cc fast_cal/internal/fast_cal.cc
group/internal/group_union.cc group/internal/group_union.cc
group/internal/extend.cc group/internal/extend.cc

11
src/core/fast_cal/fast_cal.h

@ -8,7 +8,6 @@
#include <cstdint> #include <cstdint>
#include <functional> #include <functional>
#include "group/group.h"
#include "mover/mover.h" #include "mover/mover.h"
#include "layer_queue.h" #include "layer_queue.h"
#include "raw_code/raw_code.h" #include "raw_code/raw_code.h"
@ -27,6 +26,8 @@ public:
// TODO: add global build // TODO: add global build
void build();
/// Calculate a minimum-step case. /// Calculate a minimum-step case.
std::optional<codec::RawCode> solve(); std::optional<codec::RawCode> solve();
@ -56,18 +57,20 @@ private:
KLSK_INLINE void spawn_next(mover::MaskMover &mover); KLSK_INLINE void spawn_next(mover::MaskMover &mover);
/// Try to emplace the searched info into the cache. /// Try to emplace the searched info into the cache.
KLSK_INLINE bool try_emplace(uint64_t code, uint64_t mask); KLSK_INLINE bool try_emplace(codec::RawCode code, uint64_t mask);
// ------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------- //
// TODO: add invalid RawCode constexpr var
struct data_t { struct data_t {
uint64_t mask; uint64_t mask;
uint64_t back; codec::RawCode back;
}; };
// codec::RawCode root_; // codec::RawCode root_;
LayerQueue<codec::RawCode> codes_; LayerQueue<codec::RawCode> codes_;
phmap::flat_hash_map<uint64_t, data_t> cases_; phmap::flat_hash_map<codec::RawCode, data_t> cases_;
// ------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------- //
}; };

46
src/core/fast_cal/internal/demo.cc → src/core/fast_cal/internal/fast_cal.cc

@ -1,11 +1,6 @@
#include "fast_cal/fast_cal.h"
#include <iostream>
#include <parallel_hashmap/phmap.h>
#include "mover/mover.h" #include "mover/mover.h"
#include "group/group.h" #include "group/group.h"
#include "fast_cal/fast_cal.h"
using klotski::codec::RawCode; using klotski::codec::RawCode;
using klotski::codec::CommonCode; using klotski::codec::CommonCode;
@ -16,8 +11,8 @@ using klotski::cases::GroupUnion;
using klotski::fast_cal::FastCalPro; using klotski::fast_cal::FastCalPro;
static KLSK_INLINE bool is_solved(uint64_t raw_code) { static KLSK_INLINE bool is_solved(RawCode raw_code) {
return ((raw_code >> 39) & 0b111) == 0b100; return ((raw_code.unwrap() >> 39) & 0b111) == 0b100;
} }
std::optional<RawCode> FastCalPro::solve() { std::optional<RawCode> FastCalPro::solve() {
@ -26,9 +21,9 @@ std::optional<RawCode> FastCalPro::solve() {
// } // }
uint64_t solution = 0; uint64_t solution = 0;
auto mover = MaskMover([this, &solution](uint64_t code, uint64_t mask) { auto mover = MaskMover([this, &solution](RawCode code, uint64_t mask) {
if (try_emplace(code, mask) && is_solved(code)) { if (try_emplace(code, mask) && is_solved(code)) {
solution = code; solution = code.unwrap();
} }
}); });
while (!codes_.is_ending()) { while (!codes_.is_ending()) {
@ -44,9 +39,9 @@ std::optional<RawCode> FastCalPro::search(std::function<bool(RawCode)> &&match)
// TODO: check root case // TODO: check root case
uint64_t target = 0; uint64_t target = 0;
auto mover = MaskMover([this, &target, match = std::move(match)](uint64_t code, uint64_t mask) { auto mover = MaskMover([this, &target, match = std::move(match)](RawCode code, uint64_t mask) {
if (try_emplace(code, mask) && match(RawCode::unsafe_create(code))) { if (try_emplace(code, mask) && match(code)) {
target = code; target = code.unwrap();
} }
}); });
while (!codes_.is_ending()) { while (!codes_.is_ending()) {
@ -64,17 +59,16 @@ std::vector<RawCode> FastCalPro::solve_multi() {
bool stop_flag = false; bool stop_flag = false;
std::vector<RawCode> results {}; std::vector<RawCode> results {};
auto mover = MaskMover([this, &stop_flag, &results](uint64_t code, uint64_t mask) { auto mover = MaskMover([this, &stop_flag, &results](RawCode code, uint64_t mask) {
if (try_emplace(code, mask) && is_solved(code)) { if (try_emplace(code, mask) && is_solved(code)) {
stop_flag = true; stop_flag = true;
results.emplace_back(RawCode::unsafe_create(code)); results.emplace_back(code);
} }
}); });
while (!codes_.is_ending()) { while (!codes_.is_ending()) {
spawn_next(mover); spawn_next(mover);
if (codes_.is_new_layer() && stop_flag) { if (stop_flag && (codes_.is_new_layer() || codes_.is_ending())) {
// TODO: fix when solutions at last layer
return results; return results;
} }
@ -82,26 +76,30 @@ std::vector<RawCode> FastCalPro::solve_multi() {
return {}; return {};
} }
std::vector<RawCode> FastCalPro::furthest() { void FastCalPro::build() {
auto mover = MaskMover([this](uint64_t code, uint64_t mask) { auto mover = MaskMover([this](RawCode code, uint64_t mask) {
try_emplace(code, mask); try_emplace(code, mask);
}); });
while (true) { while (!codes_.is_ending()) {
spawn_next(mover); spawn_next(mover);
if (codes_.is_ending()) {
return codes_.last_layer();
} }
}
std::vector<RawCode> FastCalPro::furthest() {
if (!codes_.is_ending()) {
build();
} }
return codes_.last_layer();
} }
std::vector<RawCode> FastCalPro::backtrack(RawCode code) const { std::vector<RawCode> FastCalPro::backtrack(RawCode code) const {
if (const auto match = cases_.find(code.unwrap()); match == cases_.end()) { if (const auto match = cases_.find(code); match == cases_.end()) {
return {}; // case not found return {}; // case not found
} }
std::vector<RawCode> path; std::vector<RawCode> path;
while (code != 0) { while (code != 0) {
path.emplace_back(code); path.emplace_back(code);
code = RawCode::unsafe_create(cases_.find(code.unwrap())->second.back); code = cases_.find(code)->second.back;
} }
std::reverse(path.begin(), path.end()); std::reverse(path.begin(), path.end());
return path; return path;

18
src/core/fast_cal/internal/fast_cal.inl

@ -1,30 +1,32 @@
#pragma once #pragma once
#include "group/group.h"
namespace klotski::fast_cal { namespace klotski::fast_cal {
inline FastCalPro::FastCalPro(codec::RawCode raw_code) : codes_({raw_code}, cases::GroupUnion::from_raw_code(raw_code).max_group_size()) { inline FastCalPro::FastCalPro(codec::RawCode raw_code)
auto reserve = cases::GroupUnion::from_raw_code(raw_code).max_group_size(); : codes_({raw_code}, cases::GroupUnion::from_raw_code(raw_code).max_group_size()) {
// cases_.reserve(static_cast<size_t>(25955 * 1.56)); const auto reserve = cases::GroupUnion::from_raw_code(raw_code).max_group_size();
cases_.reserve(static_cast<size_t>(reserve * 1.56)); cases_.reserve(static_cast<size_t>(reserve * 1.56));
cases_.emplace(raw_code, data_t {0, 0}); // without mask cases_.emplace(raw_code, data_t {0, codec::RawCode::unsafe_create(0)}); // without mask
} }
inline KLSK_INLINE bool FastCalPro::try_emplace(uint64_t code, uint64_t mask) { inline KLSK_INLINE bool FastCalPro::try_emplace(codec::RawCode code, uint64_t mask) {
if (const auto match = cases_.find(code); match != cases_.end()) { if (const auto match = cases_.find(code); match != cases_.end()) {
match->second.mask |= mask; // update mask match->second.mask |= mask; // update mask
return false; return false;
} }
cases_.emplace(code, data_t { cases_.emplace(code, data_t {
.mask = mask, .mask = mask,
.back = codes_.current().unwrap(), .back = codes_.current(),
}); });
codes_.emplace(codec::RawCode::unsafe_create(code)); codes_.emplace(code);
return true; return true;
} }
inline KLSK_INLINE void FastCalPro::spawn_next(mover::MaskMover &mover) { inline KLSK_INLINE void FastCalPro::spawn_next(mover::MaskMover &mover) {
auto curr = codes_.current(); auto curr = codes_.current();
mover.next_cases(curr.unwrap(), cases_.find(curr.unwrap())->second.mask); mover.next_cases(curr, cases_.find(curr)->second.mask);
codes_.next(); codes_.next();
} }

16
src/core/group/internal/extend.cc

@ -24,13 +24,13 @@ std::vector<RawCode> klotski::cases::Group_extend(RawCode raw_code, uint32_t res
codes.reserve(GroupUnion::from_raw_code(raw_code).max_group_size()); codes.reserve(GroupUnion::from_raw_code(raw_code).max_group_size());
cases.reserve(25955 * 1.56); cases.reserve(25955 * 1.56);
auto core = MaskMover([&codes, &cases](uint64_t code, uint64_t mask) { auto core = MaskMover([&codes, &cases](RawCode code, uint64_t mask) {
if (const auto match = cases.find(code); match != cases.end()) { if (const auto match = cases.find(code.unwrap()); match != cases.end()) {
match->second |= mask; // update mask match->second |= mask; // update mask
return; return;
} }
cases.emplace(code, mask); cases.emplace(code, mask);
codes.emplace_back(RawCode::unsafe_create(code)); // new case codes.emplace_back(code); // new case
}); });
uint64_t offset = 0; uint64_t offset = 0;
@ -38,7 +38,7 @@ std::vector<RawCode> klotski::cases::Group_extend(RawCode raw_code, uint32_t res
cases.emplace(raw_code, 0); // without mask cases.emplace(raw_code, 0); // without mask
while (offset != codes.size()) { while (offset != codes.size()) {
auto curr = codes[offset++].unwrap(); auto curr = codes[offset++].unwrap();
core.next_cases(curr, cases.find(curr)->second); core.next_cases(RawCode::unsafe_create(curr), cases.find(curr)->second);
} }
// std::cout << cases.size() << std::endl; // std::cout << cases.size() << std::endl;
// std::cout << cases.load_factor() << std::endl; // std::cout << cases.load_factor() << std::endl;
@ -52,13 +52,13 @@ double klotski::cases::Group_load_factor(RawCode raw_code, double coff) {
codes.reserve(reserve); codes.reserve(reserve);
cases.reserve(static_cast<size_t>(coff * reserve)); cases.reserve(static_cast<size_t>(coff * reserve));
auto core = MaskMover([&codes, &cases](uint64_t code, uint64_t mask) { auto core = MaskMover([&codes, &cases](RawCode code, uint64_t mask) {
if (const auto match = cases.find(code); match != cases.end()) { if (const auto match = cases.find(code.unwrap()); match != cases.end()) {
match->second |= mask; // update mask match->second |= mask; // update mask
return; return;
} }
cases.emplace(code, mask); cases.emplace(code, mask);
codes.emplace_back(RawCode::unsafe_create(code)); // new case codes.emplace_back(code); // new case
}); });
uint64_t offset = 0; uint64_t offset = 0;
@ -66,7 +66,7 @@ double klotski::cases::Group_load_factor(RawCode raw_code, double coff) {
cases.emplace(raw_code, 0); // without mask cases.emplace(raw_code, 0); // without mask
while (offset != codes.size()) { while (offset != codes.size()) {
auto curr = codes[offset++].unwrap(); auto curr = codes[offset++].unwrap();
core.next_cases(curr, cases.find(curr)->second); core.next_cases(RawCode::unsafe_create(curr), cases.find(curr)->second);
} }
// if (cases.size() != reserve) { // if (cases.size() != reserve) {

14
src/core/main.cc

@ -14,6 +14,8 @@
#include "short_code/short_code.h" #include "short_code/short_code.h"
#include "common_code/common_code.h" #include "common_code/common_code.h"
#include <parallel_hashmap/phmap.h>
#include "../../third_party/thread-pool/include/BS_thread_pool.hpp" #include "../../third_party/thread-pool/include/BS_thread_pool.hpp"
using klotski::mover::MaskMover; using klotski::mover::MaskMover;
@ -49,7 +51,7 @@ int main() {
auto code = CommonCode::unsafe_create(0x1A9BF0C00).to_raw_code(); auto code = CommonCode::unsafe_create(0x1A9BF0C00).to_raw_code();
klotski::fast_cal::FastCalPro fc {code}; klotski::fast_cal::FastCalPro fc {code};
// std::cout << fc.solve().value() << std::endl; std::cout << fc.solve().value() << std::endl;
// for (auto x : fc.solve_multi()) { // for (auto x : fc.solve_multi()) {
// std::cout << x << std::endl; // std::cout << x << std::endl;
@ -59,11 +61,11 @@ int main() {
// std::cout << x.to_common_code() << std::endl; // std::cout << x.to_common_code() << std::endl;
// } // }
fc.furthest(); // fc.furthest();
for (const auto &layer : fc.exports()) { // for (const auto &layer : fc.exports()) {
std::cout << layer.size() << std::endl; // std::cout << layer.size() << std::endl;
} // }
std::cout << "layer num: " << fc.exports().size() << std::endl; // std::cout << "layer num: " << fc.exports().size() << std::endl;
// for (int i = 0; i < 10000000; ++i) { // for (int i = 0; i < 10000000; ++i) {
// MaskMover mover([](uint64_t code, uint64_t mask) { // MaskMover mover([](uint64_t code, uint64_t mask) {

6
src/core/mover/internal/mover.cc

@ -73,6 +73,7 @@
/////////////////////////////////////////////// ///////////////////////////////////////////////
using klotski::codec::RawCode;
using klotski::mover::MaskMover; using klotski::mover::MaskMover;
inline void MaskMover::cache_insert(cache_t next_case) { // try to insert into cache inline void MaskMover::cache_insert(cache_t next_case) { // try to insert into cache
@ -162,7 +163,8 @@ void MaskMover::move_2x2(uint64_t code, int addr) { // try to move target 2x2 bl
} }
} }
void MaskMover::next_cases(uint64_t code, uint64_t mask) { // search next step cases void MaskMover::next_cases(RawCode raw_code, uint64_t mask) { // search next step cases
const uint64_t code = raw_code.unwrap();
cache_[0].filter = 0; // without filter cache_[0].filter = 0; // without filter
cache_[0].code = code; // bfs root code cache_[0].code = code; // bfs root code
auto range = code | mask; auto range = code | mask;
@ -186,7 +188,7 @@ void MaskMover::next_cases(uint64_t code, uint64_t mask) { // search next step c
} }
if (cache_size_ != 1) { // found one or more next cases if (cache_size_ != 1) { // found one or more next cases
for (int i = 1; i < cache_size_; ++i) { for (int i = 1; i < cache_size_; ++i) {
release_(cache_[i].code, cache_[i].mask); // release next cases release_(RawCode::unsafe_create(cache_[i].code), cache_[i].mask); // release next cases
} }
cache_size_ = 1; // reset cache size cache_size_ = 1; // reset cache size
} }

6
src/core/mover/mover.h

@ -61,6 +61,8 @@
#include <utility> #include <utility>
#include <functional> #include <functional>
#include "raw_code/raw_code.h"
namespace klotski::mover { namespace klotski::mover {
// TODO: new version without mask // TODO: new version without mask
@ -70,10 +72,10 @@ namespace klotski::mover {
class MaskMover { class MaskMover {
public: public:
/// Release with code and mask /// Release with code and mask
typedef std::function<void(uint64_t, uint64_t)> release_t; typedef std::function<void(codec::RawCode, uint64_t)> release_t;
/// Core interface /// Core interface
void next_cases(uint64_t code, uint64_t mask); void next_cases(codec::RawCode code, uint64_t mask);
explicit MaskMover(release_t release_func) : release_(std::move(release_func)) {} explicit MaskMover(release_t release_func) : release_(std::move(release_func)) {}
private: private:

Loading…
Cancel
Save