// File: sebastienmeyer2[P]mst-clustering/src/graph.cpp
// Function: build_from_ashiip(Graph*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>)
void build_from_ashiip(Graph* g, std::string file_path)
{
    /*!
     * @brief Builds a graph from scratch, from the nodes and edges generated by 
     * aSHIIP and contained in a specific file format. Adds a random weight drawn 
     * by an exponential distribution to each edge.
     * 
     * @param file_path The path to the file 
     * 
     */

    std::ifstream is(file_path);
    assert(("No such file", is.is_open()));

    std::unordered_map<node_label_t, Node*> created_nodes;
    std::unordered_map<Node*, std::unordered_set<Node*> > links;

    std::default_random_engine generator;
    std::exponential_distribution<double> distribution(1);

    std::string line;

    while (std::getline(is, line)) {

        std::istringstream iss(line);

        // node's label (here, we want positive integers)
        node_label_t label;
        iss >> label;

        if (label <= 0) {
            continue;
        }

        Node* n_in;
        if (created_nodes.find(label) == created_nodes.end()) {
            n_in = new Node(label);
            created_nodes.insert(std::pair<node_label_t, Node*>(label, n_in));
        } else {
            n_in = created_nodes.at(label);
        }

        // type of node (not useful here)
        std::string cat;
        iss >> cat;

        // edges
        std::string other_node;
        int j = 0;
        while (iss >> other_node) {

            if (j == 0) {
                other_node = other_node.substr(1); // eliminating bracket
            }

            int length = other_node.size();
            other_node = other_node.substr(0, length-1); // eliminating comma
            node_label_t other_label = stoi(other_node);

            Node* n_out;
            if (created_nodes.find(other_label) == created_nodes.end()) {
                n_out = new Node(other_label);
                created_nodes.insert(std::pair<node_label_t, Node*>(other_label, n_out));
            } else {
                n_out = created_nodes.at(other_label);
            }

            // avoid double insertion of same edges
            Node* master_node = (n_in->label > n_out->label) ? n_in : n_out;
            Node* slave_node = (master_node == n_in) ? n_out : n_in;

            bool force_insert = false;

            if (links.find(master_node) == links.end()) {
                links.insert(std::pair<Node*, std::unordered_set<Node*> >(master_node, std::unordered_set<Node*>()));
                force_insert = true;
            }

            std::unordered_set<Node*>& linked_nodes = links.at(master_node);
            if (linked_nodes.find(slave_node) == linked_nodes.end()) {
                linked_nodes.insert(slave_node);
                force_insert = true;
            }

            if (force_insert == true) {
                Edge* e = new Edge(n_in, n_out, distribution(generator));
                g->add_edge(e);
            }

            j += 1;
        }
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x760, %rsp            # imm = 0x760
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
leaq -0x218(%rbp), %rdi
movq %rdi, -0x650(%rbp)
movl $0x8, %edx
callq 0xac80
movq -0x650(%rbp), %rdi
callq 0xac60
movb %al, -0x641(%rbp)
jmp 0xc52f
movb -0x641(%rbp), %al
testb $0x1, %al
jne 0xc53b
jmp 0xc53d
jmp 0xc573
leaq 0x2aacd(%rip), %rdi     # 0x37011
leaq 0x2aba5(%rip), %rsi     # 0x370f0
movl $0x15, %edx
leaq 0x2aba7(%rip), %rcx     # 0x370fe
callq 0xa4a0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x220(%rbp)
movl %eax, -0x224(%rbp)
jmp 0xced6
leaq -0x260(%rbp), %rdi
callq 0xd8f0
leaq -0x298(%rbp), %rdi
callq 0xd930
leaq -0x2a0(%rbp), %rdi
callq 0xd950
jmp 0xc599
leaq -0x2a8(%rbp), %rdi
movsd 0x2ab00(%rip), %xmm0    # 0x370a8
callq 0xd970
jmp 0xc5af
leaq -0x2c8(%rbp), %rdi
callq 0xaad0
leaq -0x218(%rbp), %rdi
leaq -0x2c8(%rbp), %rsi
callq 0xa120
movq %rax, -0x658(%rbp)
jmp 0xc5d7
movq -0x658(%rbp), %rdi
movq (%rdi), %rax
movq -0x18(%rax), %rax
addq %rax, %rdi
callq 0xa9c0
movb %al, -0x659(%rbp)
jmp 0xc5f5
movb -0x659(%rbp), %al
testb $0x1, %al
jne 0xc604
jmp 0xce79
leaq -0x448(%rbp), %rdi
leaq -0x2c8(%rbp), %rsi
movl $0x8, %edx
callq 0xad20
jmp 0xc61e
leaq -0x448(%rbp), %rdi
leaq -0x44c(%rbp), %rsi
callq 0xa460
jmp 0xc633
cmpl $0x0, -0x44c(%rbp)
jg 0xc690
movl $0x2, -0x450(%rbp)
jmp 0xce31
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x220(%rbp)
movl %eax, -0x224(%rbp)
jmp 0xcebe
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x220(%rbp)
movl %eax, -0x224(%rbp)
jmp 0xceb2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x220(%rbp)
movl %eax, -0x224(%rbp)
jmp 0xce6b
leaq -0x260(%rbp), %rdi
leaq -0x44c(%rbp), %rsi
callq 0xd9d0
movq %rax, -0x668(%rbp)
jmp 0xc6ac
movq -0x668(%rbp), %rax
movq %rax, -0x460(%rbp)
leaq -0x260(%rbp), %rdi
callq 0xda00
movq %rax, -0x468(%rbp)
leaq -0x460(%rbp), %rdi
leaq -0x468(%rbp), %rsi
callq 0xd9a0
testb $0x1, %al
jne 0xc6e9
jmp 0xc7a0
movl $0x18, %edi
callq 0xa790
movq %rax, -0x670(%rbp)
jmp 0xc6fc
movq -0x670(%rbp), %rdi
movl -0x44c(%rbp), %esi
callq 0x230b0
jmp 0xc710
movq -0x670(%rbp), %rax
movq %rax, -0x458(%rbp)
leaq -0x478(%rbp), %rdi
leaq -0x44c(%rbp), %rsi
leaq -0x458(%rbp), %rdx
callq 0xda70
jmp 0xc73a
leaq -0x260(%rbp), %rdi
leaq -0x478(%rbp), %rsi
callq 0xda30
movb %dl, -0x679(%rbp)
movq %rax, -0x678(%rbp)
jmp 0xc75c
movb -0x679(%rbp), %al
movq -0x678(%rbp), %rcx
movq %rcx, -0x488(%rbp)
movb %al, -0x480(%rbp)
jmp 0xc7cd
movq -0x670(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x220(%rbp)
movl %eax, -0x224(%rbp)
movl $0x18, %esi
callq 0xa7b0
jmp 0xce6b
leaq -0x260(%rbp), %rdi
leaq -0x44c(%rbp), %rsi
callq 0xdaa0
movq %rax, -0x688(%rbp)
jmp 0xc7bc
movq -0x688(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x458(%rbp)
leaq -0x4a8(%rbp), %rdi
movq %rdi, -0x690(%rbp)
callq 0xaad0
movq -0x690(%rbp), %rsi
leaq -0x448(%rbp), %rdi
callq 0xa9d0
jmp 0xc7f5
leaq -0x4c8(%rbp), %rdi
callq 0xaad0
movl $0x0, -0x4cc(%rbp)
leaq -0x448(%rbp), %rdi
leaq -0x4c8(%rbp), %rsi
callq 0xa9d0
movq %rax, -0x698(%rbp)
jmp 0xc827
movq -0x698(%rbp), %rdi
movq (%rdi), %rax
movq -0x18(%rax), %rax
addq %rax, %rdi
callq 0xa9c0
movb %al, -0x699(%rbp)
jmp 0xc845
movb -0x699(%rbp), %al
testb $0x1, %al
jne 0xc854
jmp 0xce0f
cmpl $0x0, -0x4cc(%rbp)
jne 0xc8cd
leaq -0x4f0(%rbp), %rdi
leaq -0x4c8(%rbp), %rsi
movl $0x1, %edx
movq $-0x1, %rcx
callq 0xa7c0
jmp 0xc87e
leaq -0x4c8(%rbp), %rdi
leaq -0x4f0(%rbp), %rsi
callq 0xa960
leaq -0x4f0(%rbp), %rdi
callq 0xa470
jmp 0xc8cd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x220(%rbp)
movl %eax, -0x224(%rbp)
jmp 0xce5f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x220(%rbp)
movl %eax, -0x224(%rbp)
jmp 0xce53
leaq -0x4c8(%rbp), %rdi
movq %rdi, -0x6a8(%rbp)
callq 0xa4f0
movq -0x6a8(%rbp), %rsi
movl %eax, -0x4f4(%rbp)
movl -0x4f4(%rbp), %eax
decl %eax
movslq %eax, %rcx
xorl %eax, %eax
movl %eax, %edx
leaq -0x518(%rbp), %rdi
callq 0xa7c0
jmp 0xc90a
leaq -0x4c8(%rbp), %rdi
movq %rdi, -0x6b8(%rbp)
leaq -0x518(%rbp), %rsi
movq %rsi, -0x6c0(%rbp)
callq 0xa960
movq -0x6c0(%rbp), %rdi
callq 0xa470
movq -0x6b8(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
movl $0xa, %edx
callq 0xdad0
movl %eax, -0x6ac(%rbp)
jmp 0xc954
movl -0x6ac(%rbp), %eax
movl %eax, -0x51c(%rbp)
leaq -0x260(%rbp), %rdi
leaq -0x51c(%rbp), %rsi
callq 0xd9d0
movq %rax, -0x6c8(%rbp)
jmp 0xc97c
movq -0x6c8(%rbp), %rax
movq %rax, -0x530(%rbp)
leaq -0x260(%rbp), %rdi
callq 0xda00
movq %rax, -0x538(%rbp)
leaq -0x530(%rbp), %rdi
leaq -0x538(%rbp), %rsi
callq 0xd9a0
testb $0x1, %al
jne 0xc9b9
jmp 0xca70
movl $0x18, %edi
callq 0xa790
movq %rax, -0x6d0(%rbp)
jmp 0xc9cc
movq -0x6d0(%rbp), %rdi
movl -0x51c(%rbp), %esi
callq 0x230b0
jmp 0xc9e0
movq -0x6d0(%rbp), %rax
movq %rax, -0x528(%rbp)
leaq -0x548(%rbp), %rdi
leaq -0x51c(%rbp), %rsi
leaq -0x528(%rbp), %rdx
callq 0xda70
jmp 0xca0a
leaq -0x260(%rbp), %rdi
leaq -0x548(%rbp), %rsi
callq 0xda30
movb %dl, -0x6d9(%rbp)
movq %rax, -0x6d8(%rbp)
jmp 0xca2c
movb -0x6d9(%rbp), %al
movq -0x6d8(%rbp), %rcx
movq %rcx, -0x558(%rbp)
movb %al, -0x550(%rbp)
jmp 0xca9d
movq -0x6d0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x220(%rbp)
movl %eax, -0x224(%rbp)
movl $0x18, %esi
callq 0xa7b0
jmp 0xce53
leaq -0x260(%rbp), %rdi
leaq -0x51c(%rbp), %rsi
callq 0xdaa0
movq %rax, -0x6e8(%rbp)
jmp 0xca8c
movq -0x6e8(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x528(%rbp)
movq -0x458(%rbp), %rax
movl 0x10(%rax), %eax
movq -0x528(%rbp), %rcx
cmpl 0x10(%rcx), %eax
jle 0xcac3
movq -0x458(%rbp), %rax
movq %rax, -0x6f0(%rbp)
jmp 0xcad1
movq -0x528(%rbp), %rax
movq %rax, -0x6f0(%rbp)
movq -0x6f0(%rbp), %rax
movq %rax, -0x560(%rbp)
movq -0x560(%rbp), %rax
cmpq -0x458(%rbp), %rax
jne 0xcaff
movq -0x528(%rbp), %rax
movq %rax, -0x6f8(%rbp)
jmp 0xcb0d
movq -0x458(%rbp), %rax
movq %rax, -0x6f8(%rbp)
movq -0x6f8(%rbp), %rax
movq %rax, -0x568(%rbp)
movb $0x0, -0x569(%rbp)
leaq -0x298(%rbp), %rdi
leaq -0x560(%rbp), %rsi
callq 0xdb40
movq %rax, -0x700(%rbp)
jmp 0xcb3e
movq -0x700(%rbp), %rax
movq %rax, -0x578(%rbp)
leaq -0x298(%rbp), %rdi
callq 0xdb70
movq %rax, -0x580(%rbp)
leaq -0x578(%rbp), %rdi
leaq -0x580(%rbp), %rsi
callq 0xdb10
testb $0x1, %al
jne 0xcb7b
jmp 0xcc6d
xorps %xmm0, %xmm0
movaps %xmm0, -0x5e0(%rbp)
movaps %xmm0, -0x5f0(%rbp)
movaps %xmm0, -0x600(%rbp)
movq $0x0, -0x5d0(%rbp)
leaq -0x600(%rbp), %rdi
movq %rdi, -0x708(%rbp)
callq 0xdbe0
movq -0x708(%rbp), %rdx
leaq -0x5c0(%rbp), %rdi
leaq -0x560(%rbp), %rsi
callq 0xdc00
jmp 0xcbcd
leaq -0x298(%rbp), %rdi
leaq -0x5c0(%rbp), %rsi
callq 0xdba0
movb %dl, -0x711(%rbp)
movq %rax, -0x710(%rbp)
jmp 0xcbef
movb -0x711(%rbp), %al
movq -0x710(%rbp), %rcx
movq %rcx, -0x610(%rbp)
movb %al, -0x608(%rbp)
leaq -0x5c0(%rbp), %rdi
callq 0xdc40
leaq -0x600(%rbp), %rdi
callq 0xdc60
movb $0x1, -0x569(%rbp)
jmp 0xcc6d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x220(%rbp)
movl %eax, -0x224(%rbp)
jmp 0xcc5c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x220(%rbp)
movl %eax, -0x224(%rbp)
leaq -0x5c0(%rbp), %rdi
callq 0xdc40
leaq -0x600(%rbp), %rdi
callq 0xdc60
jmp 0xce53
leaq -0x298(%rbp), %rdi
leaq -0x560(%rbp), %rsi
callq 0xdc80
movq %rax, -0x720(%rbp)
jmp 0xcc89
movq -0x720(%rbp), %rax
movq %rax, -0x618(%rbp)
movq -0x618(%rbp), %rdi
leaq -0x568(%rbp), %rsi
callq 0xdce0
movq %rax, -0x728(%rbp)
jmp 0xccb3
movq -0x728(%rbp), %rax
movq %rax, -0x620(%rbp)
movq -0x618(%rbp), %rdi
callq 0xdd10
movq %rax, -0x628(%rbp)
leaq -0x620(%rbp), %rdi
leaq -0x628(%rbp), %rsi
callq 0xdcb0
testb $0x1, %al
jne 0xcced
jmp 0xcd30
movq -0x618(%rbp), %rdi
leaq -0x568(%rbp), %rsi
callq 0xdd40
movb %dl, -0x731(%rbp)
movq %rax, -0x730(%rbp)
jmp 0xcd0f
movb -0x731(%rbp), %al
movq -0x730(%rbp), %rcx
movq %rcx, -0x638(%rbp)
movb %al, -0x630(%rbp)
movb $0x1, -0x569(%rbp)
movb -0x569(%rbp), %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x1, %eax
jne 0xcdfb
movl $0x20, %edi
callq 0xa790
movq %rax, -0x740(%rbp)
jmp 0xcd57
movq -0x458(%rbp), %rax
movq %rax, -0x758(%rbp)
movq -0x528(%rbp), %rax
movq %rax, -0x750(%rbp)
leaq -0x2a8(%rbp), %rdi
leaq -0x2a0(%rbp), %rsi
callq 0xdd80
movsd %xmm0, -0x748(%rbp)
jmp 0xcd90
movsd -0x748(%rbp), %xmm0
movq -0x750(%rbp), %rdx
movq -0x758(%rbp), %rsi
movq -0x740(%rbp), %rdi
callq 0xb440
jmp 0xcdb4
movq -0x740(%rbp), %rax
movq %rax, -0x640(%rbp)
movq -0x8(%rbp), %rdi
movq -0x640(%rbp), %rsi
callq 0xcef0
jmp 0xcdd4
jmp 0xcdfb
movq -0x740(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x220(%rbp)
movl %eax, -0x224(%rbp)
movl $0x20, %esi
callq 0xa7b0
jmp 0xce53
movl -0x4cc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x4cc(%rbp)
jmp 0xc80b
leaq -0x4c8(%rbp), %rdi
callq 0xa470
leaq -0x4a8(%rbp), %rdi
callq 0xa470
movl $0x0, -0x450(%rbp)
leaq -0x448(%rbp), %rdi
callq 0xa300
movl -0x450(%rbp), %eax
testl %eax, %eax
je 0xce4e
jmp 0xce49
jmp 0xc5bb
jmp 0xc5bb
leaq -0x4c8(%rbp), %rdi
callq 0xa470
leaq -0x4a8(%rbp), %rdi
callq 0xa470
leaq -0x448(%rbp), %rdi
callq 0xa300
jmp 0xceb2
leaq -0x2c8(%rbp), %rdi
callq 0xa470
leaq -0x298(%rbp), %rdi
callq 0xddb0
leaq -0x260(%rbp), %rdi
callq 0xddd0
leaq -0x218(%rbp), %rdi
callq 0xa1b0
addq $0x760, %rsp            # imm = 0x760
popq %rbp
retq
leaq -0x2c8(%rbp), %rdi
callq 0xa470
leaq -0x298(%rbp), %rdi
callq 0xddb0
leaq -0x260(%rbp), %rdi
callq 0xddd0
leaq -0x218(%rbp), %rdi
callq 0xa1b0
movq -0x220(%rbp), %rdi
callq 0xade0
nop