C++ 高效计算向量组合

C++ 高效计算向量组合,c++,algorithm,vector,combinations,C++,Algorithm,Vector,Combinations,出于好奇,我正在研究一个问题,我不知道如何编程我所想的逻辑。让我向你解释一下: 我有四个向量,比如说 v1 = 1 1 1 1 v2 = 2 2 2 2 v3 = 3 3 3 3 v4 = 4 4 4 4 现在我想做的是把它们组合起来,就是 v12 = v1+v2 v13 = v1+v3 v14 = v1+v4 v23 = v2+v3 v24 = v2+v4 v34 = v3+v4 直到这一步,一切都很好。现在的问题是,我想将这些向量中的每一个都添加到v1、v2、v3、v4中的一个向量中,这

出于好奇,我正在研究一个问题,我不知道如何编程我所想的逻辑。让我向你解释一下:

我有四个向量,比如说

v1 = 1 1 1 1
v2 = 2 2 2 2
v3 = 3 3 3 3
v4 = 4 4 4 4
现在我想做的是把它们组合起来,就是

v12 = v1+v2
v13 = v1+v3
v14 = v1+v4
v23 = v2+v3
v24 = v2+v4
v34 = v3+v4
直到这一步,一切都很好。现在的问题是,我想将这些向量中的每一个都添加到v1、v2、v3、v4中的一个向量中,这是它以前没有添加过的。例如:

v3和v4还没有添加到v12中,所以我想创建v123和v124。类似地,对于所有向量

v12 should become:
v123 = v12+v3
v124 = v12+v4

v13 should become:
v132 // This should not occur because I already have v123
v134

v14 should become:
v142 // Cannot occur because I've v124 already
v143 // Cannot occur

v23 should become:
v231 // Cannot occur
v234 ... and so on.
重要的是,我不要一开始就一步到位。例如,我可以做(4选择3)4C3并完成它,但我想在每次迭代中一步一步地做

我该如何编程

