예제 #1
0
void CDLib::generate_barabasi_albert_model(graph& g, size_t num_nodes, size_t min_degree_of_node) {
    init_empty_graph(g, num_nodes);
    vector<id_type> vertices_with_edges;
    UniformRandomGeneratorAkash<id_type> randint;
    UniformRandomGeneratorAkash<double> randdouble;

    for (id_type k = 1; k <= min_degree_of_node; k++) {
        g.add_edge(0, k, 1);
        vertices_with_edges.push_back(k);
    }

    for (id_type i = 1; i < num_nodes; i++) {
        while (g.get_node_in_degree(i) < min_degree_of_node) {
            double R1 = randdouble.next(1);
            if (R1 < 0.5) {
                id_type R2 = randint.next(vertices_with_edges.size());
                g.add_edge(i, vertices_with_edges[R2], 1);
                vertices_with_edges.push_back(vertices_with_edges[R2]);
            } else {
                id_type R3 = randint.next(i);
                g.add_edge(i, R3, 1);
                vertices_with_edges.push_back(R3);
            }
        }
    }
    g.set_graph_name("ba_" + T2str<size_t > (num_nodes) + "_" + T2str<size_t > (min_degree_of_node));
}
예제 #2
0
void CDLib::generate_LEET_chord_graph(graph& g, id_type num_nodes) {
    //    init_empty_graph(g,num_nodes);
    //    id_type cluster_size = log2(g.get_num_nodes());
    //    for (id_type i=0; i<g.get_num_nodes(); i++)
    //    {
    //        g.add_edge(i,(i-1) %  g.get_num_nodes(),1);
    //        g.add_edge(i,(i+1) %  g.get_num_nodes(),1);
    //        id_type id_in_cluster = g.get_num_nodes() % static_cast<id_type>(cluster_size);
    //        g.add_edge(i,id_in_cluster*(1+static_cast<id_type>(cluster_size)),1);
    //    }
    init_empty_graph(g, num_nodes);
    id_type num_clusters = num_nodes / log2(num_nodes);
    id_type num_nodes_per_cluster = static_cast<id_type> (log2(num_nodes));
    for (id_type i = 0; i < num_clusters; i++) {
        id_type start_id = i*num_nodes_per_cluster;
        //Adding the individual Clusters
        for (id_type j = 0; j < num_nodes_per_cluster; j++) {
            g.add_edge(start_id + j, start_id + ((j - 1) % num_nodes_per_cluster), 1);
            for (id_type k = 1; k <= num_nodes_per_cluster / 2; k *= 2)
                g.add_edge(start_id + j, start_id + ((j + k) % num_nodes_per_cluster), 1);
        }
        //Adding the long range links
        for (id_type j = log2(num_clusters) - 1, k = 0; j > 0; j--, k++) {
            id_type next_cluster_id = ((i + j) % num_clusters) * num_nodes_per_cluster;
            g.add_edge(start_id + (k % num_nodes_per_cluster), next_cluster_id + (j % num_nodes_per_cluster), 1);
        }
    }
    g.set_graph_name("leet_chord_" + T2str<id_type > (num_nodes));
    g.remove_isolates();
}
예제 #3
0
void CDLib::generate_chord_graph(graph& g, id_type num_nodes) {
    init_empty_graph(g, num_nodes);
    for (id_type i = 0; i < g.get_num_nodes(); i++) {
        g.add_edge(i, (i - 1) % g.get_num_nodes(), 1);
        for (id_type j = 1; j <= g.get_num_nodes() / 2; j *= 2)
            g.add_edge(i, (i + j) % g.get_num_nodes(), 1);
    }
    g.set_graph_name("chord_" + T2str<id_type > (num_nodes));
}
예제 #4
0
void CDLib::generate_spoke_graph(graph& g, id_type size) {
    generate_star_graph(g, size);
    id_type last_id = g.get_num_nodes() - 1;
    if (last_id > 1) {
        for (id_type i = 1; i < last_id; i++)
            g.add_edge(i, (i + 1), 1);
        g.add_edge(last_id, 1, 1);
    }
    g.set_graph_name("spoke_" + T2str<id_type > (size));
}
예제 #5
0
void CDLib::generate_clique_graph(graph& g, id_type size) {
    init_empty_graph(g, size);
    for (id_type i = 0; i < g.get_num_nodes(); i++)
        for (id_type j = 0; j < i; j++)
            if (i != j) g.add_edge(i, j, 1);
    g.set_graph_name("clique_" + T2str<id_type > (size));
}
예제 #6
0
파일: 1486.cpp 프로젝트: miskcoo/oicode
int main()
{
	std::freopen("circle.in", "r", stdin);
	std::freopen("circle.out", "w", stdout);
	int N, M;
	std::scanf("%d %d", &N, &M);
	gp.init(N);
	for(int i = 0; i != M; ++i)
	{
		int u, v;
		double w;
		std::scanf("%d %d %lf", &u, &v, &w);
		gp.add_edge(u, v, w);
	}

	double epsilon = 1.0e-9;
	double r = 1.0e8, l = -1.0e8;
	while(r - l > epsilon)
	{
		double m = (l + r) * 0.5;
		if(gp.has_neg_circle(m))
			r = m;
		else l = m;
	}
	std::printf("%.8f\n", l);
	return 0;
}
예제 #7
0
파일: graphio.cpp 프로젝트: BalkiLab/graffy
bool CDLib::read_edgelist(graph& g, const string& filepath) {
    g.clear();
    ifstream ifs;
    ifs.open(filepath.c_str());
    if (ifs.is_open()) {
        vector<string> units;
        double weight;
        while (!ifs.eof()) {
            weight = 1;
            string line;
            getline(ifs, line);
            if ((line.size() > 0) && (line[0] != '#')) {
                split(line, units);
                if (units.size() != 0) {
                    if ((units.size() < 2) || (units.size() > 3)) return false;
                    if (units.size() == 3) weight = str2T<double>(units[2]);
                    g.add_node(units[0]);
                    g.add_node(units[1]);
                    g.add_edge(units[0], units[1], weight);
                }
            }
        }
        g.set_graph_name(filename(filepath));
        return true;
    }
    return false;
}
예제 #8
0
/*degree distribution of this model follows power law distribution.
 * this is a most suitable synthetic model to real-world network like peer to peer networks and citation networks.*/
