c++ - 优化的 argmin : an effective way to find an item minimizing a function

标签 c++ algorithm search standard-library

假设我有一个项目集合和对它们的评分函数:

struct Item { /* some data */ };
std::vector<Item> items;
double score(Item);

我想从该集合中找到分数最低的项目。一个简单的写法是:

const auto argmin = std::min_element(begin(items), end(items), [](Item a, Item b) {
    return score(a) < score(b);
});

但如果 score 是一个计算量很大的函数,std::min_element 的事实实际上在某些项目上多次调用它可能令人担忧。这是预料之中的,因为编译器无法猜测 scorepure function .

我如何找到 argminscore 每个项目只被调用一次?记忆化是一种可能性,还有别的吗?

我的目标是编写一个易于阅读的代码片段,就像在集合上调用 std::min_element 一样显而易见。

最佳答案

正如我在上面评论的那样,如果 vector 不是太大,您可以先使用 std::transform 存储所有分数,然后应用 std::min_element

但是,如果您想利用“懒惰求值”的好处,并且仍然想使用 C++ 的 STL,可以使用一些技巧来解决。

重点是 std::accumulate 可以被视为一般的 reducefold 操作(如 foldl 在 haskell )。使用 C++17 的 std::tuple 语法糖,我们可以编写如下内容:

    auto [min_ind, _, min_value] = std::accumulate(items.begin(), items.end(),
        std::make_tuple(-1LU, 0LU, std::numeric_limits<double>::max()),
        [] (std::tuple<std::size_t, std::size_t, double> accu, const Item &s) {
            // up to this point, the index of min, the current index, and the last minimal value
            auto [min_ind, cur_ind, prev_min] = accu;
            double r = score(s);
            if ( r < prev_min ) {
                return std::make_tuple(cur_ind, cur_ind + 1, r);
            } else {
                return std::make_tuple(min_ind, cur_ind + 1, prev_min);
            }
    });

关于c++ - 优化的 argmin : an effective way to find an item minimizing a function,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48322854/

相关文章:

c++ - 什么是 undefined reference /未解析的外部符号错误,我该如何解决?

python - 树搜索 - 给定树中的两个节点,检查它们是否连接 - python

c++ - 在两个文本文件中搜索词 C++

c++ - 如果函数是在类体内定义的,我是否需要在成员函数的返回类型中指定 typename ?

c++ - Boost.Process - 如何让一个进程运行一个函数?

algorithm - 最坏情况下具有相同边界的等效数据结构(与摊销相比)

java - 尝试编写迭代算法但无法使其工作

c# - 接口(interface)上没有静态方法的解决方法或替代方法

c++ - 为什么这两个版本的代码给出不同的输出

algorithm - 找出哪个 token 属于哪个 AST 节点