为boost::dynamic_bitset生成哈希,并将哈希转换回boost::dynamic_bitset

Generate hash for boost::dynamic_bitset and convert hash back to boost::dynamic_bitset

本文关键字:哈希 bitset boost dynamic 转换      更新时间:2023-10-16

我希望生成一个boost::dynamic_bitset哈希,以便将值存储在boost::bimaps中。我尝试了以下代码,在这里测试代码。

#include <iostream>
#include <boost/dynamic_bitset.hpp>
#include <unordered_map>
#include <boost/bimap.hpp>
#include <boost/bimap/unordered_set_of.hpp>
#include <boost/bimap/unordered_multiset_of.hpp>
#include <boost/bimap/set_of.hpp>
#include <boost/bimap/multiset_of.hpp>
#define BOOST_DYNAMIC_BITSET_DONT_USE_FRIENDS
namespace boost {
template <typename B, typename A>
std::size_t hash_value(const boost::dynamic_bitset<B, A>& bs) {
return boost::hash_value(bs.m_bits);
}
}
namespace bimaps = boost::bimaps;
typedef boost::bimap<bimaps::unordered_set_of<unsigned long long int>,
bimaps::unordered_multiset_of<size_t> > bimap_reference;
typedef bimap_reference::value_type position;
bimap_reference reference_index_vector;
int main()
{
std::string str = "1011010001101101000001101101000011111111011010000011011010000111111111110110100011011010000011011010000111111110110100000110110100001111111111";
boost::dynamic_bitset<>  bits = boost::dynamic_bitset<> (str);
std::cout << "bitmap " << bits << std::endl;
std::cout << "Number of bits " << bits.count() << std::endl;
size_t hash1 = boost::hash_value (bits);
std::cout << "Hash value "  << hash1 << std::endl;

/* Insert hash value in bimap
*
*/
//    reference_index_vector.insert(position(10000000000, hash1));
//    for( bimap_reference::const_iterator iter = reference_index_vector.begin(), iend = reference_index_vector.end();
//            iter != iend; ++iter ) {
//        std::cout << iter->left << " <--> "<< iter->right <<std::endl;
//    }
return 0;
}

我得到错误

在/usr/include/boost/dynamic_bitset.hp:15:0,from 3:在'std::size_t boost::hash_value(const-boost::dynamic_bitset&)的实例化中[其中B=长无符号int;A=std::分配器;std::size _t=长无签名int]':34:40:从这里开始需要/usr/include/brust/dynamic_bitset/dynamic_bitset.hp:422:17:错误:'boost:buffer_type boost::dynamic_bitset<>::m_bits'是专用buffer_type m_bits;^16:37:错误:在此上下文中

不确定出了什么问题。

  1. 如何哈希boost::dynamic_bitset
  2. 如何将哈希转换回原始比特集
  3. 所需的总空间(计数为0和1或仅为1)。上述代码仅通过bits.count()显示80位。我尝试了以下方法来生成哈希值,但不确定需要多少空间

此外,我试图通过以下代码生成比特集的哈希值

/*Generating hash by bitset
* 
*/
std::bitset<142> seq (str);
std::hash<std::bitset<142>> hash_bitset;
std::cout << "Bitset " << seq << std::endl;
std::cout << "Hash value " << hash_bitset(seq) << std::endl; 
#Bitset 1011010001101101000001101101000011111111011010000011011010000111111111110110100011011010000011011010000111111110110100000110110100001111111111
#Hash value 4886653603414440856

好吧,我发现了很多关于"哈希"本质的困惑,所以有几个友好的指针可以开始:

Q2。如何将哈希转换回原始比特集。

这是不可能的。散列是有损摘要。只有当哈希是完美哈希时,才能执行此操作。由于熵定律,如果比特集容量超过平台上size_t的大小(通常为32或64比特),则无法执行完美哈希。

Q我还尝试通过…创建一个散列。。。

std::bitset<142> seq (str);
....

我希望你意识到std::bitset<>是一种完全不同的类型,所以它与任务并没有真正的关系。而且,由于它不是动态的,它对任务毫无帮助,即使是作为一种变通方法。

但最重要的是:

哈希表(如unordered_*<>)使用,但它们未存储。哈希是有损的摘要,只用于在内部桶上获得良好的分布。对于实际元素相等,std::equal<T>使用

换句话说:

typedef boost::bimap<bimaps::unordered_set_of<unsigned long long int>,
bimaps::unordered_multiset_of<size_t> > bimap_reference;

不适合创建除size_tunsigned long long²以外的任何对象的映射。如果你在那里存储东西的散列:

reference_index_vector.insert(position(10000000000, hash1));

,您将丢失原始信息。无法从hash1获取位集。

编译器错误

您的hash_value实现错误地使用了dynamic_bitset<>的私有成员。你不能,因为它不可访问。

下面是一个使用公共接口的std::hash<>的简单实现:

在Coliru上直播

#include <boost/dynamic_bitset.hpp>
#include <boost/functional/hash.hpp>
#include <unordered_map>
#include <sstream>
namespace std {
template <typename Block, typename Alloc> struct hash<boost::dynamic_bitset<Block, Alloc> > {
size_t operator()(boost::dynamic_bitset<Block, Alloc> const& bs) const {
size_t seed = boost::hash_value(bs.size());
std::vector<Block> blocks(bs.num_blocks());
boost::hash_range(seed, blocks.begin(), blocks.end());
return seed;
}
};
}
int main() {
boost::dynamic_bitset<> x, y;
x.resize(rand()%100, 1);
y.resize(rand()%100, 0);
std::unordered_map<boost::dynamic_bitset<>, std::string> m;
m[x] = "x";
m[y] = "y";
}

您可以使用此std::hash<>专业化,并将boost::bimap与之一起使用。

注意,使用公共接口不是最佳的,因为它复制了Blocks(您也使用了std::bitset<>破解)。您可能对我之前为boost::dynamic_bitset<>所做的Boost序列化实现感兴趣:

  • 如何序列化boost::dynamic_bitset
  • 这里的代码展示了如何使用Serialization实现来高效地实现哈希哈希任意精度值(boost::multiprecision::cpp_int)

为了简单起见,假设使用bucket而不是"开放寻址"样式。同样的逻辑也适用于此,但稍微复杂一些

²(顺便说一下,请说uintmax_tuint64_t)