bool CDLib::generate_vertex_copying_model(graph& g, size_t num_nodes, size_t num_of_out_degree, size_t num_of_vertices_at_initial, double probability_to_copy_from_existing_vertex) {
    if (num_of_vertices_at_initial > num_of_out_degree && probability_to_copy_from_existing_vertex >= 0 && probability_to_copy_from_existing_vertex <= 1) {
        UniformRandomGeneratorAkash<wt_t> randdouble;
        UniformRandomGeneratorAkash<id_type> randint;

        init_empty_graph(g, num_nodes);

        for (id_type i = 0; i < num_of_vertices_at_initial; i++) {
            while (g.get_node_out_degree(i) < num_of_out_degree) {
back:
                id_type R1 = randint.next(num_of_vertices_at_initial);
                if (R1 == i)
                    goto back;
                else {
                    g.add_edge(i, R1, 1);
                }
            }
        }

        for (id_type i = num_of_vertices_at_initial; i < num_nodes; i++) {
            id_type R2 = randint.next(i);
            vector<id_type> vertices_pointed_by_R2;
            for (adjacent_edges_iterator aeit = g.out_edges_begin(R2); aeit != g.out_edges_end(R2); aeit++) {
                vertices_pointed_by_R2.push_back(aeit->first);
            }
            while (g.get_node_out_degree(i) < num_of_out_degree) {
                wt_t R3 = randdouble.next(1);
                if (R3 < probability_to_copy_from_existing_vertex) {
                    g.add_edge(i, vertices_pointed_by_R2[g.get_node_out_degree(i)], 1);

                } else {
A:
                    id_type R4 = randint.next(num_nodes);
                    if (R4 != i) {
                        g.add_edge(i, R4, 1);
                    } else
                        goto A;
                }
            }
        }
        g.set_graph_name("vc_" + T2str<size_t > (num_nodes) + "_" + T2str<size_t > (num_of_out_degree) + "_" + T2str<size_t > (num_of_vertices_at_initial) + "_" + T2str<double>(probability_to_copy_from_existing_vertex));
        return 1;
    } else {
        //        cout<<"\nnum_of_vertices_at_initial should greater than num_of_out_degree\n";
        return 0;
    }
}
예제 #9
0
	void
