Mercurial > lbo > hg > ccplay
changeset 6:90bf264f80a5
LISS / MSIS
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Sun, 12 Mar 2023 21:49:53 +0100 |
parents | a1ac40ee3a1e |
children | 202259bcb331 |
files | dynprog.cc lib/exec.cc lib/exec.h |
diffstat | 3 files changed, 123 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/dynprog.cc Sun Mar 12 16:11:39 2023 +0100 +++ b/dynprog.cc Sun Mar 12 21:49:53 2023 +0100 @@ -10,9 +10,6 @@ #include <unordered_map> #include <vector> -#include <fmt/core.h> -#include <fmt/ranges.h> - using namespace std; using MemoKey = tuple<size_t, size_t, size_t>; @@ -83,7 +80,106 @@ fmt::print("{}\n", result); } -int main(void) { +template <typename T> +size_t longest_increasing_subsequence(const vector<T> &a, size_t i, size_t prev, + size_t length, size_t &longest, + vector<size_t> &seqixs) { + longest = max(length, longest); + if (i >= a.size()) return length; + + // Need to restart series? + if (a.at(i) < a.at(prev)) { + size_t length_with_new = longest_increasing_subsequence(a, i+1, i, 1, longest, seqixs); + size_t length_with_skip = longest_increasing_subsequence(a, i+1, prev, length, longest, seqixs); + size_t result = max(length_with_new, length_with_skip); + + // If current element started the sequence: update seqixs. + if (result == length_with_new && result == longest) { + seqixs.at(0) = i; + } + // Else: current element not included in sequence. + + return result; + } else { // We can include or exclude current element i. + size_t length_with_current = longest_increasing_subsequence(a, i+1, i, length+1, longest, seqixs); + size_t length_without_current = longest_increasing_subsequence(a, i+1, prev, length, longest, seqixs); + size_t result = max(length_with_current, length_without_current); + + if (result == length_with_current && result == longest) { + seqixs.at(length) = i; + } + return result; + } +} + +// Bug: if first element is 0 or negative, may repeat last index in seqixs +template<typename T> +T max_sum_incr_subseq(const vector<T>& a, size_t i, size_t prev, size_t length, T sum, T& highest_sum, vector<size_t>& seqixs) { + highest_sum = max(sum, highest_sum); + if (i >= a.size()) return sum; + + if (a.at(i) < a.at(prev)) { + T sum_with_new = max_sum_incr_subseq(a, i+1, i, 1, a.at(i), highest_sum, seqixs); + T sum_with_skip = max_sum_incr_subseq(a, i+1, prev, length, sum, highest_sum, seqixs); + T result = max(sum_with_new, sum_with_skip); + + if (result == sum_with_new && sum_with_new == highest_sum) { + seqixs.at(0) = i; + } + + return result; + } else { + T sum_with_this = max_sum_incr_subseq(a, i+1, i, length+1, sum + a.at(i), highest_sum, seqixs); + T sum_without_this = max_sum_incr_subseq(a, i+1, prev, length, sum, highest_sum, seqixs); + T result = max(sum_with_this, sum_without_this); + + if (result == sum_with_this && sum_with_this > sum_without_this && sum_with_this == highest_sum) { + if (i == 7 && length == 3) fmt::print("{} {} {} {} {} / {} - {}\n", i, prev, length, sum, highest_sum, sum_with_this, sum_without_this); + seqixs.at(length) = i; + } + + return result; + } +} + + +template<typename T, template<typename> typename C> +void evaluate_liss(const C<T>& v) requires ranges::range<C<T>> { + vector<T> a(v.begin(), v.end()); + size_t longest = 0; + vector<size_t> seqixs(a.size()); + size_t result = timeit_f(function([&a,&longest,&seqixs]() -> size_t { return longest_increasing_subsequence(a, 0, 0, 0, longest, seqixs); }), "longest incr. subsequence"); + + fmt::print("Longest incr. subsequence has length {}/{} and has indices: {}\n", longest, result, seqixs); + + vector<T> seq(longest); + for (int i = 0; i < seq.size(); i++) + seq.at(i) = a.at(seqixs.at(i)); + fmt::print("Longest incr. subsequence is: {}\n", seq); +} + +template<typename T, template<typename> typename C> +void evaluate_msis(const C<T>& v) requires ranges::range<C<T>> { + vector<T> a(v.begin(), v.end()); + T highest = 0; + vector<size_t> seqixs(a.size()); + size_t result = + timeit_f(function([&a, &highest, &seqixs]() -> size_t { + return max_sum_incr_subseq(a, 0, 0, 0, static_cast<T>(0), highest, seqixs); + }), + "max sum incr. subsequence"); + + fmt::print("Max incr sum subseq subsequence has sum {}/{} and has indices: {}\n", highest, result, seqixs); + + vector<T> seq(seqixs.size()); + for (int i = 0; i < seq.size(); i++) { + if (i > 0 && seqixs.at(i) == 0) break; + seq.at(i) = a.at(seqixs.at(i)); + } + fmt::print("Max sum incr. subsequence is: {}\n", seq); +} + +int lcss_main(void) { vector<int> a{1,6,2,-1,3,55,2,4,23,5,6,7,8,9,10}; vector<int> b{-3, 1, 5, 7, 2, 4, -1, 3, 6, 7, 9, 11, 10}; @@ -92,3 +188,19 @@ evaluate_lcss(views::single(11), views::single(11)); return 0; } + +int liss_main(void) { + vector<int> a{0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11}; + // Expect: 0,2,6,9,13 or ,11 + // or 0,4,6,9,13 + evaluate_liss(a); + return 0; +} + +int main(void) { + vector<int> a{-1, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11}; + // Expect: 0,2,6,9,13 or ,11 + // or 0,4,6,9,13 + evaluate_msis(a); + return 0; +}
--- a/lib/exec.cc Sun Mar 12 16:11:39 2023 +0100 +++ b/lib/exec.cc Sun Mar 12 21:49:53 2023 +0100 @@ -16,7 +16,7 @@ decltype(d)::rep count = d.count(); decltype(d)::period p; - cout << name << " :: " << static_cast<double>(p.num)/p.den * count << endl; + fmt::print("{} :: {} s\n", name, static_cast<double>(p.num)/p.den * count); } void benchmarkit(function<void()> f, string name, function<void()> setup) { @@ -27,7 +27,7 @@ while (true) { setup(); - cout << "Running " << name << " for " << n << " iterations.\n"; + fmt::print("Running {} for {} iterations\n", name, n); auto begin = high_resolution_clock::now(); @@ -40,7 +40,7 @@ if (seconds < min_duration) { n *= 2; } else { - cout << n << " iterations took " << seconds << " seconds (" << seconds/n << " s/iter)\n"; + fmt::print("{} iterations took {} seconds ({} s/iter)\n", n, seconds, seconds/n); break; } }
--- a/lib/exec.h Sun Mar 12 16:11:39 2023 +0100 +++ b/lib/exec.h Sun Mar 12 21:49:53 2023 +0100 @@ -1,8 +1,10 @@ + +#include <fmt/core.h> +#include <fmt/ranges.h> #include <chrono> #include <functional> -#include <iostream> #include <string> void timeit(std::function<void()> f, std::string name = std::string()); @@ -22,6 +24,6 @@ decltype(d)::rep count = d.count(); decltype(d)::period p; - std::cout << name << " :: " << static_cast<double>(p.num)/p.den * count << std::endl; + fmt::print("{} :: {} s\n", name, static_cast<double>(p.num)/p.den * count); return result; }