// File: iPapatsoris[P]Maximum-Independent-Set/src/Graph.cpp
// Function: Graph::getFunnels(std::vector<Graph::Funnel, std::allocator<Graph::Funnel>>&, unsigned int const*, unsigned int*, Graph::Funnel*) const
bool Graph::getFunnels(vector<Funnel> &funnels, const uint32_t *measure, uint32_t *effectiveNode, Funnel *fourFunnel) const {
    GraphTraversal graphTraversal(*this);
    while (graphTraversal.curNode != NONE) {
        uint32_t nodeV = graphTraversal.curNode;
        uint32_t vDegree = getNodeDegree(nodeV);
        if (vDegree == 3 || vDegree == 4) {
            vector<uint32_t> neighborsV;
            gatherNeighbors(nodeV, neighborsV);
            for (uint32_t i = 0 ; i < neighborsV.size() ; i++) {
                uint32_t nodeA = neighborsV[i];
                uint32_t nodeB, nodeC, nodeD;
                if (i == 0) {
                    nodeB = neighborsV[1];
                    nodeC = neighborsV[2];
                    nodeD = (neighborsV.size() == 3 ? NONE : neighborsV[3]);
                } else if (i == 1) {
                    nodeB = neighborsV[0];
                    nodeC = neighborsV[2];
                    nodeD = (neighborsV.size() == 3 ? NONE : neighborsV[3]);
                } else if (i == 2) {
                    nodeB = neighborsV[0];
                    nodeC = neighborsV[1];
                    nodeD = (neighborsV.size() == 3 ? NONE : neighborsV[3]);
                } else {
                    nodeB = neighborsV[0];
                    nodeC = neighborsV[1];
                    nodeD = (neighborsV.size() == 3 ? NONE : neighborsV[2]);
                }
                if (edgeExists(nodeB, nodeC) && (vDegree == 3 || vDegree == 4 && edgeExists(nodeB, nodeD) && edgeExists(nodeC, nodeD)))  {
                    if (measure == NULL) {
                        funnels.push_back(Funnel(nodeA, nodeB, nodeC, nodeD, nodeV));
                        if (vDegree == 4 || (getNodeDegree(nodeA) == 4 && (getNodeDegree(nodeB) == 4 || getNodeDegree(nodeC) == 4))) {
                            return true;
                        }
                    } else {
                        uint32_t degree3NodesCount;
                        if (getNodeDegree(nodeA) == 3) {
                            degree3NodesCount++;
                        }
                        if (getNodeDegree(nodeB) == 3) {
                            degree3NodesCount++;
                        }
                        if (getNodeDegree(nodeC) == 3) {
                            degree3NodesCount++;
                        }
                        if (vDegree == 4 && getNodeDegree(nodeD) == 3) {
                            degree3NodesCount++;
                        }
                        if (degree3NodesCount >= 3) {
                            Graph newGraph = *this;
                            unordered_set<uint32_t> extendedGrandchildren;
                            goToNode(nodeV, graphTraversal);
                            getExtendedGrandchildren(graphTraversal, extendedGrandchildren);
                            extendedGrandchildren.insert(nodeV);
                            std::unordered_set<uint32_t> neighbors;
                            gatherAllNeighbors(extendedGrandchildren, neighbors);
                            unordered_set<uint32_t> *smaller = &neighbors;
                            unordered_set<uint32_t> *bigger = &extendedGrandchildren;
                            if (smaller->size() > bigger->size()) {
                                std::unordered_set<uint32_t> *tmp = smaller;
                                smaller = bigger;
                                bigger = tmp;
                            }
                            smaller->insert(bigger->begin(), bigger->end());
                            ReduceInfo dummy;
                            newGraph.remove(vector<uint32_t>(smaller->begin(), smaller->end()), dummy);
                            if (newGraph.getEffectiveNodeMeasure(*measure - 20) <= *measure - 20) {
                                *effectiveNode = nodeV;
                                return true;
                            }
                        }
                        Funnel funnel(nodeA, nodeB, nodeC, nodeD, nodeV);
                        if (vDegree == 4) {
                            *fourFunnel = funnel;
                            return true;
                        } else {
                            funnels.push_back(funnel);
                        }
                    }
                }
            }
        }
        getNextNode(graphTraversal);
    }
    return false;
}