program2graph(vector<stmt*> const& p, 
		map<string,type*>& inputs, 
		map<string,type*>& inouts, 
		map<string,type*>& outputs, 
		graph& g)
{



	map<string, type*>::iterator i;
	for (i = inouts.begin(); i != inouts.end(); ++i) {
		inputs.insert(*i);
		outputs.insert(*i);
	}

	for (i = inputs.begin(); i != inputs.end(); i++) {
		set_container_size(i->first, *(i->second));
	}
	for (i = outputs.begin(); i != outputs.end(); i++) {
		set_container_size(i->first, *(i->second));
	}

	map<string, vertex> env;
	for (unsigned int i = 0; i != p.size(); ++i) {
		stmt* s = p[i];

		vertex tmp = s->rhs->to_graph(env, inputs, outputs, g);
		env[s->lhs] = tmp;
	}

	///// DEBUG
#ifdef DEBUG
	std::ofstream out("lower0.dot");
	print_graph(out, g);
#endif

	for (map<string,type*>::iterator i = outputs.begin(); i != outputs.end(); ++i) {
		vertex def = env[i->first];
		vertex_info vi; vi.t = *i->second; vi.op = output; vi.label = i->first;
		vi.eval = evaluate; vi.trivial = true;
		string name = i->first;
		set_container_size(name, vi.t);
		vertex v = g.add_vertex(vi);
		g.add_edge(def, v);
	}

	// push out types up to operation types
	for (vertex i = 0; i < g.num_vertices(); i++) {
		if (g.info(i).op == output) {
			std::vector<vertex> const& iav = g.inv_adj(i);
			for (vertex j = 0; j < iav.size(); j++) {
				if (g.info(iav[j]).t.k == unknown) {
					g.info(iav[j]).t = g.info(i).t;
				}
			}
		}
	}
}
예제 #10
0
void CDLib::generate_kademlia_graph(graph& g, id_type num_nodes) {
    init_empty_graph(g, num_nodes);
    unsigned int num_bits = log2(num_nodes);
    for (unsigned int i = 0; i < num_nodes; i++)
        for (unsigned int j = 0; j < num_bits; j++)
            g.add_edge(i, (i ^ ((1 << j))) % num_nodes, 1);
    g.set_graph_name("kademlia_" + T2str<id_type > (num_nodes));
}
예제 #11
0
파일: graphio.cpp 프로젝트: BalkiLab/graffy
bool CDLib::read_adjacencylist(graph& g, const string& filepath) {
    g.clear();
    ifstream ifs;
    ifs.open(filepath.c_str());
    if (ifs.is_open()) {
        int type = 0;
        id_type nid = 0, estart = 0;
        string line;
        getline(ifs, line);
        vector<id_type> units;
        split(line, units);
        if ((units.size() > 2) && (units[0] == 0) && (units[1] == units.size() - 2)) {
            type = 0;
            estart = 2;
        } else if ((units.size() > 1) && (units[0] == 0)) {
            type = 1;
            estart = 1;
        } else {
            type = 2;
            estart = 0;
        }
        g.add_node(to_string(nid));
        for (id_type i = estart; i < units.size(); i++) {
            g.add_node(to_string(units[i]));
            g.add_edge(to_string(nid), to_string(units[i]), 1);
        }
        while (!ifs.eof()) {
            string line;
            getline(ifs, line);
            vector<id_type> units;
            split(line, units);
            if (units.size() > 0) {
                if ((type == 0) || (type == 1)) nid = units[0];
                else nid++;
                g.add_node(to_string(nid));
                for (id_type i = estart; i < units.size(); i++) {
                    g.add_node(to_string(units[i]));
                    g.add_edge(to_string(nid), to_string(units[i]), 1);
                }
            }
        }
        g.set_graph_name(filename(filepath));
        return true;
    }
    return false;
}
예제 #12
0
void CDLib::generate_erdos_renyi_graph(graph& g, id_type num_nodes, double p) {
    if (p >= 0 && p <= 1) {
        init_empty_graph(g, num_nodes);
        RandomGenerator<double> p_gen(0, 1, 1);
        for (id_type i = 0; i < num_nodes; i++)
            for (id_type j = 0; j < num_nodes; j++)
                if ((!g.is_directed() && i < j) && p_gen.next() <= p) g.add_edge(i, j, 1);
        g.set_graph_name("er_" + T2str<id_type > (num_nodes) + "_" + T2str<double>(p));
    }
}
예제 #13
0
void CDLib::generate_de_bruijn_graph(graph& g, id_type num_symbols, id_type sequence_length) {
    if (num_symbols && sequence_length) {
        id_type size = (unsigned long) pow((double) num_symbols, (double) sequence_length);
        init_empty_graph(g, size);
        for (id_type i = 0; i < g.get_num_nodes(); i++) {
            id_type basis = (i * num_symbols) % g.get_num_nodes();
            for (id_type j = 0; j < num_symbols; j++) g.add_edge(i, basis + j, 1);
        }
        g.set_graph_name("db_" + T2str<id_type > (num_symbols) + "_" + T2str<id_type > (sequence_length));
    }
}
예제 #14
0
void CDLib::generate_planted_partition_graph(graph& g, id_type num_comms, id_type comm_size, double pin, double pout, vector< node_set>& communities) {
    if (pin >= 0 && pout >= 0 && pin <= 1 && pout <= 1) {
        id_type num_nodes = comm_size*num_comms;
        init_empty_graph(g, num_nodes);
        communities.assign(num_comms, node_set());
        Uniform01RandomGeneratorMT p_gen;
        for (id_type i = 0; i < num_nodes; i++)
            if (i % comm_size) communities[i / comm_size].insert(i);
        for (id_type i = 0; i < g.get_num_nodes(); i++) {
            id_type comm_id_i = i / comm_size;
            for (id_type j = 0; j < g.get_num_nodes(); j++) {
                id_type comm_id_j = j / comm_size;
                double p = p_gen.next();
                if (comm_id_i == comm_id_j && p > pin) g.add_edge(i, j, 1);
                else if (p > pout) g.add_edge(i, j, 1);
            }
        }
        g.set_graph_name("pp_" + T2str<id_type > (num_comms) + "_" + T2str<id_type > (comm_size) + "_" + T2str<double>(pin) + "_" + T2str<double>(pout));
    }
}
예제 #15
0
void CDLib::generate_scale_free_graph(graph& g, id_type num_nodes, id_type num_edges, double alpha, double beta) {
    init_empty_graph(g, num_nodes);
    RandomGenerator<id_type> x_gen(0, num_nodes), from_gen(0, num_nodes), to_gen(0, num_nodes);
    vector<id_type> outdegrees(num_nodes, 0.0);
    for (id_type i = 0; i < num_nodes; i++)
        outdegrees[i] = (id_type) x_gen.exp_next(alpha, beta);
    for (id_type i = 0; i < num_edges; i++) {
        id_type from_id = from_gen.next(), to_id = to_gen.next();
        if (outdegrees[from_id] && outdegrees[to_id] && from_id != to_id && !g.get_edge_weight(from_id, to_id))
            g.add_edge(from_id, to_id, 1);
    }
    g.set_graph_name("sf_" + T2str<id_type > (num_nodes) + "_" + T2str<id_type > (num_edges) + "_" + T2str<double>(alpha) + "_" + T2str<double>(beta));
}
예제 #16
0
void CDLib::generate_prices_model(graph& g, size_t num_nodes, size_t num_of_out_degree, size_t in_degree_constant) {
    init_empty_graph(g, num_nodes);
    vector<id_type> vertices_pointed_by_edges;
    UniformRandomGeneratorAkash<id_type> randint;
    UniformRandomGeneratorAkash<double> randdouble;

    double probability = num_of_out_degree / (num_of_out_degree + in_degree_constant);

    for (id_type i = 0; i < num_nodes; i++) {
        while (g.get_node_out_degree(i) < num_of_out_degree) {
            double R1 = randdouble.next(1);
            if (R1 < probability) {
                id_type R2 = randint.next(vertices_pointed_by_edges.size());
                g.add_edge(i, vertices_pointed_by_edges[R2], 1);
                vertices_pointed_by_edges.push_back(vertices_pointed_by_edges[R2]);
            } else {
                id_type R3 = randint.next(num_nodes);
                g.add_edge(i, R3, 1);
                vertices_pointed_by_edges.push_back(R3);
            }
        }
    }
    g.set_graph_name("price_" + T2str<size_t > (num_nodes) + "_" + T2str<size_t > (num_of_out_degree) + "_" + T2str<size_t > (in_degree_constant));
}
예제 #17
0
/*this model is used to generate graph with high clustering coefficient.
 this model matches sports network like american football league.*/
