Browse Source

refactor: code structure of fast cal module

master
Dnomd343 3 weeks ago
parent
commit
f93deb908f
  1. 7
      src/core/benchmark/fast_cal.cc
  2. 128
      src/core/fast_cal/fast_cal.h
  3. 186
      src/core/fast_cal/internal/cal_core.cc
  4. 37
      src/core/fast_cal/internal/demo.cc
  5. 193
      src/core/fast_cal/internal/fast_cal.cc
  6. 10
      src/core/fast_cal/internal/fast_cal.inl
  7. 3
      src/core/fast_cal/internal/layer_queue.inl
  8. 43
      src/core/fast_cal/layer_queue.h
  9. 42
      src/core/main.cc

7
src/core/benchmark/fast_cal.cc

@ -8,15 +8,18 @@
using klotski::codec::CommonCode; using klotski::codec::CommonCode;
using klotski::fast_cal::FastCalPro;
static void FastCalBenchmark(benchmark::State &state) { static void FastCalBenchmark(benchmark::State &state) {
auto code = CommonCode::unsafe_create(0x1A9BF0C00).to_raw_code(); auto code = CommonCode::unsafe_create(0x1A9BF0C00).to_raw_code();
// auto code = CommonCode::unsafe_create(0x4FEA13400).to_raw_code(); // auto code = CommonCode::unsafe_create(0x4FEA13400).to_raw_code();
for (auto _ : state) { for (auto _ : state) {
// auto fc = FastCal(code); auto fc = FastCalPro(code);
benchmark::DoNotOptimize(fc.solve());
// benchmark::DoNotOptimize(fc.demo()); // benchmark::DoNotOptimize(fc.demo());
benchmark::DoNotOptimize(FastCal_demo(code)); // benchmark::DoNotOptimize(FastCal_demo(code));
// auto tmp = klotski::cases::Group_extend(code); // auto tmp = klotski::cases::Group_extend(code);
} }

128
src/core/fast_cal/fast_cal.h

@ -4,11 +4,11 @@
#pragma once #pragma once
#include <queue> // #include <queue>
#include <vector> #include <vector>
#include <cstdint> #include <cstdint>
#include <functional> #include <functional>
#include <unordered_map> // #include <unordered_map>
#include "mover/mover.h" #include "mover/mover.h"
#include "raw_code/raw_code.h" #include "raw_code/raw_code.h"
@ -21,91 +21,60 @@
#include <parallel_hashmap/phmap.h> #include <parallel_hashmap/phmap.h>
using klotski::codec::RawCode; // using klotski::codec::RawCode;
using klotski::mover::MaskMover; // using klotski::mover::MaskMover;
// TODO: using prime number // TODO: using prime number
const uint32_t FC_MAP_RESERVE = 65536 * 8; // const uint32_t FC_MAP_RESERVE = 65536 * 8;
/// FastCal not found -> return invalid raw code /// FastCal not found -> return invalid raw code
const RawCode FC_NOT_FOUND = RawCode::unsafe_create(0); // const RawCode FC_NOT_FOUND = RawCode::unsafe_create(0);
class FastCal { // class FastCal {
public: // public:
typedef std::function<bool(uint64_t)> match_t; // typedef std::function<bool(uint64_t)> match_t;
/// setting root code /// setting root code
void set_root(const RawCode &code); // void set_root(const RawCode &code);
explicit FastCal(const RawCode &code); // explicit FastCal(const RawCode &code);
/// backtrack functions /// backtrack functions
int step_num(const RawCode &code); // int step_num(const RawCode &code);
std::vector<RawCode> backtrack(const RawCode &code); // std::vector<RawCode> backtrack(const RawCode &code);
/// BFS search functions /// BFS search functions
void build(); // void build();
RawCode solve(); // RawCode solve();
std::vector<RawCode> furthest(); // std::vector<RawCode> furthest();
std::vector<RawCode> solve_multi(); // std::vector<RawCode> solve_multi();
RawCode target(const match_t &match); // RawCode target(const match_t &match);
std::vector<RawCode> target_multi(const match_t &match); // std::vector<RawCode> target_multi(const match_t &match);
RawCode demo(); // RawCode demo();
/// static BFS search functions /// static BFS search functions
static std::vector<RawCode> resolve(const RawCode &start); // static std::vector<RawCode> resolve(const RawCode &start);
static std::vector<std::vector<RawCode>> to_furthest(const RawCode &start); // static std::vector<std::vector<RawCode>> to_furthest(const RawCode &start);
static std::vector<std::vector<RawCode>> resolve_multi(const RawCode &start); // static std::vector<std::vector<RawCode>> resolve_multi(const RawCode &start);
static std::vector<RawCode> search(const RawCode &start, const match_t &match); // static std::vector<RawCode> search(const RawCode &start, const match_t &match);
static std::vector<std::vector<RawCode>> search_multi(const RawCode &start, const match_t &match); // static std::vector<std::vector<RawCode>> search_multi(const RawCode &start, const match_t &match);
private:
struct fast_cal_t {
uint64_t code;
uint64_t mask;
fast_cal_t *last;
};
uint64_t root;
std::queue<fast_cal_t*> cache;
std::unordered_map<uint64_t, fast_cal_t> cases;
inline MaskMover init(uint64_t code);
void new_case(uint64_t code, uint64_t mask);
};
RawCode FastCal_demo(RawCode code);
namespace klotski {
template <typename T>
class LayerQueue {
public:
LayerQueue(size_t reserve, std::initializer_list<T> first_layer);
void emplace(T item); // private:
// struct fast_cal_t {
// uint64_t code;
// uint64_t mask;
// fast_cal_t *last;
// };
T current() const; // uint64_t root;
// std::queue<fast_cal_t*> cache;
// std::unordered_map<uint64_t, fast_cal_t> cases;
void next(); // inline MaskMover init(uint64_t code);
// void new_case(uint64_t code, uint64_t mask);
// };
[[nodiscard]] bool is_ending() const; #include "layer_queue.h"
[[nodiscard]] bool is_new_layer() const;
std::vector<T> layer_cases() const;
private:
size_t queue_begin_ {0};
size_t queue_end_ {0};
size_t layer_begin_ {0};
size_t layer_end_ {0};
std::vector<T> data_ {};
};
} // namespace klotski
namespace klotski::fast_cal { namespace klotski::fast_cal {
@ -113,26 +82,30 @@ class FastCalPro {
public: public:
FastCalPro() = delete; FastCalPro() = delete;
explicit FastCalPro(RawCode raw_code); explicit FastCalPro(codec::RawCode raw_code);
// ------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------- //
// TODO: add global build
/// Calculate the case with minimum steps. /// Calculate the case with minimum steps.
std::optional<RawCode> solve(); std::optional<codec::RawCode> solve();
/// Calculate the cases with maximum steps. /// Calculate the cases with maximum steps.
std::vector<RawCode> furthest(); std::vector<codec::RawCode> furthest();
/// Calculate all of the minimum-step cases. /// Calculate all of the minimum-step cases.
std::vector<RawCode> solve_multi(); std::vector<codec::RawCode> solve_multi();
/// Calculate the first case that meets the requirement. /// Calculate the first case that meets the requirement.
std::optional<RawCode> achieve(std::function<bool(RawCode)> &&match); std::optional<codec::RawCode> search(std::function<bool(codec::RawCode)> &&match);
// ------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------- //
/// Backtrack the shortest path from specified case. /// Backtrack the shortest path from specified case.
std::vector<RawCode> backtrack(RawCode code); std::vector<codec::RawCode> backtrack(codec::RawCode code) const;
// std::vector<std::vector<codec::RawCode>> export_layers() const;
// ------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------- //
@ -140,7 +113,7 @@ private:
// ------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------- //
/// Search next step cases and pop current. /// Search next step cases and pop current.
KLSK_INLINE void spawn_next(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(uint64_t code, uint64_t mask);
@ -160,5 +133,6 @@ private:
} // namespace klotski::fast_cal } // namespace klotski::fast_cal
#include "internal/layer_queue.inl" // klotski::codec::RawCode FastCal_demo(klotski::codec::RawCode code);
#include "internal/fast_cal.inl" #include "internal/fast_cal.inl"

186
src/core/fast_cal/internal/cal_core.cc

@ -1,105 +1,105 @@
#include "fast_cal/fast_cal.h" #include "fast_cal/fast_cal.h"
MaskMover FastCal::init(uint64_t code) { // initialize process // MaskMover FastCal::init(uint64_t code) { // initialize process
/// reset working data // /// reset working data
cases.clear(); // cases.clear();
cases.reserve(FC_MAP_RESERVE); // hashmap pre-reserve // cases.reserve(FC_MAP_RESERVE); // hashmap pre-reserve
std::queue<fast_cal_t*>{}.swap(cache); // std::queue<fast_cal_t*>{}.swap(cache);
//
/// insert root node // /// insert root node
cache.emplace(&cases.emplace(code, fast_cal_t { // cache.emplace(&cases.emplace(code, fast_cal_t {
.code = code, // .code = code,
.mask = 0, // .mask = 0,
.last = nullptr, // without parent node // .last = nullptr, // without parent node
}).first->second); // }).first->second);
//
/// import klotski mover // /// import klotski mover
return MaskMover( // return MaskMover(
[this](auto &&code, auto &&mask) { // lambda as function pointer // [this](auto &&code, auto &&mask) { // lambda as function pointer
new_case(std::forward<decltype(code)>(code), std::forward<decltype(mask)>(mask)); // new_case(std::forward<decltype(code)>(code), std::forward<decltype(mask)>(mask));
} // }
); // );
} // }
/// callback function for new case /// callback function for new case
void FastCal::new_case(uint64_t code, uint64_t mask) { // void FastCal::new_case(uint64_t code, uint64_t mask) {
auto current = cases.find(code); // auto current = cases.find(code);
if (current != cases.end()) { // find existed case // if (current != cases.end()) { // find existed case
current->second.mask |= mask; // update mask info // current->second.mask |= mask; // update mask info
return; // return;
} // }
cache.emplace(&cases.emplace(code, fast_cal_t { // record new case // cache.emplace(&cases.emplace(code, fast_cal_t { // record new case
.code = code, // .code = code,
.mask = mask, // .mask = mask,
.last = cache.front(), // link parent case // .last = cache.front(), // link parent case
}).first->second); // }).first->second);
} // }
/// build total search tree /// build total search tree
void FastCal::build() { // void FastCal::build() {
auto core = init(root); // auto core = init(root);
while (!cache.empty()) { // while (!cache.empty()) {
core.next_cases(cache.front()->code, cache.front()->mask); // core.next_cases(cache.front()->code, cache.front()->mask);
cache.pop(); // cache.pop();
} // }
} // }
/// found first matched target /// found first matched target
RawCode FastCal::target(const match_t &match) { // RawCode FastCal::target(const match_t &match) {
auto core = init(root); // auto core = init(root);
while (!cache.empty()) { // while (!cache.empty()) {
if (match(cache.front()->code)) { // if (match(cache.front()->code)) {
return RawCode::unsafe_create(cache.front()->code); // match target // return RawCode::unsafe_create(cache.front()->code); // match target
} // }
core.next_cases(cache.front()->code, cache.front()->mask); // core.next_cases(cache.front()->code, cache.front()->mask);
cache.pop(); // cache.pop();
} // }
return FC_NOT_FOUND; // target not found // return FC_NOT_FOUND; // target not found
} // }
/// found all of the furthest cases /// found all of the furthest cases
std::vector<RawCode> FastCal::furthest() { // std::vector<RawCode> FastCal::furthest() {
auto core = init(root); // auto core = init(root);
auto layer_end = cache.back(); // auto layer_end = cache.back();
std::vector<RawCode> layer_cases; // std::vector<RawCode> layer_cases;
/// start BFS search // /// start BFS search
while (!cache.empty()) { // while (!cache.empty()) {
core.next_cases(cache.front()->code, cache.front()->mask); // core.next_cases(cache.front()->code, cache.front()->mask);
layer_cases.emplace_back( // layer_cases.emplace_back(
RawCode::unsafe_create(cache.front()->code) // record layer cases // RawCode::unsafe_create(cache.front()->code) // record layer cases
); // );
if (cache.front() == layer_end) { // reach layer ending // if (cache.front() == layer_end) { // reach layer ending
if (cache.size() == 1) { // if (cache.size() == 1) {
break; // stop loop at last layer // break; // stop loop at last layer
} // }
layer_cases.clear(); // layer_cases.clear();
layer_end = cache.back(); // reset layer ending // layer_end = cache.back(); // reset layer ending
} // }
cache.pop(); // cache.pop();
} // }
return layer_cases; // release the latest layer cases // return layer_cases; // release the latest layer cases
} // }
/// found multi-targets matched in first same layer /// found multi-targets matched in first same layer
std::vector<RawCode> FastCal::target_multi(const match_t &match) { // std::vector<RawCode> FastCal::target_multi(const match_t &match) {
auto core = init(root); // auto core = init(root);
auto layer_end = cache.back(); // auto layer_end = cache.back();
std::vector<RawCode> matched; // matched list // std::vector<RawCode> matched; // matched list
/// start BFS search // /// start BFS search
while (!cache.empty()) { // while (!cache.empty()) {
if (match(cache.front()->code)) { // match target // if (match(cache.front()->code)) { // match target
matched.emplace_back( // matched.emplace_back(
RawCode::unsafe_create(cache.front()->code) // record matched cases // RawCode::unsafe_create(cache.front()->code) // record matched cases
); // );
} // }
core.next_cases(cache.front()->code, cache.front()->mask); // core.next_cases(cache.front()->code, cache.front()->mask);
if (cache.front() == layer_end) { // reach layer ending // if (cache.front() == layer_end) { // reach layer ending
if (!matched.empty()) { // if (!matched.empty()) {
return matched; // stop at first matched layer // return matched; // stop at first matched layer
} // }
layer_end = cache.back(); // reset layer ending // layer_end = cache.back(); // reset layer ending
} // }
cache.pop(); // cache.pop();
} // }
return std::vector<RawCode>{}; // no target found // return std::vector<RawCode>{}; // no target found
} // }

37
src/core/fast_cal/internal/demo.cc

@ -40,7 +40,7 @@ std::optional<RawCode> FastCalPro::solve() {
return std::nullopt; return std::nullopt;
} }
std::optional<RawCode> FastCalPro::achieve(std::function<bool(RawCode)> &&match) { 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;
@ -96,7 +96,7 @@ std::vector<RawCode> FastCalPro::furthest() {
} }
} }
std::vector<RawCode> FastCalPro::backtrack(RawCode code) { 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.unwrap()); match == cases_.end()) {
return {}; // case not found return {}; // case not found
} }
@ -109,15 +109,30 @@ std::vector<RawCode> FastCalPro::backtrack(RawCode code) {
return path; return path;
} }
RawCode FastCal_demo(RawCode raw_code) { // std::vector<std::vector<RawCode>> FastCalPro::export_layers() const {
klotski::fast_cal::FastCalPro fc {raw_code}; // auto layer = furthest();
// return fc.solve().value(); //
// std::vector<std::vector<RawCode>> result;
// result.emplace_back(layer);
//
// for (auto code : layer) {
// std::cout << code << std::endl;
// }
auto tmp = fc.solve(); // return {};
// std::cout << tmp.value().to_common_code() << std::endl; // }
// RawCode FastCal_demo(RawCode raw_code) {
// FastCalPro fc {raw_code};
// return fc.solve().value();
// auto tmp = fc.solve();
// std::cout << tmp.value().to_common_code() << std::endl;
auto path = fc.backtrack(tmp.value()); // auto path = fc.backtrack(tmp.value());
std::cout << path.size() << std::endl; // std::cout << path.size() << std::endl;
// fc.export_layers();
// auto tmp = fc.solve_multi(); // auto tmp = fc.solve_multi();
// for (const auto x : tmp) { // for (const auto x : tmp) {
@ -134,5 +149,5 @@ RawCode FastCal_demo(RawCode raw_code) {
// }); // });
// std::cout << tmp.value().to_common_code() << std::endl; // std::cout << tmp.value().to_common_code() << std::endl;
return RawCode::unsafe_create(0); // return RawCode::unsafe_create(0);
} // }

193
src/core/fast_cal/internal/fast_cal.cc

@ -8,133 +8,88 @@
#include "group/group.h" #include "group/group.h"
FastCal::FastCal(const RawCode &code) { // FastCal::FastCal(const RawCode &code) {
this->root = (uint64_t)code; // this->root = (uint64_t)code;
} // }
void FastCal::set_root(const RawCode &code) { // void FastCal::set_root(const RawCode &code) {
this->root = (uint64_t)code; // this->root = (uint64_t)code;
} // }
/// klotski resolved -> 2x2 block at address 13 (aka 0xD) /// klotski resolved -> 2x2 block at address 13 (aka 0xD)
auto resolved = [](uint64_t code) { // auto resolved = [](uint64_t code) {
return ((code >> (3 * 0xD)) & 0b111) == BLOCK_2x2; // check 2x2 block address // return ((code >> (3 * 0xD)) & 0b111) == BLOCK_2x2; // check 2x2 block address
}; // };
RawCode FastCal::solve() { // RawCode FastCal::solve() {
return FastCal::target(resolved); // return FastCal::target(resolved);
} // }
RawCode FastCal::demo() { // std::vector<RawCode> FastCal::solve_multi() {
// return FastCal::target_multi(resolved);
// }
// max_group_size = 25955 // std::vector<RawCode> FastCal::resolve(const RawCode &start) {
// auto reserve = klotski::cases::GroupUnion::from_raw_code(RawCode::unsafe_create(root)).max_group_size(); // return FastCal::search(start, resolved);
// }
cases.reserve(25955); // FAST !!! (about 5ms) // std::vector<std::vector<RawCode>> FastCal::resolve_multi(const RawCode &start) {
// cases.reserve(32768); // SLOW !!! (about 50ms) // return FastCal::search_multi(start, resolved);
// }
// TODO: using prime number!
std::queue<fast_cal_t*>{}.swap(cache);
cache.emplace(&cases.emplace(root, fast_cal_t {
.code = root,
.mask = 0,
.last = nullptr, // without parent node
}).first->second);
auto core = MaskMover(
[this](uint64_t code, uint64_t mask) { // lambda as function pointer
auto current = cases.find(code);
if (current != cases.end()) { // find existed case
current->second.mask |= mask; // update mask info
return;
}
cache.emplace(&cases.emplace(code, fast_cal_t { // record new case
.code = code,
.mask = mask,
.last = cache.front(), // link parent case
}).first->second);
}
);
while (!cache.empty()) {
if (((cache.front()->code >> (3 * 0xD)) & 0b111) == BLOCK_2x2) {
return RawCode::unsafe_create(cache.front()->code); // match target
}
core.next_cases(cache.front()->code, cache.front()->mask);
cache.pop();
}
return FC_NOT_FOUND; // target not found
}
std::vector<RawCode> FastCal::solve_multi() {
return FastCal::target_multi(resolved);
}
std::vector<RawCode> FastCal::resolve(const RawCode &start) {
return FastCal::search(start, resolved);
}
std::vector<std::vector<RawCode>> FastCal::resolve_multi(const RawCode &start) {
return FastCal::search_multi(start, resolved);
}
/// backtrack of FastCal tree /// backtrack of FastCal tree
int FastCal::step_num(const RawCode &code) { // int FastCal::step_num(const RawCode &code) {
auto tmp = cases.find((uint64_t)code); // auto tmp = cases.find((uint64_t)code);
if (tmp == cases.end()) { // if (tmp == cases.end()) {
return -1; // code not exist // return -1; // code not exist
} // }
int num = 0; // step number // int num = 0; // step number
auto node = &tmp->second; // backtrack entry // auto node = &tmp->second; // backtrack entry
while ((node = node->last) != nullptr) { // while ((node = node->last) != nullptr) {
++num; // ++num;
} // }
return num; // return num;
} // }
std::vector<RawCode> FastCal::backtrack(const RawCode &code) { // std::vector<RawCode> FastCal::backtrack(const RawCode &code) {
auto tmp = cases.find((uint64_t)code); // auto tmp = cases.find((uint64_t)code);
if (tmp == cases.end()) { // if (tmp == cases.end()) {
return std::vector<RawCode>{}; // code not exist // return std::vector<RawCode>{}; // code not exist
} // }
auto node = &tmp->second; // backtrack entry // auto node = &tmp->second; // backtrack entry
std::vector<RawCode> path; // backtrack path // std::vector<RawCode> path; // backtrack path
while (node != nullptr) { // while (node != nullptr) {
path.emplace_back(RawCode::unsafe_create(node->code)); // record path info // path.emplace_back(RawCode::unsafe_create(node->code)); // record path info
node = node->last; // node = node->last;
} // }
std::reverse(path.begin(), path.end()); // reverse path cases // std::reverse(path.begin(), path.end()); // reverse path cases
return path; // return path;
} // }
/// static BFS search functions /// static BFS search functions
std::vector<std::vector<RawCode>> FastCal::to_furthest(const RawCode &start) { // std::vector<std::vector<RawCode>> FastCal::to_furthest(const RawCode &start) {
auto fc = FastCal(start); // auto fc = FastCal(start);
std::vector<std::vector<RawCode>> result; // std::vector<std::vector<RawCode>> result;
for (const auto &furthest : fc.furthest()) { // for (const auto &furthest : fc.furthest()) {
result.emplace_back(fc.backtrack(furthest)); // backtrack every furthest cases // result.emplace_back(fc.backtrack(furthest)); // backtrack every furthest cases
} // }
return result; // return result;
} // }
std::vector<RawCode> FastCal::search(const RawCode &start, const match_t &match) { // std::vector<RawCode> FastCal::search(const RawCode &start, const match_t &match) {
auto fc = FastCal(start); // auto fc = FastCal(start);
auto result = fc.target(match); // auto result = fc.target(match);
if (result == FC_NOT_FOUND) { // if (result == FC_NOT_FOUND) {
return std::vector<RawCode>{}; // target not matched // return std::vector<RawCode>{}; // target not matched
} // }
return fc.backtrack(result); // backtrack target path // return fc.backtrack(result); // backtrack target path
} // }
std::vector<std::vector<RawCode>> FastCal::search_multi(const RawCode &start, const match_t &match) { // std::vector<std::vector<RawCode>> FastCal::search_multi(const RawCode &start, const match_t &match) {
auto fc = FastCal(start); // auto fc = FastCal(start);
std::vector<std::vector<RawCode>> result; // std::vector<std::vector<RawCode>> result;
for (const auto &target : fc.target_multi(match)) { // for (const auto &target : fc.target_multi(match)) {
result.emplace_back(fc.backtrack(target)); // backtrack every target // result.emplace_back(fc.backtrack(target)); // backtrack every target
} // }
return result; // return result;
} // }

10
src/core/fast_cal/internal/fast_cal.inl

@ -2,10 +2,10 @@
namespace klotski::fast_cal { namespace klotski::fast_cal {
inline FastCalPro::FastCalPro(RawCode raw_code) : codes_(cases::GroupUnion::from_raw_code(raw_code).max_group_size(), {raw_code.unwrap()}) { inline FastCalPro::FastCalPro(codec::RawCode raw_code) : codes_(cases::GroupUnion::from_raw_code(raw_code).max_group_size(), {raw_code.unwrap()}) {
// auto reserve = cases::GroupUnion::from_raw_code(raw_code).max_group_size(); auto reserve = cases::GroupUnion::from_raw_code(raw_code).max_group_size();
cases_.reserve(static_cast<size_t>(25955 * 1.56)); // cases_.reserve(static_cast<size_t>(25955 * 1.56));
// 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, 0}); // without mask
} }
@ -22,7 +22,7 @@ inline KLSK_INLINE bool FastCalPro::try_emplace(uint64_t code, uint64_t mask) {
return true; return true;
} }
inline KLSK_INLINE void FastCalPro::spawn_next(MaskMover &mover) { inline KLSK_INLINE void FastCalPro::spawn_next(mover::MaskMover &mover) {
auto curr = codes_.current(); auto curr = codes_.current();
mover.next_cases(curr, cases_.find(curr)->second.mask); mover.next_cases(curr, cases_.find(curr)->second.mask);
codes_.next(); codes_.next();

3
src/core/fast_cal/internal/layer_queue.inl

@ -9,6 +9,8 @@ inline LayerQueue<T>::LayerQueue(size_t reserve, std::initializer_list<T> first_
emplace(x); emplace(x);
} }
layer_end_ = first_layer.size(); layer_end_ = first_layer.size();
layers_.reserve(139);
layers_.emplace_back(0, layer_end_);
} }
template <typename T> template <typename T>
@ -28,6 +30,7 @@ void LayerQueue<T>::next() {
if (queue_begin_ == layer_end_ && !is_ending()) { if (queue_begin_ == layer_end_ && !is_ending()) {
layer_begin_ = layer_end_; layer_begin_ = layer_end_;
layer_end_ = queue_end_; layer_end_ = queue_end_;
layers_.emplace_back(layer_begin_, layer_end_);
} }
} }