// Assembly:
subq $0x288, %rsp            # imm = 0x288
movq %rdi, 0x278(%rsp)
movq %rsi, 0x270(%rsp)
movq %rdx, 0x268(%rsp)
movq %rcx, 0x260(%rsp)
movq %r8, 0x258(%rsp)
movq 0x278(%rsp), %rsi
movq %rsi, 0x88(%rsp)
leaq 0x250(%rsp), %rdi
callq 0x2a40
cmpl $-0x1, 0x250(%rsp)
je 0x7b93
movq 0x88(%rsp), %rdi
movl 0x250(%rsp), %eax
movl %eax, 0x24c(%rsp)
leaq 0x24c(%rsp), %rsi
callq 0x1a040
movl %eax, 0x248(%rsp)
cmpl $0x3, 0x248(%rsp)
je 0x715c
cmpl $0x4, 0x248(%rsp)
jne 0x7b79
leaq 0x230(%rsp), %rdi
movq %rdi, 0x80(%rsp)
callq 0x17e60
movq 0x88(%rsp), %rdi
movq 0x80(%rsp), %rdx
movl $0xffffffff, 0x22c(%rsp) # imm = 0xFFFFFFFF
xorl %eax, %eax
movl %eax, %ecx
leaq 0x24c(%rsp), %rsi
leaq 0x22c(%rsp), %r8
callq 0x19c30
jmp 0x71a7
movl $0x0, 0x218(%rsp)
movl 0x218(%rsp), %eax
movq %rax, 0x78(%rsp)
leaq 0x230(%rsp), %rdi
callq 0x188e0
movq %rax, %rcx
movq 0x78(%rsp), %rax
cmpq %rcx, %rax
jae 0x7b41
movl 0x218(%rsp), %eax
movl %eax, %esi
leaq 0x230(%rsp), %rdi
callq 0x18900
movl (%rax), %eax
movl %eax, 0x214(%rsp)
cmpl $0x0, 0x218(%rsp)
jne 0x729e
leaq 0x230(%rsp), %rdi
movl $0x1, %esi
callq 0x18900
movl (%rax), %eax
movl %eax, 0x210(%rsp)
leaq 0x230(%rsp), %rdi
movl $0x2, %esi
callq 0x18900
movl (%rax), %eax
movl %eax, 0x20c(%rsp)
leaq 0x230(%rsp), %rdi
callq 0x188e0
cmpq $0x3, %rax
jne 0x725d
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movl %eax, 0x74(%rsp)
jmp 0x7275
leaq 0x230(%rsp), %rdi
movl $0x3, %esi
callq 0x18900
movl (%rax), %eax
movl %eax, 0x74(%rsp)
movl 0x74(%rsp), %eax
movl %eax, 0x208(%rsp)
jmp 0x741f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x220(%rsp)
movl %eax, 0x21c(%rsp)
jmp 0x7b6a
cmpl $0x1, 0x218(%rsp)
jne 0x7323
leaq 0x230(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x18900
movl (%rax), %eax
movl %eax, 0x210(%rsp)
leaq 0x230(%rsp), %rdi
movl $0x2, %esi
callq 0x18900
movl (%rax), %eax
movl %eax, 0x20c(%rsp)
leaq 0x230(%rsp), %rdi
callq 0x188e0
cmpq $0x3, %rax
jne 0x72fb
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movl %eax, 0x70(%rsp)
jmp 0x7313
leaq 0x230(%rsp), %rdi
movl $0x3, %esi
callq 0x18900
movl (%rax), %eax
movl %eax, 0x70(%rsp)
movl 0x70(%rsp), %eax
movl %eax, 0x208(%rsp)
jmp 0x741d
cmpl $0x2, 0x218(%rsp)
jne 0x73a5
leaq 0x230(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x18900
movl (%rax), %eax
movl %eax, 0x210(%rsp)
leaq 0x230(%rsp), %rdi
movl $0x1, %esi
callq 0x18900
movl (%rax), %eax
movl %eax, 0x20c(%rsp)
leaq 0x230(%rsp), %rdi
callq 0x188e0
cmpq $0x3, %rax
jne 0x7380
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movl %eax, 0x6c(%rsp)
jmp 0x7398
leaq 0x230(%rsp), %rdi
movl $0x3, %esi
callq 0x18900
movl (%rax), %eax
movl %eax, 0x6c(%rsp)
movl 0x6c(%rsp), %eax
movl %eax, 0x208(%rsp)
jmp 0x741b
leaq 0x230(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x18900
movl (%rax), %eax
movl %eax, 0x210(%rsp)
leaq 0x230(%rsp), %rdi
movl $0x1, %esi
callq 0x18900
movl (%rax), %eax
movl %eax, 0x20c(%rsp)
leaq 0x230(%rsp), %rdi
callq 0x188e0
cmpq $0x3, %rax
jne 0x73f8
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movl %eax, 0x68(%rsp)
jmp 0x7410
leaq 0x230(%rsp), %rdi
movl $0x2, %esi
callq 0x18900
movl (%rax), %eax
movl %eax, 0x68(%rsp)
movl 0x68(%rsp), %eax
movl %eax, 0x208(%rsp)
jmp 0x741d
jmp 0x741f
movq 0x88(%rsp), %rdi
leaq 0x210(%rsp), %rsi
leaq 0x20c(%rsp), %rdx
callq 0x18920
movb %al, 0x67(%rsp)
jmp 0x7442
movb 0x67(%rsp), %al
testb $0x1, %al
jne 0x744f
jmp 0x7b29
cmpl $0x3, 0x248(%rsp)
je 0x74c7
cmpl $0x4, 0x248(%rsp)
jne 0x7b29
movq 0x88(%rsp), %rdi
leaq 0x210(%rsp), %rsi
leaq 0x208(%rsp), %rdx
callq 0x18920
movb %al, 0x66(%rsp)
jmp 0x748a
movb 0x66(%rsp), %al
testb $0x1, %al
jne 0x7497
jmp 0x7b29
movq 0x88(%rsp), %rdi
leaq 0x20c(%rsp), %rsi
leaq 0x208(%rsp), %rdx
callq 0x18920
movb %al, 0x65(%rsp)
jmp 0x74ba
movb 0x65(%rsp), %al
testb $0x1, %al
jne 0x74c7
jmp 0x7b29
cmpq $0x0, 0x268(%rsp)
jne 0x75c1
movq 0x270(%rsp), %rax
movq %rax, 0x58(%rsp)
leaq 0x1f4(%rsp), %rdi
leaq 0x214(%rsp), %rsi
leaq 0x210(%rsp), %rdx
leaq 0x20c(%rsp), %rcx
leaq 0x208(%rsp), %r8
leaq 0x24c(%rsp), %r9
callq 0x1a430
jmp 0x751a
movq 0x58(%rsp), %rdi
leaq 0x1f4(%rsp), %rsi
callq 0x1a400
jmp 0x752e
cmpl $0x4, 0x248(%rsp)
je 0x75a4
movq 0x88(%rsp), %rdi
leaq 0x214(%rsp), %rsi
callq 0x1a040
movl %eax, 0x54(%rsp)
jmp 0x7553
movl 0x54(%rsp), %eax
cmpl $0x4, %eax
jne 0x75bc
movq 0x88(%rsp), %rdi
leaq 0x210(%rsp), %rsi
callq 0x1a040
movl %eax, 0x50(%rsp)
jmp 0x7577
movl 0x50(%rsp), %eax
cmpl $0x4, %eax
je 0x75a4
movq 0x88(%rsp), %rdi
leaq 0x20c(%rsp), %rsi
callq 0x1a040
movl %eax, 0x4c(%rsp)
jmp 0x759b
movl 0x4c(%rsp), %eax
cmpl $0x4, %eax
jne 0x75bc
movb $0x1, 0x287(%rsp)
movl $0x1, 0x1f0(%rsp)
jmp 0x7b4c
jmp 0x7b27
movq 0x88(%rsp), %rdi
leaq 0x214(%rsp), %rsi
callq 0x1a040
movl %eax, 0x48(%rsp)
jmp 0x75dc
movl 0x48(%rsp), %eax
cmpl $0x3, %eax
jne 0x75f6
movl 0x1ec(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1ec(%rsp)
movq 0x88(%rsp), %rdi
leaq 0x210(%rsp), %rsi
callq 0x1a040
movl %eax, 0x44(%rsp)
jmp 0x7611
movl 0x44(%rsp), %eax
cmpl $0x3, %eax
jne 0x762b
movl 0x1ec(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1ec(%rsp)
movq 0x88(%rsp), %rdi
leaq 0x20c(%rsp), %rsi
callq 0x1a040
movl %eax, 0x40(%rsp)
jmp 0x7646
movl 0x40(%rsp), %eax
cmpl $0x3, %eax
jne 0x7660
movl 0x1ec(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1ec(%rsp)
cmpl $0x4, 0x248(%rsp)
jne 0x769f
movq 0x88(%rsp), %rdi
leaq 0x208(%rsp), %rsi
callq 0x1a040
movl %eax, 0x3c(%rsp)
jmp 0x7685
movl 0x3c(%rsp), %eax
cmpl $0x3, %eax
jne 0x769f
movl 0x1ec(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1ec(%rsp)
cmpl $0x3, 0x1ec(%rsp)
jb 0x7a8d
movq 0x88(%rsp), %rsi
leaq 0x198(%rsp), %rdi
callq 0x2660
jmp 0x76c4
leaq 0x160(%rsp), %rdi
callq 0x1a020
movq 0x88(%rsp), %rdi
leaq 0x24c(%rsp), %rsi
leaq 0x250(%rsp), %rdx
callq 0x187b0
jmp 0x76f0
movq 0x88(%rsp), %rdi
movb $0x0, 0x15f(%rsp)
xorl %eax, %eax
movl %eax, %ecx
leaq 0x250(%rsp), %rsi
leaq 0x160(%rsp), %rdx
leaq 0x15f(%rsp), %r8
callq 0x4f80
jmp 0x7723
leaq 0x160(%rsp), %rdi
leaq 0x24c(%rsp), %rsi
callq 0x18960
movb %dl, 0x2f(%rsp)
movq %rax, 0x30(%rsp)
jmp 0x7743
movb 0x2f(%rsp), %al
movq 0x30(%rsp), %rcx
movq %rcx, 0x148(%rsp)
movb %al, 0x150(%rsp)
leaq 0x110(%rsp), %rdi
movq %rdi, 0x20(%rsp)
callq 0x1a020
movq 0x88(%rsp), %rdi
movq 0x20(%rsp), %rdx
movl $0xffffffff, 0x10c(%rsp) # imm = 0xFFFFFFFF
leaq 0x160(%rsp), %rsi
leaq 0x10c(%rsp), %rcx
callq 0x1a270
jmp 0x779c
leaq 0x110(%rsp), %rax
movq %rax, 0x100(%rsp)
leaq 0x160(%rsp), %rax
movq %rax, 0xf8(%rsp)
movq 0x100(%rsp), %rdi
callq 0x191e0
movq %rax, 0x18(%rsp)
movq 0xf8(%rsp), %rdi
callq 0x191e0
movq %rax, %rcx
movq 0x18(%rsp), %rax
cmpq %rcx, %rax
jbe 0x784c
movq 0x100(%rsp), %rax
movq %rax, 0xf0(%rsp)
movq 0xf8(%rsp), %rax
movq %rax, 0x100(%rsp)
movq 0xf0(%rsp), %rax
movq %rax, 0xf8(%rsp)
jmp 0x784c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x220(%rsp)
movl %eax, 0x21c(%rsp)
jmp 0x7a6e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x220(%rsp)
movl %eax, 0x21c(%rsp)
jmp 0x7a61
movq 0x100(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0xf8(%rsp), %rdi
callq 0x19220
movq %rax, 0xe8(%rsp)
movq 0xf8(%rsp), %rdi
callq 0x19250
movq 0x10(%rsp), %rdi
movq %rax, 0xe0(%rsp)
movq 0xe8(%rsp), %rsi
movq 0xe0(%rsp), %rdx
callq 0x1a490
jmp 0x789f
leaq 0xdc(%rsp), %rdi
callq 0x1a320
jmp 0x78ae
movq 0x100(%rsp), %rdi
callq 0x19220
movq %rax, 0xb8(%rsp)
movq 0x100(%rsp), %rdi
callq 0x19250
movq %rax, 0xb0(%rsp)
leaq 0xaf(%rsp), %rdi
movq %rdi, 0x8(%rsp)
callq 0x18d80
movq 0x8(%rsp), %rcx
movq 0xb8(%rsp), %rsi
movq 0xb0(%rsp), %rdx
leaq 0xc0(%rsp), %rdi
callq 0x1a4d0
jmp 0x790e
movb $0x0, 0xae(%rsp)
movb $0x0, 0xad(%rsp)
xorl %eax, %eax
movl %eax, %r8d
leaq 0x198(%rsp), %rdi
leaq 0xc0(%rsp), %rsi
leaq 0xdc(%rsp), %rdx
leaq 0xae(%rsp), %rcx
leaq 0xad(%rsp), %r9
callq 0x189b0
jmp 0x7952
leaq 0xc0(%rsp), %rdi
callq 0x18520
leaq 0xaf(%rsp), %rdi
callq 0x18e10
movq 0x268(%rsp), %rax
movl (%rax), %eax
addl $-0x14, %eax
movl %eax, 0xa8(%rsp)
leaq 0x198(%rsp), %rdi
leaq 0xa8(%rsp), %rsi
callq 0x6a40
movl %eax, 0x4(%rsp)
jmp 0x799b
movl 0x4(%rsp), %eax
movq 0x268(%rsp), %rcx
movl (%rcx), %ecx
subl $0x14, %ecx
cmpl %ecx, %eax
ja 0x7a1c
movl 0x24c(%rsp), %ecx
movq 0x260(%rsp), %rax
movl %ecx, (%rax)
movb $0x1, 0x287(%rsp)
movl $0x1, 0x1f0(%rsp)
jmp 0x7a27
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x220(%rsp)
movl %eax, 0x21c(%rsp)
jmp 0x7a0d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x220(%rsp)
movl %eax, 0x21c(%rsp)
leaq 0xc0(%rsp), %rdi
callq 0x18520
leaq 0xaf(%rsp), %rdi
callq 0x18e10
jmp 0x7a61
movl $0x0, 0x1f0(%rsp)
leaq 0x110(%rsp), %rdi
callq 0x1a030
leaq 0x160(%rsp), %rdi
callq 0x1a030
leaq 0x198(%rsp), %rdi
callq 0x2990
movl 0x1f0(%rsp), %eax
testl %eax, %eax
jne 0x7b4c
jmp 0x7a5f
jmp 0x7a8d
leaq 0x110(%rsp), %rdi
callq 0x1a030
leaq 0x160(%rsp), %rdi
callq 0x1a030
leaq 0x198(%rsp), %rdi
callq 0x2990
jmp 0x7b6a
leaq 0x94(%rsp), %rdi
leaq 0x214(%rsp), %rsi
leaq 0x210(%rsp), %rdx
leaq 0x20c(%rsp), %rcx
leaq 0x208(%rsp), %r8
leaq 0x24c(%rsp), %r9
callq 0x1a430
jmp 0x7ac4
cmpl $0x4, 0x248(%rsp)
jne 0x7b0c
movq 0x258(%rsp), %rax
movq 0x94(%rsp), %rcx
movq %rcx, (%rax)
movq 0x9c(%rsp), %rcx
movq %rcx, 0x8(%rax)
movl 0xa4(%rsp), %ecx
movl %ecx, 0x10(%rax)
movb $0x1, 0x287(%rsp)
movl $0x1, 0x1f0(%rsp)
jmp 0x7b4c
movq 0x270(%rsp), %rdi
leaq 0x94(%rsp), %rsi
callq 0x1a560
jmp 0x7b23
jmp 0x7b25
jmp 0x7b27
jmp 0x7b29
jmp 0x7b2b
movl 0x218(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x218(%rsp)
jmp 0x71b2
movl $0x0, 0x1f0(%rsp)
leaq 0x230(%rsp), %rdi
callq 0x18520
movl 0x1f0(%rsp), %eax
testl %eax, %eax
je 0x7b68
jmp 0x7b66
jmp 0x7b9b
jmp 0x7b79
leaq 0x230(%rsp), %rdi
callq 0x18520
jmp 0x7bac
movq 0x88(%rsp), %rdi
leaq 0x250(%rsp), %rsi
callq 0x185f0
jmp 0x710c
movb $0x0, 0x287(%rsp)
movb 0x287(%rsp), %al
andb $0x1, %al
addq $0x288, %rsp            # imm = 0x288
retq
movq 0x220(%rsp), %rdi
callq 0x2310
nopl (%rax)