bool CDLib::generate_small_world_model(graph& g, size_t num_nodes, size_t degree_of_each_vertex, double probability_to_replace_edge) {
    if (probability_to_replace_edge >= 0 && probability_to_replace_edge <= 1) {
        UniformRandomGeneratorAkash<id_type> randint;
        UniformRandomGeneratorAkash<double> randdouble;

        init_empty_graph(g, num_nodes);

        for (id_type i = 0; i < num_nodes; i++) {
            for (id_type j = 0; j < degree_of_each_vertex / 2; j++) {
                g.add_edge(i, (i + j + 1) % num_nodes, 1);
            }
            if (degree_of_each_vertex % 2 == 1) {
                g.add_edge(i, (i + (degree_of_each_vertex / 2) + 1) % num_nodes, 1);
            }
        }
        for (id_type i = 0; i < num_nodes; i++) {
            for (id_type j = 0; j < degree_of_each_vertex; j++) {
                double R1 = randdouble.next(1);
                if (R1 < probability_to_replace_edge) {
back:
                    id_type R2 = randint.next(num_nodes);
                    if (R2 == i)
                        goto back;
                    else {
                        g.add_edge(i, R2, 1);
                    }
                }
            }
        }
        g.set_graph_name("sw_" + T2str<size_t > (num_nodes) + "_" + T2str<size_t > (degree_of_each_vertex) + "_" + T2str<double>(probability_to_replace_edge));
        return 1;
    } else {
        //        cout<<"\nprobability value might be wrong";
        return 0;
    }
}
예제 #18
0
파일: graphio.cpp 프로젝트: BalkiLab/graffy
bool CDLib::read_matlab_sp(graph& g, const string& filepath) {
    g.clear();
    ifstream ifs;
    ifs.open(filepath.c_str());
    if (ifs.is_open()) {
        id_type from, to;
        double weight = 1;
        while (!ifs.eof()) {
            ifs >> from >> to >> weight;
            while (max(from, to) > g.get_num_nodes()) {
                g.add_node();
            }
            g.add_edge(from - 1, to - 1, weight);
        }
        g.set_graph_name(filename(filepath));
        return true;
    }
예제 #19
0
/*
 * Given the tokens from one line (split on whitespace) and a tree
 * decomposition, this reads the edge (in the graph) represented by this line
 * and adds the respective edge to the graph
 */
void read_graph_edge(const std::vector<std::string>& tokens, graph& g)
{
  if (current_state == P_LINE) {
    current_state = EDGES;
  }

  if (current_state != EDGES) {
    throw std::invalid_argument(INV_FMT);
  }

  unsigned s = pure_stou(tokens[0]);
  unsigned d = pure_stou(tokens[1]);
  if(s < 1 || d < 1 || s > n_vertices || d > n_vertices) {
    throw std::invalid_argument(INV_EDGE);
  }
  g.add_edge(s-1, d-1);
}
예제 #20
0
void CDLib::generate_configuration_model(graph& g, vector<id_type>& degree_sequence) {
    if (degree_sequence.size() > 0) {
        init_empty_graph(g, degree_sequence.size());
        vector<id_type> nodes_with_non_0_degree;

        for (id_type i = 0; i < degree_sequence.size(); i++) {
            if (degree_sequence[i] != 0) {
                nodes_with_non_0_degree.push_back(i);
            }
        }

        UniformRandomGeneratorAkash<id_type> rand;
        for (id_type i = 0; i < degree_sequence.size(); i++) {
            id_type remaining_degree = degree_sequence[i];
            for (id_type j = 0; j < remaining_degree; j++) {
back:
                id_type R = rand.next(nodes_with_non_0_degree.size());
                if (degree_sequence[i] == 1 && i == nodes_with_non_0_degree[R])
                    goto back;

                g.add_edge(i, nodes_with_non_0_degree[R], 1);

                degree_sequence[i]--;
                degree_sequence[nodes_with_non_0_degree[R]]--;

                if (degree_sequence[nodes_with_non_0_degree[R]] == 0) {
                    if (nodes_with_non_0_degree[R] == i)
                        break;
                    nodes_with_non_0_degree.erase(nodes_with_non_0_degree.begin() + R);
                }
                if (degree_sequence[i] == 0)
                    break;
            }
            if (remaining_degree != 0) {
                nodes_with_non_0_degree.erase(nodes_with_non_0_degree.begin());
            }
        }
        g.set_graph_name("configuration_model");
    }
}
예제 #21
0
int find_or_add_op(op_code op, vector<vertex> const& rands, graph& g) {
	for (unsigned int i = 0; i != g.num_vertices(); ++i) {
		if (g.info(i).op == op) {
			if (rands.size() == g.inv_adj(i).size()
					&& includes(rands.begin(), rands.end(), g.inv_adj(i).begin(), g.inv_adj(i).end()))
				return i;
		}
	}
	int n;
	if (op == trans && rands.size() > 0 && g.info(rands[0]).label.compare("") != 0) {
		vertex_info vi(op, g.info(rands[0]).label);
		n = g.add_vertex(vi);
	}
	else {
		vertex_info vi(op); 
		n = g.add_vertex(vi);
	}

	for (unsigned int i = 0; i != rands.size(); ++i)
		g.add_edge(rands[i], n);

	return n;
}
예제 #22
0
void CDLib::generate_ring_graph(graph& g, id_type size) {
    init_empty_graph(g, size);
    for (id_type i = 0; i < g.get_num_nodes(); i++)
        g.add_edge(i, (i + 1) % size, 1);
    g.set_graph_name("ring_" + T2str<id_type > (size));
}
예제 #23
0
void CDLib::generate_star_graph(graph& g, id_type size) {
    init_empty_graph(g, size);
    for (id_type i = 1; i < g.get_num_nodes(); i++)
        g.add_edge(0, i, 1);
    g.set_graph_name("star_" + T2str<id_type > (size));
}
예제 #24
0
파일: graph.cpp 프로젝트: Nishesh1412/CU
// read in 120 cities and their latitude/longitude
// cities within limit km of each other are connected by edges
void init_graph_from_file(graph& g, const string& filename, double limit)
{
    string line;
    string city_name;
    int lat1, lat2, long1, long2;
    ifstream file_to_read;
    string part_string;
    char compass_dir;

    // open the data file of cities
    open_for_read(file_to_read, filename.c_str());
    size_t count = 0;
    // keep reading until all cities have been added
    while (is_more_stuff_there(file_to_read) && count < 120)
    {
        string city_name = "";
        // build the city name from the file
        do
        {
            file_to_read >> part_string;
            city_name += part_string + ' ';
        } while (city_name[city_name.length() - 2] != ':');
        city_name = city_name.substr(0, city_name.length() - 2);

        // grab latitude coordinates
        file_to_read >> lat1 >> lat2 >> compass_dir;
        // southern coordinates are negative
        if (compass_dir == 'S')
        {
            lat1 *= -1;
            lat2 *= -1;
        }
        // and grab longitude coordinates
        file_to_read >> long1 >> long2 >> compass_dir;
        // western coordinates are negative
        if (compass_dir == 'W')
        {
            long1 *= -1;
            long2 *= -1;
        }
        // create a city vertex in the graph from the data you read
        vertex city(city_name, lat1, lat2, long1, long2);
        g.add_vertex(city);
        ++count;
    }

    // now we are done with our file
    file_to_read.close();

    // now we compute the edges that are within the allowed distance
    vector<vertex>::iterator it1, it2;
    for (it1 = g.vertices.begin(); it1 != g.vertices.end(); ++it1)
    {
        for (it2 = g.vertices.begin(); it2 != g.vertices.end(); ++it2)
        {
            if (it1 != it2)
            {
                g.add_edge(&*it1, &*it2, limit);
            }
        }
    }
}
    int load(const int argc, const char *argv[])
    {
        /***************************
         * CHECK IF IS FILE EXISTS *
         ***************************/
        if(argc < 2)
        {
            fprintf(stdout, "Warning: Resource file not loaded.\nUsage: %s [path_of_file]\n", argv[0]);
            return 1;
        }

        parser fp;
        if(fp.open(argv[1]) != true)
        {
            fprintf(stdout, "Error: File '%s' not found.\n", argv[1]);
            return 2;
        }

        clock_t begin, end;
        double elapsed_secs = 0;

        /***************************
         * READ FILE               *
         ***************************/
        std::cout << "Step 1 of 2: Read a file, add to the vertex of the graph, add to the BST (together) . . . ";
        begin = clock();

        fp.parse(
            [&] (const std::string &line)
            {
                std::string arr[5];
                fp.divide_by_delimiter(arr, line, 5, '\t');
                /*
                    arr[0] = StateAbb
                    arr[1] = PlaceName
                    arr[2] = longitude
                    arr[3] = latitude
                    arr[4] = DistancetoCapitalCity_km
                */

                std::string city_name = arr[1];
                double longitude, latitude;
                try
                {
                    longitude = stod(arr[2]);
                    latitude = stod(arr[3]);
                }
                catch(const std::invalid_argument &e)
                {
                    return; /* Invalid line, so we should not add this line */
                }

                /* Add to graph */
                int key = g.add_vertex(graphelement(arr[1]));
                if(key == -1) /* Duplicate city name */
                {
                    char *temp = new char[5]();
                    for(int i = 2; ; ++i) /* suffix start with #2 */
                    {
                        std::snprintf(temp, 5, "%d", i);
                        if((key = g.add_vertex(graphelement(std::string(city_name + " #" + temp)))) != -1)
                        {
                            city_name = city_name + " #" + temp;
                            break;
                        }
                    }
                    delete temp;
                }

                /* Add to BST */
                bstelement *element = new bstelement(city_name, key, longitude, latitude);
                bst->add(element);
            }
        );

        end = clock();
        std::cout << "Finished (" << elapsed_secs(begin, end) << "sec)" << std::endl;
        //bst->printall();

        std::cout << "Step 2 of 2: Add the edges to each vertex . . . ";
        begin = clock();

        double lat1, lon1, lat2, lon2;
        bst->traverse_level_order(
            [&] (bstnode *node)
            {
                bst->binary_search_tree::traverse_level_order(
                    [&] (bstnode *n)
                    {
                        if(10000 >= calc_distance(node->element->latitude,
                                                  node->element->longitude,
                                                  n->element->latitude,
                                                  n->element->longitude))
                        {
                            if(node->element->latitude < n->element->latitude
                                && node->element->longitude < n->element->longitude)
                            {
                                bool is_connected = false;
                                g.traverse(n->element->value,
                                    [&] (graph<graphelement>::node* edgn)
                                    { if(edgn->key == node->element->value) is_connected = true; }
                                );
                                if(! is_connected)
                                    g.add_edge(node->element->value, n->element->value);
                            }
                        }
                    }
                );
            }
        );

        end = clock();
        std::cout << "Finished (" << elapsed_secs(begin, end) << "sec)" << std::endl;
        g.print();
    }