/// rewire bipartite community affiliation graphs
void TAGMUtil::RewireCmtyVV(const TVec<TIntV>& CmtyVVIn, TVec<TIntV>& CmtyVVOut, TRnd& Rnd) {
    THash<TInt,TIntV> CmtyVH;
    for (int i = 0; i < CmtyVVIn.Len(); i++) {
        CmtyVH.AddDat(i, CmtyVVIn[i]);
    }
    TAGMUtil::RewireCmtyNID(CmtyVH, Rnd);
    CmtyVH.GetDatV(CmtyVVOut);
}
///Generate bipartite community affiliation from given power law coefficients for membership distribution and community size distribution.
void TAGMUtil::ConnectCmtyVV(TVec<TIntV>& CmtyVV, const TIntPrV& CIDSzPrV, const TIntPrV& NIDMemPrV, TRnd& Rnd) {
    const int Nodes = NIDMemPrV.Len(), Coms = CIDSzPrV.Len();
    TIntV NDegV,CDegV;
    TIntPrSet CNIDSet;
    TIntSet HitNodes(Nodes);
    THash<TInt,TIntV> CmtyVH;
    for (int i = 0; i < CIDSzPrV.Len(); i++) {
        for (int j = 0; j < CIDSzPrV[i].Val2; j++) {
            CDegV.Add(CIDSzPrV[i].Val1);
        }
    }
    for (int i = 0; i < NIDMemPrV.Len(); i++) {
        for (int j = 0; j < NIDMemPrV[i].Val2; j++) {
            NDegV.Add(NIDMemPrV[i].Val1);
        }
    }
    while (CDegV.Len() < (int) (1.2 * Nodes)) {
        CDegV.Add(CIDSzPrV[Rnd.GetUniDevInt(Coms)].Val1);
    }
    while (NDegV.Len() < CDegV.Len()) {
        NDegV.Add(NIDMemPrV[Rnd.GetUniDevInt(Nodes)].Val1);
    }
    printf("Total Mem: %d, Total Sz: %d\n",NDegV.Len(), CDegV.Len());
    int c=0;
    while (c++ < 15 && CDegV.Len() > 1) {
        for (int i = 0; i < CDegV.Len(); i++) {
            int u = Rnd.GetUniDevInt(CDegV.Len());
            int v = Rnd.GetUniDevInt(NDegV.Len());
            if (CNIDSet.IsKey(TIntPr(CDegV[u], NDegV[v]))) {
                continue;
            }
            CNIDSet.AddKey(TIntPr(CDegV[u], NDegV[v]));
            HitNodes.AddKey(NDegV[v]);
            if (u == CDegV.Len() - 1) {
                CDegV.DelLast();
            }
            else {
                CDegV[u] = CDegV.Last();
                CDegV.DelLast();
            }
            if (v == NDegV.Len() - 1) {
                NDegV.DelLast();
            }
            else {
                NDegV[v] = NDegV.Last();
                NDegV.DelLast();
            }
        }
    }
    //make sure that every node belongs to at least one community
    for (int i = 0; i < Nodes; i++) {
        int NID = NIDMemPrV[i].Val1;
        if (! HitNodes.IsKey(NID)) {
            CNIDSet.AddKey(TIntPr(CIDSzPrV[Rnd.GetUniDevInt(Coms)].Val1, NID));
            HitNodes.AddKey(NID);
        }
    }
    IAssert(HitNodes.Len() == Nodes);
    for (int i = 0; i < CNIDSet.Len(); i++) {
        TIntPr CNIDPr = CNIDSet[i];
        CmtyVH.AddDat(CNIDPr.Val1);
        CmtyVH.GetDat(CNIDPr.Val1).Add(CNIDPr.Val2);
    }
    CmtyVH.GetDatV(CmtyVV);
}