【问题标题】:boost::multi_index_container with random_access and ordered_uniqueboost::multi_index_container 带有 random_access 和 ordered_unique
【发布时间】:2010-12-14 13:21:38
【问题描述】:

我在让 boost::multi_index_container 同时使用随机访问和 orderd_unique 时遇到问题。 (很抱歉这个冗长的问题,但我想我应该举个例子..)

这里有一个例子:假设我想在工厂中生产 N 个对象,并且对于每个对象我都有一个需要满足的需求(这个需求在创建多索引时是已知的)。 好吧,在我的算法中,我得到了中间结果,我将其存储在以下类中:

class intermediate_result
{
private:
    std::vector<int>   parts;     // which parts are produced
    int                used_time; // how long did it take to produce

    ValueType          max_value; // how much is it worth
};

向量parts 描述了生成了哪些对象(它的长度为 N,并且它在字典上比我的 coresp 需求向量小!) - 对于每个这样的向量,我也知道 used_time。此外,我得到了这个生成对象向量的值。

我有另一个约束,所以我不能生成每个对象 - 我的算法需要在数据结构中存储多个 intermediate_result-objects。这里使用了boost::multi_index_container,因为partsused_time 描述了一个唯一的intermediate_result(它在我的数据结构中应该是唯一的)但是max_value 是另一个索引我必须考虑一下,因为我的算法总是需要intermediate_result 最高的max_value

所以我尝试将boost::multi_index_containerordered_unique&lt;&gt; 一起用于我的“parts&used_time-pair”和ordered_non_unique&lt;&gt; 用于我的max_value(不同的intermediate_result-objects 可能具有相同的值)。

问题是:决定哪个“parts&used_time-pair”更小的谓词在我的parts-vector 上使用std::lexicographical_compare,因此对于许多intermediate_result-objects 来说非常慢。 但是会有一个解决方案:我对每个对象的需求不是那么高,因此我可以在每个可能部分向量上存储中间结果,唯一地通过其used_time

例如:如果我有一个需求向量( 2 , 3 , 1),那么我需要一个数据结构来存储(2+1)*(3+1)*(1+1)=24 可能的部分向量,并且在每个这样的条目上都有不同的used_times,它们必须是唯一的! (存储最小的时间是不够的——例如:如果我的附加限制是:满足给定的生产时间)

但是如何将random_access&lt;&gt;-index 与ordered_unique&lt;&gt;-index 结合起来呢?
Example11 在这方面没有帮助我..)

【问题讨论】:

  • 哦,我忘了提:如果我在向量之前测试 used_time,则“parts&used_time-pair”唯一性的谓词不会更快。此外,我尝试使用 hashed_unique&lt;&gt; 而不是 ordered_unique&lt;&gt; - 但我必须将向量和 used_time 推送到字符串中才能使用散列(生成的 multi_index 较慢)。有没有更好的方法来使用哈希或使用自己的 random_access 数据结构(保证唯一性)与其他排序索引(对于 max_value)链接?

标签: c++ boost random-access multi-index


【解决方案1】:

要使用两个索引,您可以编写以下代码:

indexed_by<
  random_access< >,      
  ordered_unique< 
    composite_key< 
      intermediate_result,
      member<intermediate_result, int, &intermediate_result::used_time>,
      member<intermediate_result, std::vector<int>, &intermediate_result::parts>
    >
  >
>

您可以首先使用composite_key 比较used_time,仅在必要时使用vector。除此之外,请记住,您可以使用成员函数作为索引。

