Browse Source

update: interfaces of fast cal

master
Dnomd343 3 weeks ago
parent
commit
a9f53602e4
  1. 34
      src/core/fast_cal/fast_cal.h
  2. 116
      src/core/fast_cal/internal/demo.cc
  3. 21
      src/core/fast_cal/internal/fast_cal.inl

34
src/core/fast_cal/fast_cal.h

@ -109,17 +109,39 @@ private:
namespace klotski::fast_cal {
class FCDemo {
class FastCalPro {
public:
explicit FCDemo(RawCode raw_code);
FastCalPro() = delete;
std::optional<RawCode> DoCal();
explicit FastCalPro(RawCode raw_code);
std::vector<RawCode> DoCalMulti();
// ------------------------------------------------------------------------------------- //
std::vector<RawCode> DoCalFurthest();
/// Calculate the case with minimum steps.
std::optional<RawCode> solve();
/// Calculate the cases with maximum steps.
std::vector<RawCode> furthest();
/// Calculate all of the minimum-step cases.
std::vector<RawCode> solve_multi();
/// Calculate the first case that meets the requirement.
std::optional<RawCode> achieve(std::function<bool(RawCode)> &&match);
// ------------------------------------------------------------------------------------- //
private:
// ------------------------------------------------------------------------------------- //
/// Search next step cases and pop current.
KLSK_INLINE void spawn_next(MaskMover &mover);
/// Try to emplace the searched info into the cache.
KLSK_INLINE bool try_emplace(uint64_t code, uint64_t mask);
// ------------------------------------------------------------------------------------- //
struct data_t {
uint64_t mask;
uint64_t back;
@ -127,6 +149,8 @@ private:
LayerQueue<uint64_t> codes_;
phmap::flat_hash_map<uint64_t, data_t> cases_;
// ------------------------------------------------------------------------------------- //
};
} // namespace klotski::fast_cal

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

@ -16,64 +16,63 @@ using klotski::cases::RangesUnion;
using klotski::mover::MaskMover;
using klotski::cases::GroupUnion;
using klotski::fast_cal::FCDemo;
std::optional<RawCode> FCDemo::DoCal() {
uint64_t result = 0;
auto core = MaskMover([this, &result](uint64_t code, uint64_t mask) {
if (const auto match = cases_.find(code); match != cases_.end()) {
match->second.mask |= mask; // update mask
return;
}
cases_.emplace(code, data_t {
.mask = mask,
.back = codes_.current(),
});
codes_.emplace(code);
if (((code >> 39) & 0b111) == 0b100) {
result = code;
using klotski::fast_cal::FastCalPro;
static KLSK_INLINE bool is_solved(uint64_t raw_code) {
return ((raw_code >> 39) & 0b111) == 0b100;
}
std::optional<RawCode> FastCalPro::solve() {
// TODO: check root case
uint64_t solution = 0;
auto mover = MaskMover([this, &solution](uint64_t code, uint64_t mask) {
if (try_emplace(code, mask) && is_solved(code)) {
solution = code;
}
});
while (!codes_.is_ending()) {
auto curr = codes_.current();
core.next_cases(curr, cases_.find(curr)->second.mask);
spawn_next(mover);
if (solution != 0) {
return RawCode::unsafe_create(solution);
}
}
return std::nullopt;
}
std::optional<RawCode> FastCalPro::achieve(std::function<bool(RawCode)> &&match) {
// TODO: check root case
codes_.next();
if (result != 0) {
return RawCode::unsafe_create(result);
uint64_t target = 0;
auto mover = MaskMover([this, &target, match = std::move(match)](uint64_t code, uint64_t mask) {
if (try_emplace(code, mask) && match(RawCode::unsafe_create(code))) {
target = code;
}
});
while (!codes_.is_ending()) {
spawn_next(mover);
if (target != 0) {
return RawCode::unsafe_create(target);
}
}
return std::nullopt;
}
std::vector<RawCode> FCDemo::DoCalMulti() {
std::vector<RawCode> FastCalPro::solve_multi() {
// TODO: check root case
bool stop_flag = false;
std::vector<RawCode> results {};
auto core = MaskMover([this, &stop_flag, &results](uint64_t code, uint64_t mask) {
if (const auto match = cases_.find(code); match != cases_.end()) {
match->second.mask |= mask; // update mask
return;
}
cases_.emplace(code, data_t {
.mask = mask,
.back = codes_.current(),
});
codes_.emplace(code);
if (((code >> 39) & 0b111) == 0b100) {
auto mover = MaskMover([this, &stop_flag, &results](uint64_t code, uint64_t mask) {
if (try_emplace(code, mask) && is_solved(code)) {
stop_flag = true;
results.emplace_back(RawCode::unsafe_create(code));
}
});
while (!codes_.is_ending()) {
auto curr = codes_.current();
core.next_cases(curr, cases_.find(curr)->second.mask);
codes_.next();
spawn_next(mover);
if (codes_.is_new_layer() && stop_flag) {
// TODO: fix when solutions at last layer
return results;
@ -83,24 +82,12 @@ std::vector<RawCode> FCDemo::DoCalMulti() {
return {};
}
std::vector<RawCode> FCDemo::DoCalFurthest() {
auto core = MaskMover([this](uint64_t code, uint64_t mask) {
if (const auto match = cases_.find(code); match != cases_.end()) {
match->second.mask |= mask; // update mask
return;
}
cases_.emplace(code, data_t {
.mask = mask,
.back = codes_.current(),
});
codes_.emplace(code);
std::vector<RawCode> FastCalPro::furthest() {
auto mover = MaskMover([this](uint64_t code, uint64_t mask) {
try_emplace(code, mask);
});
while (true) {
auto curr = codes_.current();
core.next_cases(curr, cases_.find(curr)->second.mask);
codes_.next();
spawn_next(mover);
if (codes_.is_ending()) {
return codes_.layer_cases() | std::views::transform([](uint64_t code) {
return RawCode::unsafe_create(code);
@ -110,21 +97,26 @@ std::vector<RawCode> FCDemo::DoCalFurthest() {
}
RawCode FastCal_demo(RawCode raw_code) {
klotski::fast_cal::FCDemo fc {raw_code};
// return fc.DoCal().value();
klotski::fast_cal::FastCalPro fc {raw_code};
return fc.solve().value();
// auto tmp = fc.DoCal();
// auto tmp = fc.solve();
// std::cout << tmp.value().to_common_code() << std::endl;
// auto tmp = fc.DoCalMulti();
// auto tmp = fc.solve_multi();
// for (const auto x : tmp) {
// std::cout << x.to_common_code() << std::endl;
// }
auto tmp = fc.DoCalFurthest();
// auto tmp = fc.furthest();
// for (const auto x : tmp) {
// std::cout << x.to_common_code() << std::endl;
// }
return RawCode::unsafe_create(0);
// auto tmp = fc.achieve([](RawCode r) {
// return r == 0x7F87E0E5BFFF492;
// });
// std::cout << tmp.value().to_common_code() << std::endl;
// return RawCode::unsafe_create(0);
}

21
src/core/fast_cal/internal/fast_cal.inl

@ -2,11 +2,30 @@
namespace klotski::fast_cal {
inline FCDemo::FCDemo(RawCode raw_code) : codes_(cases::GroupUnion::from_raw_code(raw_code).max_group_size(), {raw_code.unwrap()}) {
inline FastCalPro::FastCalPro(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();
cases_.reserve(static_cast<size_t>(25955 * 1.56));
// cases_.reserve(static_cast<size_t>(reserve * 1.56));
cases_.emplace(raw_code, data_t {0, 0}); // without mask
}
inline KLSK_INLINE bool FastCalPro::try_emplace(uint64_t code, uint64_t mask) {
if (const auto match = cases_.find(code); match != cases_.end()) {
match->second.mask |= mask; // update mask
return false;
}
cases_.emplace(code, data_t {
.mask = mask,
.back = codes_.current(),
});
codes_.emplace(code);
return true;
}
inline KLSK_INLINE void FastCalPro::spawn_next(MaskMover &mover) {
auto curr = codes_.current();
mover.next_cases(curr, cases_.find(curr)->second.mask);
codes_.next();
}
} // namespace klotski::fast_cal

Loading…
Cancel
Save