我正在尝试编写代码来生成set中的所有子集,其中包含一个条件 如果我有阈值= 2,则设置为3:
1, 2, 3, 4, 5
1,3,5
1,3,4
然后程序将输出:
第一次迭代时的生成集:
1 = number of frequency = 3
2 = number of frequency = 1
3 = number of frequency = 3
4 = number of frequency = 2
5= number of frequency = 2
由于数字2的频率<1。阈值,我将从任何进一步的超集中排除此集合,
第二次迭代时的生成集:
1,3 = number of frequency = 3
1,4 = number of frequency = 2
1,5 = number of frequency = 2
3,4 = number of frequency = 2
3,5= number of frequency = 2
4,5= number of frequency = 1
由于数字(4,5)的频率<1。阈值,我将从任何进一步的超集中排除此集合,
第三次迭代的生成集
1,3,4= number of frequency = 2
1,3,5= number of frequency = 2
第四次迭代的生成集
不再是超集,因为(4,5)&lt;我们无法生成的门槛(1,3,4,5)
我编写了程序,我已经生成了所有子集,但是失败了两件事:
std::map <int,std::pair<list<int>,
int>> CandList
中搜索相似的集合(频率数)请感谢任何帮助。
这是我的代码:
int threshold = 2;
std::vector<std::list<int>> data;
std::map<int, int> FISupp;
typedef std::pair<list<int>, int> combo;
std::map <int,combo> CandList;
std::list<int> FrqList;
/*
input:Threshold =2, and data=
1 2 3 4 5
1 3 4 5
1 2 3 5
1 3
at first scan after PassOne function:
FISupp(1,4)
FISupp(2,2)
FISupp(3,4)
FISupp(4,4)
FISupp(5,3)
at k scan after Passk function:
---
*/
int Lsize = 2; // Level size
void ScanData()
{
ifstream in;
in.open("mydata.txt");
/* mydata.txt
1 2 3 4 5
1 3 4 5
1 2 3 5
1 3
*/
std::string line;
int i = 0;
while (std::getline(in, line))
{
std::stringstream Sline1(line);
std::stringstream ss(line);
std::list<int> inner;
int info;
while (ss >> info)
inner.push_back(info);
data.push_back(inner);
}
}
/* first pass to generate first Candidates items */
void PassOne()
{
for (unsigned i = 0; i < data.size(); ++i)
{
std::list<int>::iterator li;
for (li = data[i].begin(); li != data[i].end(); ++li)
FISupp[*li] += 1;
}
/*update the FFISupp by erasing all first Candidates items with support < Threshold*/
std::map<int, int> ::iterator current = FISupp.begin();
std::list<int> ls; /* save Candidates itemes with support < Threshold*/
while (current != FISupp.end())
{
if (current->second < threshold)
{
ls.push_back(current->first);
current = FISupp.erase(current);
}
else
++current;
}
/*update the the orginal data by erasing all first Candidates items with support < Threshold*/
for (unsigned i = 0; i < data.size(); ++i)
{
std::list<int>::iterator li;
std::list<int>::iterator item = ls.begin();
while (item != ls.end())
{
for (li = data[i].begin(); li != data[i].end(); ++li)
{
if (*li == *item)
{
li = data[i].erase(li);
break;
}
}
++item;
}
}
}
void FrequentItem(list<int> l, int indx)
{
int a = 0;
for (list<int>::iterator it = l.begin(); it != l.end(); ++it)
{
//std::list <int> &m2 = CandList[indx].first;
//auto itr = m2.find(*it);
//auto itr = std::find(CandList.begin(), CandList.end(), *it);
auto itr = CandList.find(*it);
if (itr != CandList.end())
{
a += CandList[indx].second;
CandList[indx].first.push_back(*it);
CandList[indx].second = a;
}
}
}
int ind = 0;
void Passk(int j, std::list<int>::iterator Itm , int q = 0)
{
if (Lsize == q)
{
FrequentItem(FrqList, ind);
++ind;
return;
}
else
{
for (std::list<int>::iterator Itm2 = Itm; Itm2 != data[j].end(); ++Itm2)
{
FrqList.push_back(*Itm2);
Passk(j, ++Itm2, q + 1);
FrqList.pop_back();
--Itm2;
}
}
}
void main(int argc, char *argv[])
{
int temp = 0;
int j = -1;
ScanData();
PassOne();
while (Lsize <= data.size()) // How to stop the loop when there is no more candidate >= threshold???
{
for (unsigned i = 0; i < data.size(); ++i)
{
std::list<int>::iterator items = data[i].begin();
Passk(++j, items);
}
j = -1;
++ Lsize;
}
data.clear();
system("PAUSE");
return;
}
答案 0 :(得分:3)
好的,我会尝试回答。但首先是假设:
对于这种情况,通过位向量对您的集进行编码可能更自然(例如使用std::vector<bool>
或boost::dynamic_bitset<>
)。在这样的位向量中,如果设置了i
- 元素,则意味着集合中存在数字i
。
例如,您的三个集由此
表示1 1 1 1 1
1 0 1 0 1
1 0 1 1 0
迭代1 :在第一次迭代中,您只需要对元素求和,这在此表示中相当容易。一个人获得
1 1 1 1 1
1 0 1 0 1
1 0 1 1 0
-----------
3 1 3 2 2
接下来,您丢弃低于阈值的所有元素,这只是将第二行设置为零:
1 0 1 1 1
1 0 1 0 1
1 0 1 1 0
迭代K :在这里,您计算所有K子集的出现次数,如果它们的数量小于阈值则丢弃它们。也就是说,正式地,你生成了K-stencils
{ 1 1 0 0 0, 1 0 1 0 0, ... , 0 0 0 1 1} (for K=2)
{ 1 1 1 0 0, 1 1 0 1 0, ... , 0 0 1 1 1} (for K=3)
等等。对于这些K
- 模板中的每一个,您计算出现并最终丢弃(注意K
也可能是一个)。所以,你有三个任务,即
生成:是通过初始位向量{1 ... 1 0 ... 0}
的排列获得的,其中K
元素在左侧排序。
计数:循环遍历集合的向量,并使用按位and
检查当前向量是否包含模板。例如:1 0 1 1 1 & 0 0 0 1 1 == 0 0 0 1 1
?
丢弃:通过按位and
应用反向模板(通过flip()
进行反转)。这将删除相关的子集。最后丢弃小于迭代次数的任何子集(例如,在迭代3中,删除大小为2的子集)。
这是一个主要使用boost::dynamic_bitset<>
,但std::vector<bool>
用于排列的实现(因为我不想自己编码排列,但这当然可以改进)。请注意,没有地图或其他更复杂的存储方案:
#include<vector>
#include<iostream>
#include<algorithm>
#include<string>
#include<sstream>
#include<boost/dynamic_bitset.hpp>
//only for nice output of a bitset
std::string screenOutput(const boost::dynamic_bitset<>& bits)
{
int n=bits.size();
std::string ret;
for(int i=n-1;i>=0;--i)
{
if(bits[i])
{
std::stringstream out;
out<<i+1<<" ";
ret=out.str()+ret;
}
}
return "{"+ret+"}";
}
//function implementing the actual logic
void removeSubsets(std::vector<boost::dynamic_bitset<> > ¤tSet, size_t K, size_t thresh)
{
size_t n=currentSet.front().size();
//create initial stencil {1 ... 1 0 ... 0}
std::vector<bool> stencil(n);
for(size_t i=0;i<K;++i)
stencil[i]=true;
//apply permutations to initial stencil
do
{
//generate dynamic_bitset from permuted vector<bool>
boost::dynamic_bitset<> temp(n);
for(size_t i=0;i<n;++i)
temp[i]=stencil[i];
//count the occurence of the stencil
size_t count=0;
for(size_t j=0;j<currentSet.size();++j)
{
if((currentSet[j] & temp) == temp)
++count;
}
//remove if at least one and less than thresh is found
if(count<thresh && count>0)
{
boost::dynamic_bitset<> tempFlip=temp;
tempFlip.flip();
for(size_t j=0;j<currentSet.size();++j)
{
//remove stencil from all bitset which contain it
if((currentSet[j] & temp) == temp)
currentSet[j]= (currentSet[j] & tempFlip);
}
}
}
while(std::prev_permutation(stencil.begin(),stencil.end()));
//further remove all supersets which contain less than K elements
for(size_t j=0;j<currentSet.size();++j)
if(currentSet[j].count()<K)
{
currentSet[j]=boost::dynamic_bitset<>(n,0);
}
}
代码可以像这样使用:
int main()
{
//initialize set of three bit-vectors (all elements to true)
std::vector<boost::dynamic_bitset<> > yourSet(3, boost::dynamic_bitset<>(5, (1<<5)-1) );
//set corresponding elements to false
yourSet[1][1]=false;
yourSet[1][3]=false;
yourSet[2][1]=false;
yourSet[2][4]=false;
std::cout<<"Original sets"<<std::endl;
for(size_t i=0;i<3;++i)
std::cout<<screenOutput(yourSet[i])<<std::endl;
std::cout<<std::endl;
removeSubsets(yourSet, 1, 2);
std::cout<<"After iteration 1:"<<std::endl;
for(size_t i=0;i<3;++i)
std::cout<<screenOutput(yourSet[i])<<std::endl;
std::cout<<std::endl;
removeSubsets(yourSet, 2, 2);
std::cout<<"After iteration 2:"<<std::endl;
for(size_t i=0;i<3;++i)
std::cout<<screenOutput(yourSet[i])<<std::endl;
std::cout<<std::endl;
removeSubsets(yourSet, 3, 2);
std::cout<<"After iteration 3:"<<std::endl;
for(size_t i=0;i<3;++i)
std::cout<<screenOutput(yourSet[i])<<std::endl;
std::cout<<std::endl;
}
输出:
Original set:
{1 2 3 4 5}
{1 3 5}
{1 3 4}
After iteration 1:
{1 3 4 5}
{1 3 5}
{1 3 4}
After iteration 2:
{}
{1 3 5}
{1 3 4}
After iteration 3:
{}
{}
{}
伙计,我显然有太多时间。
编辑:更正后的代码。仍然你必须检查它是否真正带来你想要的东西。