Browse Source

update: header file of fast cal

master
Dnomd343 3 weeks ago
parent
commit
2fe64dc261
  1. 3
      src/core/CMakeLists.txt
  2. 1
      src/core/benchmark/fast_cal.cc
  3. 64
      src/core/fast_cal/fast_cal.h
  4. 228
      src/core/fast_cal/internal/demo.cc
  5. 12
      src/core/fast_cal/internal/fast_cal.inl
  6. 53
      src/core/fast_cal/internal/layer_queue.inl

3
src/core/CMakeLists.txt

@ -37,7 +37,8 @@ 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 phmap) target_link_libraries(klotski_core PRIVATE absl::flat_hash_map)
target_link_libraries(klotski_core PUBLIC phmap)
add_library(klotski::core ALIAS klotski_core) add_library(klotski::core ALIAS klotski_core)
# TODO: just for dev testing # TODO: just for dev testing

1
src/core/benchmark/fast_cal.cc

@ -11,6 +11,7 @@ using klotski::codec::CommonCode;
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();
for (auto _ : state) { for (auto _ : state) {
// auto fc = FastCal(code); // auto fc = FastCal(code);

64
src/core/fast_cal/fast_cal.h

@ -13,8 +13,14 @@
#include "mover/mover.h" #include "mover/mover.h"
#include "raw_code/raw_code.h" #include "raw_code/raw_code.h"
#include "group/group.h"
// #include <absl/container/flat_hash_map.h> // #include <absl/container/flat_hash_map.h>
#include <ranges>
#include <parallel_hashmap/phmap.h>
using klotski::codec::RawCode; using klotski::codec::RawCode;
using klotski::mover::MaskMover; using klotski::mover::MaskMover;
@ -69,3 +75,61 @@ private:
}; };
RawCode FastCal_demo(RawCode code); 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);
T current() const;
void next();
[[nodiscard]] bool is_ending() const;
[[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 {
class FCDemo {
public:
explicit FCDemo(RawCode raw_code);
std::optional<RawCode> DoCal();
std::vector<RawCode> DoCalMulti();
std::vector<RawCode> DoCalFurthest();
private:
struct data_t {
uint64_t mask;
uint64_t back;
};
LayerQueue<uint64_t> codes_;
phmap::flat_hash_map<uint64_t, data_t> cases_;
};
} // namespace klotski::fast_cal
#include "internal/layer_queue.inl"
#include "internal/fast_cal.inl"

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

@ -16,186 +16,112 @@ using klotski::cases::RangesUnion;
using klotski::mover::MaskMover; using klotski::mover::MaskMover;
using klotski::cases::GroupUnion; using klotski::cases::GroupUnion;
struct data_t { using klotski::fast_cal::FCDemo;
uint64_t mask;
uint64_t back; std::optional<RawCode> FCDemo::DoCal() {
}; uint64_t result = 0;
auto core = MaskMover([this, &result](uint64_t code, uint64_t mask) {
template <typename T> if (const auto match = cases_.find(code); match != cases_.end()) {
class MyQueue { match->second.mask |= mask; // update mask
public: return;
explicit MyQueue(size_t reserve) { }
data_.resize(reserve); cases_.emplace(code, data_t {
} .mask = mask,
.back = codes_.current(),
void emplace_back(T item) { });
data_[queue_end_] = item; codes_.emplace(code);
++queue_end_;
}
T front() {
return data_[queue_begin_];
}
void pop_and_try_layer_switch() {
++queue_begin_;
try_layer_switch();
}
[[nodiscard]] bool is_ending() const {
return queue_begin_ == queue_end_;
}
void try_layer_switch() { if (((code >> 39) & 0b111) == 0b100) {
if (queue_begin_ == layer_end_ && !is_ending()) { result = code;
layer_begin_ = layer_end_;
layer_end_ = queue_end_;
} }
} });
[[nodiscard]] bool is_layer_switched() const { while (!codes_.is_ending()) {
return queue_begin_ == layer_begin_; auto curr = codes_.current();
} core.next_cases(curr, cases_.find(curr)->second.mask);
std::vector<T> get_curr_layer() { codes_.next();
std::vector<T> layer_cases; if (result != 0) {
for (size_t offset = layer_begin_; offset < layer_end_; ++offset) { return RawCode::unsafe_create(result);
layer_cases.emplace_back(data_[offset]);
} }
return layer_cases;
}
private:
size_t queue_begin_ {0};
size_t queue_end_ {0};
size_t layer_begin_ {0};
size_t layer_end_ {1};
std::vector<T> data_ {};
};
class FCDemo {
public:
explicit FCDemo(RawCode raw_code) : codes_(GroupUnion::from_raw_code(raw_code).max_group_size()) {
// TODO: build codes_ with reserve size
auto reserve = GroupUnion::from_raw_code(raw_code).max_group_size();
// codes_.reserve(reserve);
// cases_.reserve(static_cast<size_t>(reserve * 1.56));
cases_.reserve(static_cast<size_t>(25955 * 1.56));
codes_.emplace_back(raw_code.unwrap());
cases_.emplace(raw_code, data_t {0, 0}); // without mask
} }
return std::nullopt;
}
std::optional<RawCode> DoCal() { std::vector<RawCode> FCDemo::DoCalMulti() {
uint64_t result = 0; bool stop_flag = false;
auto core = MaskMover([this, &result](uint64_t code, uint64_t mask) { std::vector<RawCode> results {};
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_.front(),
});
codes_.emplace_back(code);
if (((code >> 39) & 0b111) == 0b100) {
result = code;
}
});
while (!codes_.is_ending()) {
auto curr = codes_.front();
core.next_cases(curr, cases_.find(curr)->second.mask);
codes_.pop_and_try_layer_switch(); auto core = MaskMover([this, &stop_flag, &results](uint64_t code, uint64_t mask) {
if (result != 0) { if (const auto match = cases_.find(code); match != cases_.end()) {
return RawCode::unsafe_create(result); match->second.mask |= mask; // update mask
} return;
} }
return std::nullopt; cases_.emplace(code, data_t {
} .mask = mask,
.back = codes_.current(),
std::vector<RawCode> DoCalMulti() {
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_.front(),
});
codes_.emplace_back(code);
if (((code >> 39) & 0b111) == 0b100) {
stop_flag = true;
results.emplace_back(RawCode::unsafe_create(code));
}
}); });
codes_.emplace(code);
while (!codes_.is_ending()) { if (((code >> 39) & 0b111) == 0b100) {
auto curr = codes_.front(); stop_flag = true;
core.next_cases(curr, cases_.find(curr)->second.mask); results.emplace_back(RawCode::unsafe_create(code));
}
});
codes_.pop_and_try_layer_switch(); while (!codes_.is_ending()) {
if (codes_.is_layer_switched() && stop_flag) { auto curr = codes_.current();
return results; core.next_cases(curr, cases_.find(curr)->second.mask);
}
codes_.next();
if (codes_.is_new_layer() && stop_flag) {
// TODO: fix when solutions at last layer
return results;
} }
return {};
} }
return {};
}
std::vector<RawCode> DoCalFurthest() { std::vector<RawCode> FCDemo::DoCalFurthest() {
auto core = MaskMover([this](uint64_t code, uint64_t mask) {
auto core = MaskMover([this](uint64_t 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;
return; }
} cases_.emplace(code, data_t {
cases_.emplace(code, data_t { .mask = mask,
.mask = mask, .back = codes_.current(),
.back = codes_.front(),
});
codes_.emplace_back(code);
}); });
codes_.emplace(code);
while (true) { });
auto curr = codes_.front();
core.next_cases(curr, cases_.find(curr)->second.mask); while (true) {
auto curr = codes_.current();
codes_.pop_and_try_layer_switch(); core.next_cases(curr, cases_.find(curr)->second.mask);
if (codes_.is_ending()) {
return codes_.get_curr_layer() | std::views::transform([](uint64_t code) { codes_.next();
return RawCode::unsafe_create(code); if (codes_.is_ending()) {
}) | std::ranges::to<std::vector>(); return codes_.layer_cases() | std::views::transform([](uint64_t code) {
} return RawCode::unsafe_create(code);
}) | std::ranges::to<std::vector>();
} }
} }
}
private:
MyQueue<uint64_t> codes_;
phmap::flat_hash_map<uint64_t, data_t> cases_;
};
RawCode FastCal_demo(RawCode raw_code) { RawCode FastCal_demo(RawCode raw_code) {
FCDemo fc {raw_code}; klotski::fast_cal::FCDemo fc {raw_code};
return fc.DoCal().value(); // return fc.DoCal().value();
// auto tmp = fc.DoCal(); // auto tmp = fc.DoCal();
// std::cout << tmp.to_common_code() << std::endl; // std::cout << tmp.value().to_common_code() << std::endl;
// auto tmp = fc.DoCalMulti(); // auto tmp = fc.DoCalMulti();
// for (const auto x : tmp) { // for (const auto x : tmp) {
// std::cout << x.to_common_code() << std::endl; // std::cout << x.to_common_code() << std::endl;
// } // }
// auto tmp = fc.DoCalFurthest(); auto tmp = fc.DoCalFurthest();
// for (const auto x : tmp) { // for (const auto x : tmp) {
// std::cout << x.to_common_code() << std::endl; // std::cout << x.to_common_code() << std::endl;
// } // }

12
src/core/fast_cal/internal/fast_cal.inl

@ -0,0 +1,12 @@
#pragma once
namespace klotski::fast_cal {
inline FCDemo::FCDemo(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
}
} // namespace klotski::fast_cal

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

@ -0,0 +1,53 @@
#pragma once
namespace klotski {
template <typename T>
inline LayerQueue<T>::LayerQueue(size_t reserve, std::initializer_list<T> first_layer) {
data_.resize(reserve);
for (auto x : first_layer) {
emplace(x);
}
layer_end_ = first_layer.size();
}
template <typename T>
void LayerQueue<T>::emplace(T item) {
data_[queue_end_] = item;
++queue_end_;
}
template <typename T>
T LayerQueue<T>::current() const {
return data_[queue_begin_];
}
template <typename T>
void LayerQueue<T>::next() {
++queue_begin_;
if (queue_begin_ == layer_end_ && !is_ending()) {
layer_begin_ = layer_end_;
layer_end_ = queue_end_;
}
}
template <typename T>
[[nodiscard]] bool LayerQueue<T>::is_ending() const {
return queue_begin_ == queue_end_;
}
template <typename T>
[[nodiscard]] bool LayerQueue<T>::is_new_layer() const {
return queue_begin_ == layer_begin_;
}
template <typename T>
std::vector<T> LayerQueue<T>::layer_cases() const {
std::vector<T> layer_cases;
for (size_t offset = layer_begin_; offset < layer_end_; ++offset) {
layer_cases.emplace_back(data_[offset]);
}
return layer_cases;
}
} // namespace klotski
Loading…
Cancel
Save