From f990c9857e5d29f44cb855bbe0a345f6f80e0b54 Mon Sep 17 00:00:00 2001 From: Dnomd343 Date: Fri, 20 Jan 2023 16:27:10 +0800 Subject: [PATCH] perf: speed up backtrack --- src/analyse/backtrack.cc | 148 ++++++++++++++++++++++++--------------- 1 file changed, 91 insertions(+), 57 deletions(-) diff --git a/src/analyse/backtrack.cc b/src/analyse/backtrack.cc index af81378..5b7422a 100644 --- a/src/analyse/backtrack.cc +++ b/src/analyse/backtrack.cc @@ -5,32 +5,54 @@ #include #include +#include + #include "common_code.h" // TODO: using const RawCode& instead of uint64_t -namespace std { - template<> - struct hash { - std::size_t operator()(const Analyse::backtrack_t &b) const { - std::cout << "get hash: " << b.code << std::endl; - return std::hash()(b.code); +//namespace std { +// template<> +// struct hash { +// std::size_t operator()(const Analyse::backtrack_t &b) const { +// std::cout << "get hash: " << b.code << std::endl; +// return std::hash()(b.code); +// } +// }; +// +// template<> +// struct equal_to { +// bool operator()(const Analyse::backtrack_t &b1, const Analyse::backtrack_t &b2) const { +// std::cout << "get eq: " << b1.code << " ? " << b2.code << std::endl; +// return b1.code == b2.code; +// } +// }; +//} + +void Analyse::backtrack_demo(const std::vector &codes) { + + + std::vector> todos; + + for (const auto &code : codes) { + + auto c = cases.find(code); + + if (c == cases.end()) { + // TODO: invalid input + return; } - }; - template<> - struct equal_to { - bool operator()(const Analyse::backtrack_t &b1, const Analyse::backtrack_t &b2) const { - std::cout << "get eq: " << b1.code << " ? " << b2.code << std::endl; - return b1.code == b2.code; + if (c->second.step >= todos.size()) { + todos.resize(c->second.step + 1); } - }; -} -void Analyse::backtrack_demo(const std::vector &codes) { + todos[c->second.step].emplace_back(&c->second); + + } + + std::reverse(todos.begin(), todos.end()); - // TODO: confirm code exist -// std::cout << cases[code].step << std::endl; struct cache_t { analyse_t *a; @@ -40,61 +62,73 @@ void Analyse::backtrack_demo(const std::vector &codes) { std::queue track_cache; std::vector> track_data; - track_data.resize(82); // TODO: setting as (max steps + 1) +// track_data.resize(82); // TODO: setting as (max steps + 1) + track_data.resize(todos.size()); // TODO: for diff layer cases, layer_num from big to small -> if found then skip search - for (const auto &code : codes) { - - auto &cc = cases[code]; + for (const auto &todo : todos) { - /// enlarge track_data - if (cc.step >= track_data.size()) { - track_data.resize(cc.step + 1); + if (todo.empty()) { + continue; } - track_cache.emplace(cache_t { - .a = &cc, - .b = &track_data[cc.step].emplace(code, backtrack_t { - .code = code, - .layer_num = cc.step, - .last = std::list{}, - .next = std::list{}, - }).first->second, - }); + /// clear track cache + std::queue{}.swap(track_cache); - } + for (const auto c : todo) { + + // TODO: if c already exist -> skip + if (track_data[c->step].find(c->code) == track_data[c->step].end()) { - while (!track_cache.empty()) { - /// handle first element and pop it - auto curr = track_cache.front(); - for (auto src : curr.a->src) { // traverse src cases of current node - auto t_src = track_data[src->step].find(src->code); - if (t_src != track_data[src->step].end()) { // match src case - /// link (curr.b) and (t_src->second) - t_src->second.next.emplace_back(curr.b); - curr.b->last.emplace_back(&t_src->second); - } else { // src case not found - /// link (curr.b) and (t_src_new->second) - auto t_src_new = track_data[src->step].emplace(src->code, backtrack_t { - .code = src->code, - .layer_num = src->step, - .last = std::list{}, - .next = std::list{curr.b}, // link to curr.b - }).first; - curr.b->last.emplace_back(&t_src_new->second); - /// insert into working queue - track_cache.emplace(cache_t { - .a = src, - .b = &t_src_new->second, + track_cache.emplace(cache_t{ + .a = c, + .b = &track_data[c->step].emplace(c->code, backtrack_t{ + .code = c->code, + .layer_num = c->step, + .last = std::list{}, + .next = std::list{}, + }).first->second, }); } + + } + + + while (!track_cache.empty()) { + /// handle first element and pop it + auto curr = track_cache.front(); + for (auto src : curr.a->src) { // traverse src cases of current node + auto t_src = track_data[src->step].find(src->code); + if (t_src != track_data[src->step].end()) { // match src case + /// link (curr.b) and (t_src->second) + t_src->second.next.emplace_back(curr.b); + curr.b->last.emplace_back(&t_src->second); + } else { // src case not found + /// link (curr.b) and (t_src_new->second) + auto t_src_new = track_data[src->step].emplace(src->code, backtrack_t { + .code = src->code, + .layer_num = src->step, + .last = std::list{}, + .next = std::list{curr.b}, // link to curr.b + }).first; + curr.b->last.emplace_back(&t_src_new->second); + /// insert into working queue + track_cache.emplace(cache_t { + .a = src, + .b = &t_src_new->second, + }); + } + } + track_cache.pop(); } - track_cache.pop(); + + } + for (uint32_t i = 0; i < track_data.size(); ++i) { const auto &ly = track_data[i];