43
src/core/fast_cal/layer_queue.h

@ -0,0 +1,43 @@
/// Klotski Engine by Dnomd343 @2024
#pragma once
#include <vector>
#include <cstdint>
namespace klotski {
template <typename T>
class LayerQueue {
public:
LayerQueue(size_t reserve, std::initializer_list<T> first_layer);
void emplace(T item);
T current() const;
void next();
[[nodiscard]] bool is_ending() const;
[[nodiscard]] bool is_new_layer() const;
std::vector<T> layer_cases() const;
// TODO: allow export all layers
private:
size_t queue_begin_ {0};
size_t queue_end_ {0};
size_t layer_begin_ {0};
size_t layer_end_ {0};
std::vector<T> data_ {};
std::vector<std::pair<size_t, size_t>> layers_ {};
};
} // namespace klotski
#include "internal/layer_queue.inl"

42
src/core/main.cc

@ -47,46 +47,8 @@ int main() {
const auto start = std::chrono::system_clock::now(); const auto start = std::chrono::system_clock::now();
auto code = CommonCode::unsafe_create(0x1A9BF0C00).to_raw_code(); auto code = CommonCode::unsafe_create(0x1A9BF0C00).to_raw_code();
for (int i = 0; i < 100; ++i) { klotski::fast_cal::FastCalPro fc {code};
// FastCal fc {code}; std::cout << fc.solve().value() << std::endl;
// fc.solve();
// klotski::cases::Group_extend(code);
FastCal_demo(code);
break;
}
// for (uint32_t type_id = 0; type_id < TYPE_ID_LIMIT; ++type_id) {
// auto group_union = GroupUnion::unsafe_create(type_id);
// for (uint32_t pattern_id = 0; pattern_id < group_union.pattern_num(); ++pattern_id) {
// std::cout << std::format("[{}, {}]\n", type_id, pattern_id);
// auto seed = CommonCode::unsafe_create(PATTERN_DATA[PATTERN_OFFSET[type_id] + pattern_id] >> 23);
//
// double coff = 1.0;
// double last_val = -1;
// while (true) {
// auto val = Group_load_factor(seed.to_raw_code(), coff);
// if (int(val * 1000) != int(last_val * 1000)) {
// std::cout << std::format("{:.2f}, {:.6f}\n", coff, val);
// last_val = val;
// }
// if (coff >= 2.0) {
// break;
// }
// coff += 0.01;
// }
// std::cout << std::endl;
// }
//
// }
// std::cout << Group_load_factor(code, 0.5) << std::endl;
// std::cout << Group_load_factor(code, 0.8) << std::endl;
// std::cout << Group_load_factor(code, 1.0) << std::endl;
// std::cout << Group_load_factor(code, 1.2) << std::endl;
// std::cout << Group_load_factor(code, 1.5) << std::endl;
// std::cout << Group_load_factor(code, 2.0) << std::endl;
// std::cout << Group_load_factor(code, 3.0) << std::endl;
// std::cout << Group_load_factor(code, 5.0) << 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) {

Loading…
Cancel
Save