gpt4 book ai didi

c++ - (如何)我可以为 Boost MultiIndex 近似 "dynamic"索引( key 提取器)吗?

转载 作者:行者123 更新时间:2023-11-30 01:00:26 25 4
gpt4 key购买 nike

我有一个 boost::shared_ptrs 的 MultiIndex 容器到类 Host 的成员。这些成员包含私有(private)数组 bool infections[NUM_SEROTYPES] 揭示宿主关于 1,...,NUM_SEROTYPES 血清型中每一个的感染状态。我希望能够在模拟中随时确定感染给定血清型的人数,但我不确定如何:

  • 理想情况下,Boost MultiIndex 允许我进行排序,例如,按 Host::isInfected( int s ),其中 s 是感兴趣的血清型.据我了解,MultiIndex key 提取器不允许采用参数。
  • 另一种方法是为每个血清型定义一个索引,但我不知道如何以这种可扩展的方式编写 MultiIndex 容器 typedef ... 。我将改变模拟之间的血清型数量。 (有经验的程序员认为这应该是可能的吗?如果是的话,我会尝试的。)
  • 有 2^(NUM_SEROTYPES) 种可能的感染状态。对于少量血清型,我可以使用基于该数字(或二进制字符串)的单个索引,并提出从该键到实际感染状态的一些映射。计数仍然很慢。
  • 我可以维护一个单独的结构来计算每个血清型的感染总数。同步有点痛苦,但内存很好。我更喜欢更灵活的选项,因为我想对其他主机属性做进一步的排序(例如,在计算感染血清型的人数后,计算也在特定家庭中并具有特定年龄的感染者人数) .

提前致谢。


更新

我要出差了,直到 5 月 5 日星期三才能检查任何答案。这意味着根据其他人的投票,谁的答案最受欢迎,谁就会赢得赏金(假设达到了某个最低阈值) )--我不会及时回来选择我认为最好的答案。出于此赏金的目的,请假设 NUM_SEROTYPES ~8-10,因此我不想使用第三个选项或任何需要一些糟糕的组合枚举的选项。我真的希望找到一种方法来根据给定血清型的宿主感染状态对 MultiIndex 进行排序。

此外,如果这是一个愚蠢的问题,我很想知道为什么。谢谢。


更新 2,5 月 6 日

这些回复很有帮助,帮助我在继续优化和自定义程序时了解我的选择。我目前无法授予赏金或解决方案,但如果可以的话,我会向 outis 提供最彻底和信息最丰富的解决方案。

我目前的策略是保持 int allInfecteds[ ALL_AGES ][ NUM_SEROTYPES ]。阵列的维护将内置到事件定义中(例如,死亡、恢复、衰老和被感染)。在按感兴趣的家庭对 MultiIndex 进行排序后,通过单独查询主机来获取特定年龄段受感染的家庭成员总数。 (相对于主机总数而言,家庭数量极少。)随着我的查询变得越来越复杂,我可能会用 multimap 替换二维数组并使用 count_if。如果我们最终用相对较少的血清型进行模拟,我可能会尝试使用下面的元编程示例或使用显式索引。

再次衷心感谢所有评论者帮助我了解各种选择及其成本。如果我尝试重建索引或下面提出的元编程解决方案,我将在此处发布结果。

最佳答案

解决方案 2(为每个血清型维护一个单独的索引可以通过一些元编程来完成:

#include <boost/mpl/push_back.hpp>
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/shared_ptr.hpp>

using namespace boost::multi_index;

struct host
{
static const int NUM_SEROTYPES=8;

bool infections[NUM_SEROTYPES];
};

typedef boost::shared_ptr<host> host_ptr;

template<typename Num>
struct infection_extractor
{
typedef bool result_type;

result_type& operator()(const host_ptr& p)const
{
return p->infections[Num::value];
}
};

typedef boost::mpl::fold<
boost::mpl::range_c<int,0,host::NUM_SEROTYPES>,
boost::mpl::vector<>,
boost::mpl::push_back<
boost::mpl::_1,
ordered_non_unique<infection_extractor<boost::mpl::_2> >
>
>::type index_list_type;

typedef multi_index_container<
host_ptr,
index_list_type
> multi_t;

template<int Num>
std::size_t infected_with(const multi_t& m)
{
return m.get<Num>().count(true);
};

typedef std::size_t (*infected_with_type)(const multi_t&);

struct infected_with_table_assigner
{
infected_with_table_assigner(infected_with_type* table):table(table)
{
boost::mpl::for_each<
boost::mpl::range_c<int,0,host::NUM_SEROTYPES>
>(*this);
}

template<typename Num>
void operator()(Num)const{table[Num::value]=&infected_with<Num::value>;}

infected_with_type* table;
};

std::size_t infected_with(const multi_t& m,int n)
{
static infected_with_type table[host::NUM_SEROTYPES];
static infected_with_table_assigner assigner(table);

return table[n](m);
}

#include <iostream>

int main()
{

multi_t m;
host h;
for(int i=0;i<200;++i){
for(int j=0;j<host::NUM_SEROTYPES;++j)h.infections[j]=(i&(1<<j))?true:false;
m.insert(host_ptr(new host(h)));
}

for(int n=0;n<host::NUM_SEROTYPES;++n)
{
std::cout<<"infected with serotype "<<n<<": "
<<infected_with(m,n)<<std::endl;
}
}

但要考虑到维护 8~10 个索引会消耗内存和插入时间。一个更简单的解决方案是只维护一个 random access index并在查询之前对其进行适当排序(使用适合每个时刻感兴趣的特定血清型的自定义比较器)。

关于c++ - (如何)我可以为 Boost MultiIndex 近似 "dynamic"索引( key 提取器)吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2694973/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com