这是我参与「第三届青训营 -后端场」笔记创作活动的第3篇笔记
负数据库数据生成算法
负数据库介绍
正数据库(Positive database ,DB) :传统的数据库,负数据库(Negative database ,NDB ) : 由Esponda等人于2004年提出 DB的补集的压缩表示 全集
负数据库(NDB):
- 通配符 * 可任意表示 ‘0’ 、 ‘1’
- 确定位0、1;不确定位*
- 使用 * 缩补集UDB
- NDB的大小可以压缩到合理范围内o(DB)
- 不是所有负数据库都存储UDB中 的所有内容
如图:
隐藏串:
- 藏串对应位相同的确定位称为取正位,反之则叫做取反位。
- 藏串的个数:单串负数据库、多串负数据库。
单串数据库常用生成算法
- q-hidden算法([1] Jia H, Moore C, Strain D. Generating hard satisfiable formulas by hiding solutions deceptively[C]. National Conference on Artificial Intelligence, 2005: 384-389)
- p-hidden算法 ([2] Ran Liu, Wenjian Luo and Lihua Yue. "The p-hidden Algorithm: Hiding Single Databases More Deeply." Immune Computation, vol. 2(1), pp. 43-55, 2014)
- K-hidden算法(Dongdong Zhao, Wenjian Luo and Lihua Yue. "A fine-grained algorithm for generating hard-to-reverse negative databases." 2015 International Workshop on Artificial Immune Systems (AIS). IEEE, 201)
k-hidden算法原理与实现
算法原理
c++实现
#define K_HIDDEN
#include <vector>
#include<string>
#include <unordered_set>
class k_hidden {
public:
k_hidden(double r,int k,std::string s);
private:
int N;
int m;
double r;
int k;
std::vector<double> Qi;
std::string s;
std::string ndbs;
int findI(double qi, std::vector<double> q);
std::string generateKString(int k);
public:
std::unordered_set<std::string> NDB;
void generateNDB();
};
#endif // !K_HIDDEN
#include <iostream>
#include <fstream>
#include <windows.h>
#include"k-hidden.h"
k_hidden::k_hidden(double r,int k, std::string s):r(r),s(s),k(k) {
this->m = s.length();
this->N = m * r;
ndbs = std::string(m, '*');
Qi.resize(k);
Qi[0]= 1 / double(k);
for (int i = 1;i < k - 1;i++) {
Qi[i] =Qi[i-1]+ 1 / double(k);
}
Qi[k - 1] = 1;
}
void k_hidden::generateNDB() {
srand(unsigned(time(NULL)));
while (NDB.size() < N) {
double qi = rand() / double(RAND_MAX);
int i = findI(qi, Qi);
std::string ndbstr=generateKString(i+1);
NDB.insert(ndbstr);
}
}
int k_hidden::findI(double qi,std::vector<double> q) {
int l = 0, r = q.size() - 1;
while (l < r) {
int mid = (l + r) >> 1;
if (q[mid] < qi) {
l = mid + 1;
}
else {
r = mid;
}
}
return l;
}
std::string k_hidden::generateKString(int category){
std::string kstr=ndbs;
std::unordered_set<int> st;
std::vector<int> randCertain;
srand(unsigned(time(NULL)));
int j = 0;
while (st.size() != k) {
j = rand() % m;
if (st.count(j)) {
continue;
}
else {
kstr[j] = s[j];
st.insert(j);
randCertain.emplace_back(j);
}
}
st.clear();
while (st.size() != category) {
j = rand() % k;
if (st.count(j)) {
continue;
}
else {
st.insert(j);
kstr[randCertain[j]] = kstr[randCertain[j]] == '0' ? '1' : '0';
}
}
return kstr;
}
int main() {
std::string s = "1111010101101";
std::fstream myFile;
DWORD t1, t2;
myFile.open("saldina.txt", std::ios::out);
t1 = GetTickCount();
k_hidden khd(6.5,4,s);
khd.generateNDB();
t2 = GetTickCount();
for (auto s : khd.NDB) {
myFile << s << std::endl;
}
myFile.close();
std::cout << (double)(t2 - t1) << std::endl;
}