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})
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_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)
# 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) {
auto code = CommonCode::unsafe_create(0x1A9BF0C00).to_raw_code();
// auto code = CommonCode::unsafe_create(0x4FEA13400).to_raw_code();
for (auto _ : state) {
// auto fc = FastCal(code);

64
src/core/fast_cal/fast_cal.h

@ -13,8 +13,14 @@
#include "mover/mover.h"
#include "raw_code/raw_code.h"
#include "group/group.h"
// #include <absl/container/flat_hash_map.h>
#include <ranges>
#include <parallel_hashmap/phmap.h>
using klotski::codec::RawCode;
using klotski::mover::MaskMover;
@ -69,3 +75,61 @@ private:
};
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::cases::GroupUnion;
struct data_t {
uint64_t mask;
uint64_t back;
};
template <typename T>
class MyQueue {
public:
explicit MyQueue(size_t reserve) {
data_.resize(reserve);
}
void emplace_back(T item) {
data_[queue_end_] = item;
++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_;
}
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);
void try_layer_switch() {
if (queue_begin_ == layer_end_ && !is_ending()) {
layer_begin_ = layer_end_;
layer_end_ = queue_end_;
if (((code >> 39) & 0b111) == 0b100) {
result = code;
}
}
});
[[nodiscard]] bool is_layer_switched() const {
return queue_begin_ == layer_begin_;
}
while (!codes_.is_ending()) {
auto curr = codes_.current();
core.next_cases(curr, cases_.find(curr)->second.mask);
std::vector<T> get_curr_layer() {
std::vector<T> layer_cases;
for (size_t offset = layer_begin_; offset < layer_end_; ++offset) {
layer_cases.emplace_back(data_[offset]);
codes_.next();
if (result != 0) {
return RawCode::unsafe_create(result);
}
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() {
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_.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);
std::vector<RawCode> FCDemo::DoCalMulti() {
bool stop_flag = false;
std::vector<RawCode> results {};
codes_.pop_and_try_layer_switch();
if (result != 0) {
return RawCode::unsafe_create(result);
}
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;
}
return std::nullopt;
}
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));
}
cases_.emplace(code, data_t {
.mask = mask,
.back = codes_.current(),
});
codes_.emplace(code);
while (!codes_.is_ending()) {
auto curr = codes_.front();
core.next_cases(curr, cases_.find(curr)->second.mask);
if (((code >> 39) & 0b111) == 0b100) {
stop_flag = true;
results.emplace_back(RawCode::unsafe_create(code));
}
});
codes_.pop_and_try_layer_switch();
if (codes_.is_layer_switched() && stop_flag) {
return results;
}
while (!codes_.is_ending()) {
auto curr = codes_.current();
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() {
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_.front(),
});
codes_.emplace_back(code);
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(),
});
while (true) {
auto curr = codes_.front();
core.next_cases(curr, cases_.find(curr)->second.mask);
codes_.pop_and_try_layer_switch();
if (codes_.is_ending()) {
return codes_.get_curr_layer() | std::views::transform([](uint64_t code) {
return RawCode::unsafe_create(code);
}) | std::ranges::to<std::vector>();
}
codes_.emplace(code);
});
while (true) {
auto curr = codes_.current();
core.next_cases(curr, cases_.find(curr)->second.mask);
codes_.next();
if (codes_.is_ending()) {
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) {
FCDemo fc {raw_code};
return fc.DoCal().value();
klotski::fast_cal::FCDemo fc {raw_code};
// return fc.DoCal().value();
// 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();
// for (const auto x : tmp) {
// std::cout << x.to_common_code() << std::endl;
// }
// auto tmp = fc.DoCalFurthest();
auto tmp = fc.DoCalFurthest();
// for (const auto x : tmp) {
// 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