#include #include #include #include #include #include #include #include #include #include #include #include "common.hh" namespace param { using namespace ::args; ArgumentParser parser { "converter: feature code probability matrix -> feature code" }; HelpFlag help { parser, "help", "display this menu", {'h', "help"}, }; ValueFlag smap { parser, "path", "step map file path", {"smap"}, }; Flag output_prob { parser, "output-prob", "prints path probability at last", {"output-prob", "prob"}, }; } // namespace param static void Exec() { const auto fprobs = ReadMatrix(std::cin); Enforce(fprobs.size() > 0 && fprobs[0].size() > 0, "empty matrix"); const auto dur = fprobs.size(); const auto n = fprobs[0].size(); std::ifstream smap_st {args::get(param::smap)}; Enforce(!!smap_st, "smap path is invalid"); const auto smap = ReadMatrix(smap_st); Enforce(smap.size() >= dur*n, "smap row shortage"); struct Step { double prob = -1; size_t from = 0; }; std::vector steps((dur+1)*n); for (size_t i = 0; i < n; ++i) { steps[i].prob = fprobs[0][i]; } for (size_t t = 1; t < dur; ++t) { Enforce(fprobs[t].size() == n, "ill-formed matrix"); for (size_t i = 0; i < n; ++i) { const auto& cur = steps[(t-1)*n + i]; for (auto j : smap[(t-1)*n+i]) { auto& next = steps[t*n + j]; const auto sum = cur.prob + fprobs[t][j]; if (next.prob < sum) { next.prob = sum; next.from = i; } } } } double max_prob = -1; size_t max_idx = 0; for (size_t i = 0; i < n; ++i) { const auto& step = steps[(dur-1)*n + i]; if (max_prob < step.prob) { max_prob = step.prob; max_idx = i; } } std::vector path = {max_idx}; path.reserve(dur); for (size_t t = dur-1; t > 0; --t) { path.push_back(steps[t*n + path.back()].from); } for (auto itr = path.rbegin(); itr < path.rend(); ++itr) { std::cout << *itr << '\n'; } if (param::output_prob) { std::cout << max_prob/static_cast(path.size())*100 << "%" << std::endl; } } int main(int argc, char** argv) try { param::parser.ParseCLI(argc, argv); Exec(); return EXIT_SUCCESS; } catch (const args::Help&) { std::cout << param::parser << std::endl; return EXIT_SUCCESS; } catch (const std::exception& e) { std::cerr << e.what() << std::endl; return EXIT_FAILURE; }