【讨论】:

  • 您好,谢谢您的回答,但这是否会禁止将相同的used_time 用于不同的parts-vectors?我的意思是:只有向量和 used_time 这对应该是唯一的(而不是时间本身)
  • 然后使用composite_key。更新了我的答案。
  • 举个例子:我可以编写一个自己的数据结构,其中每个可能的部分向量都有 24 个条目(对于上面的示例),并且在每个条目中都有一个 std::map&lt;used_time , max_value&gt;。这些映射可以是空的(如果没有找到这样的中间结果)。但是给定部分向量的 used_time 是唯一的。但我也必须搜索最高的 max_value!所以我想用 multi_index_container 的随机访问索引来构建这种数据结构......(哦,请阅读您对 composite_key 的评论 - 我会调查一下 - 谢谢!!)
  • 正如您所建议的,这种方法对于返回(唯一)索引的成员函数会更好。有了这个,我可以防止将lexicographical_compare 用于整数向量。谢谢!但正如我在回答/问题中提到的那样:那么我真的不需要random_access&lt;&gt; 索引,因为我没有强制该索引具有唯一性,或者我错过了什么?我希望数据结构通过get_index 函数使用恒定时间查找(特别是当我插入一个新元素时,必须检查其唯一性)。有没有办法用多索引做到这一点?
【解决方案2】:

(我不得不使用自己的答案来编写代码块 - 抱歉!)

composite_keyused_timeparts(正如 Kirill V. Lyadvinsky 建议的那样)基本上是我已经实现的。我想摆脱parts-vector 的字典比较。

假设我以某种方式存储了所需的需求,那么我可以编写一个简单的函数,它在这样的随机访问数据结构中返回正确的索引:

int get_index(intermediate_result &input_result) const
{
    int ret_value  = 0;
    int index_part = 1;
    for(int i=0;i<needed_demand.size();++i)
    {
        ret_value  += input_result.get_part(i) * index_part;
        index_part *= (needed_demand.get_part(i) + 1);
    }
}

显然,这可以更有效地实现,并且这不是满足所需需求的唯一可能的索引排序。但是让我们假设这个函数作为intermediate_result 的成员函数存在!是否可以写这样的东西来防止lexicographical_compare

indexed_by<
  random_access< >,      
  ordered_unique< 
    composite_key< 
      intermediate_result,
      member<intermediate_result, int, &intermediate_result::used_time>,
      const_mem_fun<intermediate_result,int,&intermediate_result::get_index>
    >
  >
>

如果这是可能的,并且我用所有可能的parts-vectors 初始化了多索引(即在我上面的评论中,我会在我的数据结构中推送 24 个空映射),这是否找到正确的条目给定的intermediate_result 在恒定时间内(在使用get_index 计算正确的索引之后)?
我不得不问这个,因为我不太明白random_access&lt;&gt; 索引是如何与ordered_unique&lt;&gt; 索引相关联的。。

但感谢您到目前为止的回答!

【讨论】:

  • 删除 random_access 并将 ordered_unique 替换为 hashed_unique。您将能够使用find 函数来查找标识为used_time/get_index 对的元素。或者您可以使用equal_range 查找具有指定used_time 的元素集。
  • 您可以独立使用任何索引。要通过指定索引查找元素,您应该编写container.get&lt;1&gt;().find,其中 1 是索引号。默认使用 0(例如container.find)。
  • 如果您将删除 random_access 索引,那么您将写入 container.findcontainer.equal_range
  • 使用 hashed_unique 很好,但速度并不快。 :-( 让我们做一个大胆的假设:假设used_time 受常量max_time 的限制。然后我可以轻松扩展get_index 函数为每个used_time 返回一个唯一整数(更好:std::size_t) /get_index 对。因此:如果我用所有可能的整数作为random_access&lt;&gt; 索引初始化我的数据结构并在每个条目上存储max_value(作为第二个ordered_not_unique&lt;&gt; 索引),那么我应该能够非常快速地使用它(在恒定时间内插入/查找/更新给定的唯一 get_index 结果)
  • 这种方法的问题是(当然)我必须为此使用更多的内存,因为max_time 可能非常高(相对于needed_demand 整体而言) .此外,这些条目中的大多数都不会得到有用的intermediate_result,因为该算法没有为大多数可能的used_times 提供intermediate_result
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-06
  • 1970-01-01
  • 2014-12-02
  • 1970-01-01
  • 2015-02-08
相关资源
最近更新 更多