// File: sjain12[P]CliqueCounting/tests/../Escape/CliquesColorCoding.h
// Function: cliques_color_coding(Escape::CGraph&, CDAG&, std::basic_ofstream<char, std::char_traits<char>>&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, int)
void cliques_color_coding(CGraph &CG, CDAG &DG, ofstream &of, string gname, string fname, int clique_size)
{    
    high_resolution_clock::time_point t_elim_s = high_resolution_clock::now();
    
    Stack* stack = newStack();
    VertexSet *path = NULL, *nbrs = NULL;
    vector<VertexIdx> color;
    color.resize(CG.nVertices);
    double num_cliques = 0, est = 0;
    std::random_device rd{}; // use to seed the rng 
    std::mt19937 rng{rd()}; // rng

    std::uniform_int_distribution<int> distribution(0,clique_size-1);
    int col = 0;
    for (VertexIdx i=0; i<CG.nVertices; i++)
    {
        col = distribution(rng); 
        color[i] = col;
    }

    for (VertexIdx c=0; c<CG.nVertices; c++)
    {
        path = newVertexSet(1);
        path->vertices[0] = c;
        nbrs = newVertexSet(DG.outlist.offsets[c+1] - DG.outlist.offsets[c]);
        std::copy(DG.outlist.nbors+DG.outlist.offsets[c], DG.outlist.nbors+DG.outlist.offsets[c+1], nbrs->vertices);
        PartialClique* pc = newPartialClique(path, nbrs);
        stack->push(pc);

        StackItem* si = stack->pop();
        while (si != NULL)
        {
            path = si->pc->path;
            nbrs = si->pc->nbrs;  // get the current path and its nbrs
            VertexIdx psize = path->nVertices, nsize = nbrs->nVertices;

            if (psize + nsize < clique_size)
            {
            }
            else if (psize == clique_size)
            {   
                num_cliques++;
            }
            else
            {
                for (VertexIdx i=0; i<nsize; i++)
                {
                    VertexIdx v = nbrs->vertices[i];
                    int flag = 0;
                    for (int j=0; j<psize; j++)
                    {
                        if (color[path->vertices[j]] == color[v])
                        {
                            flag = 1;
                            break;
                        }
                    }
                    if (flag == 1) continue;

                    VertexSet *new_path = newVertexSet(psize+1);
                    std::copy(path->vertices, path->vertices + psize, new_path->vertices);
                    new_path->vertices[path->nVertices] = v;   //added i to path

                    int s = DG.outlist.offsets[v+1]-DG.outlist.offsets[v], l = nsize;
                    if (l < s)
                    {
                        l = s;
                        s = nsize;
                    }

                    VertexSet *common = newVertexSet(s);
                    int k = 0, offset = DG.outlist.offsets[v];
                    for (int l =0; l < nbrs->nVertices; l++) {
                        for (int j=0; j<DG.outlist.offsets[v+1]-DG.outlist.offsets[v]; j++) {
                            if (nbrs->vertices[l] == DG.outlist.nbors[offset + j])
                            {
                                common->vertices[k] = nbrs->vertices[l];
                                k++;
                                break;
                            }
                        }
                    }

                    common->nVertices = k; 
                    PartialClique *pc = newPartialClique(new_path, common);
                    stack->push(pc);
                }
            }
            
        	if (nbrs->nVertices >= 0) delete[] nbrs->vertices;
            delete nbrs;
            if (path->nVertices > 0) delete[] path->vertices;
            delete path;
            delete si->pc;
            delete si;
            si = stack->pop();
        }
    }

    delStack(stack);

    high_resolution_clock::time_point t_elim_e = high_resolution_clock::now();
    auto duration_program = std::chrono::duration_cast<std::chrono::microseconds>( t_elim_e - t_elim_s ).count();
    
    double kfac = 1;

    for (int i=1; i<=clique_size; i++)
        kfac *= i;
    est = num_cliques * pow(clique_size, clique_size) / kfac; 

    cout << "time reqd: " << duration_program << endl;
	cout << "number of cliques = " << num_cliques << endl;
	cout << "clique size = " << clique_size << endl;
    cout << "estimated number of cliques = " << est << endl;

	of << clique_size << "," << est << "," << duration_program << "," << endl;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x2970, %rsp           # imm = 0x2970
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movl %r9d, -0x2c(%rbp)
callq 0x3060
movq %rax, -0x38(%rbp)
callq 0x4370
movq %rax, -0x40(%rbp)
movq $0x0, -0x48(%rbp)
movq $0x0, -0x50(%rbp)
leaq -0x68(%rbp), %rdi
movq %rdi, -0x2858(%rbp)
callq 0x5d30
movq -0x2858(%rbp), %rdi
movq -0x8(%rbp), %rax
movq (%rax), %rsi
callq 0x5d50
jmp 0x460a
movq $0x0, -0x80(%rbp)
movq $0x0, -0x88(%rbp)
leaq -0x1410(%rbp), %rdi
callq 0x5de0
jmp 0x462b
leaq -0x1410(%rbp), %rdi
callq 0x5e80
movl %eax, -0x285c(%rbp)
jmp 0x463f
movl -0x285c(%rbp), %eax
movl %eax, %eax
movl %eax, %esi
leaq -0x2798(%rbp), %rdi
callq 0x5ea0
jmp 0x4657
movl -0x2c(%rbp), %edx
decl %edx
leaq -0x27a0(%rbp), %rdi
xorl %esi, %esi
callq 0x5ed0
jmp 0x466c
movl $0x0, -0x27a4(%rbp)
movq $0x0, -0x27b0(%rbp)
movq -0x27b0(%rbp), %rax
movq -0x8(%rbp), %rcx
cmpq (%rcx), %rax
jge 0x4726
leaq -0x27a0(%rbp), %rdi
leaq -0x2798(%rbp), %rsi
callq 0x5f00
movl %eax, -0x2860(%rbp)
jmp 0x46b0
movl -0x2860(%rbp), %eax
movl %eax, -0x27a4(%rbp)
movslq -0x27a4(%rbp), %rax
movq %rax, -0x2868(%rbp)
movq -0x27b0(%rbp), %rsi
leaq -0x68(%rbp), %rdi
callq 0x5f30
movq -0x2868(%rbp), %rcx
movq %rcx, (%rax)
movq -0x27b0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x27b0(%rbp)
jmp 0x4681
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x5025
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x1410(%rbp), %rdi
callq 0x6060
jmp 0x5025
movq $0x0, -0x27b8(%rbp)
movq -0x27b8(%rbp), %rax
movq -0x8(%rbp), %rcx
cmpq (%rcx), %rax
jge 0x4d08
movl $0x1, %edi
callq 0x3ff0
movq %rax, -0x2870(%rbp)
jmp 0x4758
movq -0x2870(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x27b8(%rbp), %rcx
movq -0x48(%rbp), %rax
movq 0x8(%rax), %rax
movq %rcx, (%rax)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rcx
movq -0x27b8(%rbp), %rdx
movq (%rcx,%rdx,8), %rax
movq 0x8(%rcx,%rdx,8), %rdi
subq %rax, %rdi
callq 0x3ff0
movq %rax, -0x2878(%rbp)
jmp 0x479e
movq -0x2878(%rbp), %rax
movq %rax, -0x50(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rcx
movq 0x18(%rax), %rax
movq -0x27b8(%rbp), %rsi
movq (%rcx,%rsi,8), %rdx
movq 0x8(%rcx,%rsi,8), %rcx
leaq (%rax,%rdx,8), %rdi
leaq (%rax,%rcx,8), %rsi
movq -0x50(%rbp), %rax
movq 0x8(%rax), %rdx
callq 0x5f50
jmp 0x47dc
movq -0x48(%rbp), %rdi
movq -0x50(%rbp), %rsi
callq 0x4290
movq %rax, -0x2880(%rbp)
jmp 0x47f2
movq -0x2880(%rbp), %rax
movq %rax, -0x27c0(%rbp)
movq -0x40(%rbp), %rdi
movq -0x27c0(%rbp), %rsi
callq 0x4410
jmp 0x4812
movq -0x40(%rbp), %rdi
callq 0x4470
movq %rax, -0x27c8(%rbp)
cmpq $0x0, -0x27c8(%rbp)
je 0x4cef
movq -0x27c8(%rbp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq %rax, -0x48(%rbp)
movq -0x27c8(%rbp), %rax
movq (%rax), %rax
movq 0x8(%rax), %rax
movq %rax, -0x50(%rbp)
movq -0x48(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x27d0(%rbp)
movq -0x50(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x27d8(%rbp)
movq -0x27d0(%rbp), %rax
addq -0x27d8(%rbp), %rax
movslq -0x2c(%rbp), %rcx
cmpq %rcx, %rax
jge 0x488b
jmp 0x4bef
movq -0x27d0(%rbp), %rax
movslq -0x2c(%rbp), %rcx
cmpq %rcx, %rax
jne 0x48b2
movsd 0xf765(%rip), %xmm0     # 0x14008
addsd -0x80(%rbp), %xmm0
movsd %xmm0, -0x80(%rbp)
jmp 0x4bed
movq $0x0, -0x27e0(%rbp)
movq -0x27e0(%rbp), %rax
cmpq -0x27d8(%rbp), %rax
jge 0x4beb
movq -0x50(%rbp), %rax
movq 0x8(%rax), %rax
movq -0x27e0(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x27e8(%rbp)
movl $0x0, -0x27ec(%rbp)
movl $0x0, -0x27f0(%rbp)
movslq -0x27f0(%rbp), %rax
cmpq -0x27d0(%rbp), %rax
jge 0x4973
movq -0x48(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x27f0(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
leaq -0x68(%rbp), %rdi
callq 0x5f30
movq (%rax), %rax
movq %rax, -0x2888(%rbp)
movq -0x27e8(%rbp), %rsi
leaq -0x68(%rbp), %rdi
callq 0x5f30
movq %rax, %rcx
movq -0x2888(%rbp), %rax
cmpq (%rcx), %rax
jne 0x4960
movl $0x1, -0x27ec(%rbp)
jmp 0x4973
jmp 0x4962
movl -0x27f0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x27f0(%rbp)
jmp 0x48ff
cmpl $0x1, -0x27ec(%rbp)
jne 0x4981
jmp 0x4bd4
movq -0x27d0(%rbp), %rdi
incq %rdi
callq 0x3ff0
movq %rax, -0x2890(%rbp)
jmp 0x4999
movq -0x2890(%rbp), %rax
movq %rax, -0x27f8(%rbp)
movq -0x48(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x27d0(%rbp), %rax
leaq (%rdi,%rax,8), %rsi
movq -0x27f8(%rbp), %rax
movq 0x8(%rax), %rdx
callq 0x5f50
jmp 0x49cc
movq -0x27e8(%rbp), %rdx
movq -0x27f8(%rbp), %rax
movq 0x8(%rax), %rax
movq -0x48(%rbp), %rcx
movq (%rcx), %rcx
movq %rdx, (%rax,%rcx,8)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movq -0x27e8(%rbp), %rcx
movq 0x8(%rax,%rcx,8), %rax
movq -0x10(%rbp), %rcx
movq 0x10(%rcx), %rcx
movq -0x27e8(%rbp), %rdx
subq (%rcx,%rdx,8), %rax
movl %eax, -0x27fc(%rbp)
movq -0x27d8(%rbp), %rax
movl %eax, -0x2800(%rbp)
movl -0x2800(%rbp), %eax
cmpl -0x27fc(%rbp), %eax
jge 0x4a4a
movl -0x27fc(%rbp), %eax
movl %eax, -0x2800(%rbp)
movq -0x27d8(%rbp), %rax
movl %eax, -0x27fc(%rbp)
movslq -0x27fc(%rbp), %rdi
callq 0x3ff0
movq %rax, -0x2898(%rbp)
jmp 0x4a5f
movq -0x2898(%rbp), %rax
movq %rax, -0x2808(%rbp)
movl $0x0, -0x280c(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movq -0x27e8(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movl %eax, -0x2810(%rbp)
movl $0x0, -0x2814(%rbp)
movslq -0x2814(%rbp), %rax
movq -0x50(%rbp), %rcx
cmpq (%rcx), %rax
jge 0x4b85
movl $0x0, -0x2818(%rbp)
movslq -0x2818(%rbp), %rax
movq -0x10(%rbp), %rcx
movq 0x10(%rcx), %rcx
movq -0x27e8(%rbp), %rdx
movq 0x8(%rcx,%rdx,8), %rcx
movq -0x10(%rbp), %rdx
movq 0x10(%rdx), %rdx
movq -0x27e8(%rbp), %rsi
subq (%rdx,%rsi,8), %rcx
cmpq %rcx, %rax
jge 0x4b6f
movq -0x50(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x2814(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq -0x10(%rbp), %rcx
movq 0x18(%rcx), %rcx
movl -0x2810(%rbp), %edx
addl -0x2818(%rbp), %edx
movslq %edx, %rdx
cmpq (%rcx,%rdx,8), %rax
jne 0x4b59
movq -0x50(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x2814(%rbp), %rcx
movq (%rax,%rcx,8), %rdx
movq -0x2808(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x280c(%rbp), %rcx
movq %rdx, (%rax,%rcx,8)
movl -0x280c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x280c(%rbp)
jmp 0x4b6f
jmp 0x4b5b
movl -0x2818(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2818(%rbp)
jmp 0x4ab8
jmp 0x4b71
movl -0x2814(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2814(%rbp)
jmp 0x4a9a
movslq -0x280c(%rbp), %rcx
movq -0x2808(%rbp), %rax
movq %rcx, (%rax)
movq -0x27f8(%rbp), %rdi
movq -0x2808(%rbp), %rsi
callq 0x4290
movq %rax, -0x28a0(%rbp)
jmp 0x4bb2
movq -0x28a0(%rbp), %rax
movq %rax, -0x2820(%rbp)
movq -0x40(%rbp), %rdi
movq -0x2820(%rbp), %rsi
callq 0x4410
jmp 0x4bd2
jmp 0x4bd4
movq -0x27e0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x27e0(%rbp)
jmp 0x48bd
jmp 0x4bed
jmp 0x4bef
movq -0x50(%rbp), %rax
cmpq $0x0, (%rax)
jl 0x4c1c
movq -0x50(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x28a8(%rbp)
cmpq $0x0, %rax
je 0x4c1a
movq -0x28a8(%rbp), %rdi
callq 0x33e0
jmp 0x4c1c
movq -0x50(%rbp), %rax
movq %rax, -0x28b0(%rbp)
cmpq $0x0, %rax
je 0x4c3e
movq -0x28b0(%rbp), %rdi
movl $0x10, %esi
callq 0x3320
movq -0x48(%rbp), %rax
cmpq $0x0, (%rax)
jle 0x4c6b
movq -0x48(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x28b8(%rbp)
cmpq $0x0, %rax
je 0x4c69
movq -0x28b8(%rbp), %rdi
callq 0x33e0
jmp 0x4c6b
movq -0x48(%rbp), %rax
movq %rax, -0x28c0(%rbp)
cmpq $0x0, %rax
je 0x4c8d
movq -0x28c0(%rbp), %rdi
movl $0x10, %esi
callq 0x3320
movq -0x27c8(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x28c8(%rbp)
cmpq $0x0, %rax
je 0x4cb5
movq -0x28c8(%rbp), %rdi
movl $0x10, %esi
callq 0x3320
movq -0x27c8(%rbp), %rax
movq %rax, -0x28d0(%rbp)
cmpq $0x0, %rax
je 0x4cda
movq -0x28d0(%rbp), %rdi
movl $0x10, %esi
callq 0x3320
movq -0x40(%rbp), %rdi
callq 0x4470
movq %rax, -0x27c8(%rbp)
jmp 0x4822
jmp 0x4cf1
movq -0x27b8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x27b8(%rbp)
jmp 0x4731
movq -0x40(%rbp), %rdi
callq 0x43c0
callq 0x3060
movq %rax, -0x2828(%rbp)
leaq -0x2828(%rbp), %rdi
leaq -0x38(%rbp), %rsi
callq 0x5fc0
movq %rax, -0x28d8(%rbp)
jmp 0x4d36
movq -0x28d8(%rbp), %rax
movq %rax, -0x2840(%rbp)
leaq -0x2840(%rbp), %rdi
callq 0x5f90
movq %rax, -0x28e0(%rbp)
jmp 0x4d59
movq -0x28e0(%rbp), %rax
movq %rax, -0x2838(%rbp)
leaq -0x2838(%rbp), %rdi
callq 0x6010
movq %rax, -0x28e8(%rbp)
jmp 0x4d7c
movq -0x28e8(%rbp), %rax
movq %rax, -0x2830(%rbp)
movsd 0xf276(%rip), %xmm0     # 0x14008
movsd %xmm0, -0x2848(%rbp)
movl $0x1, -0x284c(%rbp)
movl -0x284c(%rbp), %eax
cmpl -0x2c(%rbp), %eax
jg 0x4dd8
cvtsi2sdl -0x284c(%rbp), %xmm0
mulsd -0x2848(%rbp), %xmm0
movsd %xmm0, -0x2848(%rbp)
movl -0x284c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x284c(%rbp)
jmp 0x4da4
movsd -0x80(%rbp), %xmm0
movsd %xmm0, -0x28f8(%rbp)
movl -0x2c(%rbp), %esi
movl %esi, %edi
callq 0x6030
movsd %xmm0, -0x28f0(%rbp)
jmp 0x4df9
movsd -0x28f0(%rbp), %xmm1
movsd -0x28f8(%rbp), %xmm0
mulsd %xmm1, %xmm0
movsd -0x2848(%rbp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0x88(%rbp)
movq 0x181a8(%rip), %rdi     # 0x1cfd0
leaq 0xf2f1(%rip), %rsi      # 0x14120
callq 0x32f0
movq %rax, -0x2900(%rbp)
jmp 0x4e3d
movq -0x2900(%rbp), %rdi
movq -0x2830(%rbp), %rsi
callq 0x3590
movq %rax, -0x2908(%rbp)
jmp 0x4e59
movq -0x2908(%rbp), %rdi
movq 0x18151(%rip), %rsi     # 0x1cfb8
callq 0x3340
jmp 0x4e6e
movq 0x1815b(%rip), %rdi     # 0x1cfd0
leaq 0xf2c9(%rip), %rsi      # 0x14145
callq 0x32f0
movq %rax, -0x2910(%rbp)
jmp 0x4e8a
movq -0x2910(%rbp), %rdi
movsd -0x80(%rbp), %xmm0
callq 0x35c0
movq %rax, -0x2918(%rbp)
jmp 0x4ea4
movq -0x2918(%rbp), %rdi
movq 0x18106(%rip), %rsi     # 0x1cfb8
callq 0x3340
jmp 0x4eb9
movq 0x18110(%rip), %rdi     # 0x1cfd0
leaq 0xf265(%rip), %rsi      # 0x1412c
callq 0x32f0
movq %rax, -0x2920(%rbp)
jmp 0x4ed5
movq -0x2920(%rbp), %rdi
movl -0x2c(%rbp), %esi
callq 0x3540
movq %rax, -0x2928(%rbp)
jmp 0x4eed
movq -0x2928(%rbp), %rdi
movq 0x180bd(%rip), %rsi     # 0x1cfb8
callq 0x3340
jmp 0x4f02
movq 0x180c7(%rip), %rdi     # 0x1cfd0
leaq 0xf22b(%rip), %rsi      # 0x1413b
callq 0x32f0
movq %rax, -0x2930(%rbp)
jmp 0x4f1e
movq -0x2930(%rbp), %rdi
movsd -0x88(%rbp), %xmm0
callq 0x35c0
movq %rax, -0x2938(%rbp)
jmp 0x4f3b
movq -0x2938(%rbp), %rdi
movq 0x1806f(%rip), %rsi     # 0x1cfb8
callq 0x3340
jmp 0x4f50
movq -0x18(%rbp), %rdi
movl -0x2c(%rbp), %esi
callq 0x3540
movq %rax, -0x2940(%rbp)
jmp 0x4f65
movq -0x2940(%rbp), %rdi
leaq 0xf294(%rip), %rsi      # 0x14207
callq 0x32f0
movq %rax, -0x2948(%rbp)
jmp 0x4f81
movq -0x2948(%rbp), %rdi
movsd -0x88(%rbp), %xmm0
callq 0x35c0
movq %rax, -0x2950(%rbp)
jmp 0x4f9e
movq -0x2950(%rbp), %rdi
leaq 0xf25b(%rip), %rsi      # 0x14207
callq 0x32f0
movq %rax, -0x2958(%rbp)
jmp 0x4fba
movq -0x2958(%rbp), %rdi
movq -0x2830(%rbp), %rsi
callq 0x3590
movq %rax, -0x2960(%rbp)
jmp 0x4fd6
movq -0x2960(%rbp), %rdi
leaq 0xf223(%rip), %rsi      # 0x14207
callq 0x32f0
movq %rax, -0x2968(%rbp)
jmp 0x4ff2
movq -0x2968(%rbp), %rdi
movq 0x17fb8(%rip), %rsi     # 0x1cfb8
callq 0x3340
jmp 0x5007
leaq -0x1410(%rbp), %rdi
callq 0x6060
leaq -0x68(%rbp), %rdi
callq 0x6090
addq $0x2970, %rsp           # imm = 0x2970
popq %rbp
retq
leaq -0x68(%rbp), %rdi
callq 0x6090
movq -0x70(%rbp), %rdi
callq 0x3560
nopw (%rax,%rax)