注:我正在尝试数据挖掘中apriori算法的改进版本

  • 维护用于选择两个值的所有值的列表
  • 创建集合向量,使集合由原始向量中的元素和4C2元素组成。迭代原始向量,并为每个向量添加/创建一个包含步骤1中元素的集合。维护集合向量,仅当集合不存在时,才将结果添加到向量
  • 将步骤2中获得的集合向量求和
  • 但正如你所指出的,最简单的是4C3

    这里有一些用Python编写的东西。您可以将其应用于C++

    import itertools
    
    l1 = ['v1','v2','v3','v4']
    res = []
    for e in itertools.combinations(l1,2):
        res.append(e)
    
    fin = []
    for e in res:
        for l in l1:
            aset = set((e[0],e[1],l))
            if aset not in fin and len(aset) == 3:
                fin.append(aset)
    print fin
    
    这将导致:

    [set(['v1', 'v2', 'v3']), set(['v1', 'v2', 'v4']), set(['v1', 'v3', 'v4']), set(['v2', 'v3', 'v4'])]
    

    这与4C3的结果相同。

    也许我有误解,但这不等于生成1、2、3、4的所有子集(幂集),然后对幂集的每个元素求和向量吗?例如:

    //This is pseudo C++ since I'm too lazy to type everything
    //push back the vectors or pointers to vectors, etc.
    vector< vector< int > > v = v1..v4;
    
    //Populate a vector with 1 to 4
    vector< int > n = 1..4
    
    //Function that generates the power set {nil, 1, (1,2), (1,3), (1,4), (1,2,3), etc.
    vector< vector < int > > power_vec = generate_power_set(n);
    
    //One might want to make a string key by doing a Perl-style join of the subset together by a comma or something...
    map< vector < int >,vector< int > > results;
    //For each subset, we sum the original vectors together
    for subset_iter over power_vec{
        vector<int> result;
        //Assumes all the vecors same length, can be modified carefully if not.
        result.reserve(length(v1));
        for ii=0 to length(v1){
            for iter over subset from subset_iter{
                result[ii]+=v[iter][ii];
            }
        }
        results[*subset_iter] = result;
    }
    
    <代码> //这是伪C++,因为我太懒了,不能把所有的东西都打出来。 //向后推向量或指向向量的指针等。 向量v=v1..v4; //用1到4填充向量 向量n=1..4 //生成幂集{nil,1,(1,2),(1,3),(1,4),(1,2,3)等的函数。 向量>功率向量=生成功率集(n); //您可能希望通过使用逗号或其他方式对子集进行Perl风格的连接来生成字符串键。。。 映射,vector>结果; //对于每个子集,我们将原始向量相加 对于功率过大的子集{ 矢量结果; //假设所有向量长度相同,如果没有,可以仔细修改。 结果:保留长度(v1); 对于ii=0到长度(v1){ 对于子集_iter的子集上的iter{ 结果[ii]+=v[iter][ii]; } } 结果[*subset_iter]=结果; } 如果这是你的想法,你仍然需要一个幂集函数,但是如果你搜索幂集,代码很容易找到。例如,
    .

    我认为这个问题可以通过标记发生的组合来解决

    我的第一个想法是,你可以使用一个三维数组来标记发生了什么组合。但这不是很好

    一个用于标记的位数组(例如整数)怎么样?例如:

    Num 1 = 2^0 for vector 1
    Num 2 = 2^1 for vector 2
    Num 4 = 2^2 for vector 3
    Num 8 = 2^3 for vector 4
    
    进行合成时,只需将所有代表性数字相加。例如,向量124的值为:1+2+8=11。该值对于每个组合都是唯一的

    这只是我的想法,希望能对你有所帮助

    编辑:也许我对我的想法不够清楚。我会尽量解释得更清楚一些:

    1) 为每个向量指定一个代表性数字。这个数字是向量的id,并且是唯一的。此外,这些数字的每个子集的和是唯一的,这意味着如果我们有k个代表性数字的和是M,我们可以很容易地知道哪些向量参与了和

    我们通过赋值:2^0表示向量1;2^1表示向量2;2^2表示向量3,依此类推

    每M=sum(2^x+2^y+2^z+…)=(2^x或2^y或2^z或…)。我们知道向量(x+1)、(y+1)、(z+1)参与求和。这可以通过以二进制模式表示数字来轻松检查

    例如,我们知道:

    2^0=1(二进制) 2^1=10(二进制) 2^2=100(二进制)

    所以如果我们的和是10010(二进制),我们知道向量(数:10)和向量(数:10000)在和中连接

    最好的情况是,这里的和可以用“或”运算符计算,如果用二进制表示数字,这也很容易理解


    < P > 2)利用上述事实,每次计数矢量之前,可以先添加或代表其代表性的数字,然后可以像查找数组一样跟踪它们。如果查找数组中已经存在了,则可以解决这个问题。C++中的

    < P>,给出以下例程:

    template <typename Iterator>
    inline bool next_combination(const Iterator first,
                                       Iterator k,
                                 const Iterator last)
    {
       /* Credits: Thomas Draper */
       if ((first == last) || (first == k) || (last == k))
          return false;
       Iterator itr1 = first;
       Iterator itr2 = last;
       ++itr1;
       if (last == itr1)
          return false;
       itr1 = last;
       --itr1;
       itr1 = k;
       --itr2;
       while (first != itr1)
       {
          if (*--itr1 < *itr2)
          {
             Iterator j = k;
             while (!(*itr1 < *j)) ++j;
             std::iter_swap(itr1,j);
             ++itr1;
             ++j;
             itr2 = k;
             std::rotate(itr1,j,last);
             while (last != j)
             {
                ++j;
                ++itr2;
             }
             std::rotate(k,itr2,last);
             return true;
          }
       }
       std::rotate(first,k,last);
       return false;
    }
    
    模板
    内联bool next_组合(常量迭代器优先,
    迭代器k,
    常量迭代器(最后)
    {
    /*字幕:托马斯·德雷珀*/
    if((first==last)| |(first==k)| |(last==k))
    返回false;
    迭代器itr1=第一个;
    迭代器itr2=最后一个;
    ++itr1;
    if(last==itr1)
    返回false;
    itr1=最后一个;
    --itr1;
    itr1=k;
    --itr2;
    while(第一个!=itr1)
    {
    如果(*-itr1<*itr2)
    {
    迭代器j=k;
    而(!(*itr1<*j))++j;
    标准:国际热核实验堆交换(itr1,j);
    ++itr1;
    ++j;
    itr2=k;
    标准:旋转(itr1,j,最后);
    while(last!=j)
    {
    ++j;
    ++itr2;
    }
    标准:旋转(k,itr2,最后);
    返回true;
    }
    }
    标准::旋转(第一,k,最后);
    返回false;
    }
    
    然后,您可以继续执行以下操作:

    int main()
    {
       unsigned int vec_idx[] = {0,1,2,3,4};
    
       const std::size_t vec_idx_size = sizeof(vec_idx) / sizeof(unsigned int);
    
       {
          // All unique combinations of two vectors, for example, 5C2
          std::size_t k = 2;
          do
          {
             std::cout << "Vector Indicies: ";
             for (std::size_t i = 0; i < k; ++i)
             {
               std::cout << vec_idx[i] << " ";
             }
          }
          while (next_combination(vec_idx,
                                  vec_idx + k,
                                  vec_idx + vec_idx_size));
       }
    
       std::sort(vec_idx,vec_idx + vec_idx_size);
    
       {
          // All unique combinations of three vectors, for example, 5C3
          std::size_t k = 3;
          do
          {
             std::cout << "Vector Indicies: ";
             for (std::size_t i = 0; i < k; ++i)
             {
               std::cout << vec_idx[i] << " ";
             }
          }
          while (next_combination(vec_idx,
                                  vec_idx + k,
                                  vec_idx + vec_idx_size));
       }
    
       return 0;
    }
    
    intmain()
    {
    无符号int-vec_idx[]={0,1,2,3,4};
    常量std::size\t vec\u idx\u size=sizeof(vec\u idx)/sizeof(unsigned int);
    {
    //两个向量的所有唯一组合,例如5C2
    标准:尺寸k=2;
    做
    {
    
    std::难道我不能确切地理解你想说的话吗?你能详细解释一下吗?Th