ReductionType map_reduce_vertices(GraphType& g,
                                      MapFunctionType mapfunction,
                                      const vertex_set& vset = GraphType::complete_set()) {
      BOOST_CONCEPT_ASSERT((graphlab::Serializable<ReductionType>));
      BOOST_CONCEPT_ASSERT((graphlab::OpPlusEq<ReductionType>));
      typedef typename GraphType::vertex_type vertex_type;

      if(!g.is_finalized()) {
        logstream(LOG_FATAL)
          << "\n\tAttempting to run graph.map_reduce_vertices(...) "
          << "\n\tbefore calling graph.finalize()."
          << std::endl;
      }
      g.dc().barrier();
      bool global_result_set = false;
      ReductionType global_result = ReductionType();
#ifdef _OPENMP
#pragma omp parallel
#endif
      {
        bool result_set = false;
        ReductionType result = ReductionType();
#ifdef _OPENMP
        #pragma omp for
#endif
        for (int i = 0; i < (int)g.num_local_vertices(); ++i) {
          auto lvertex = g.l_vertex(i);
          if (lvertex.owned() && vset.l_contains(lvid_type(i))) {
            if (!result_set) {
              vertex_type vtx(lvertex);
              result = mapfunction(vtx);
              result_set = true;
            }
            else if (result_set){
              const vertex_type vtx(lvertex);
              const ReductionType tmp = mapfunction(vtx);
              result += tmp;
            }
          }
        }
#ifdef _OPENMP
        #pragma omp critical
#endif
        {
          if (result_set) {
            if (!global_result_set) {
              global_result = result;
              global_result_set = true;
            }
            else {
              global_result += result;
            }
          }
        }
      }
      conditional_addition_wrapper<ReductionType>
        wrapper(global_result, global_result_set);
      g.dc().all_reduce(wrapper);
      return wrapper.value;
    } // end of map_reduce_vertices
static void breadth_first_search(const GraphType& graph, 
                                 const VertexIndexType& source,
                                 const int& k_steps,
                                 AssociativeContainer& visited_vertices) {
  /* CHECK: AssociativeContainer::value_type == VertexIndexType */

  std::queue<VertexIndexType> even_epoch_queue;
  std::queue<VertexIndexType> odd_epoch_queue;
  std::queue<VertexIndexType>& current_queue = even_epoch_queue;
  std::queue<VertexIndexType>& next_queue = odd_epoch_queue;

  current_queue.push (source);
  int step_number = 0;
  while (step_number<k_steps) {
    while (!current_queue.empty ()) {
      const int vertex = current_queue.front ();
      current_queue.pop ();
      visited_vertices.insert (vertex);
      for (int target_index=graph.begin(vertex); 
           target_index<graph.end(vertex);
           ++target_index) {
        const int target = graph.get_target (target_index);
        if (visited_vertices.end()==visited_vertices.find (target)) {
          next_queue.push (target);
        }
      }
    }
    ++step_number;
    current_queue = (step_number&0x10)?even_epoch_queue:odd_epoch_queue;
    next_queue = (step_number&0x01)?even_epoch_queue:odd_epoch_queue;
  }
}
Example #3
0
static void makeGraph(GraphType &graph, double** input, int matrix_size) {
     
    std::vector<SGNode> nodes;
    nodes.resize(matrix_size); 
    for(int i = 0; i<matrix_size; i++){
		Node n; 
		n.id = i;
		SGNode node = graph.createNode(n);
		graph.addNode(node); 
		nodes[i] = node; 
	} 
	
	
	int numEdges = 0; 
	for(int i = 0; i<matrix_size; i++){
		SGNode src = nodes[i];
		for(int j = i; j<matrix_size; j++){
			if(input[i][j] != 0){
				typename GraphType::edge_iterator it = graph.addEdge(src, nodes[j], Galois::MethodFlag::NONE);
				graph.getEdgeData(it) = input[i][j];
				numEdges++;
			}
			
		}
	}
   
   //#if BORUVKA_DEBUG
   std::cout << "Final num edges " << numEdges << std::endl;
   //#endif
}
Example #4
0
int main()
{
	typedef Graph<int,int,int> GraphType;
	GraphType *g = new GraphType(/*estimated # of nodes*/ 2, /*estimated # of edges*/ 1); 

	g -> add_node(); 
	g -> add_node(); 

	g -> add_tweights( 0,   /* capacities */  1, 5 );
	g -> add_tweights( 1,   /* capacities */  2, 6 );
	g -> add_edge( 0, 1,    /* capacities */  3, 4 );

	int flow = g -> maxflow();

	printf("Flow = %d\n", flow);
	printf("Minimum cut:\n");
	if (g->what_segment(0) == GraphType::SOURCE)
		printf("node0 is in the SOURCE set\n");
	else
		printf("node0 is in the SINK set\n");
	if (g->what_segment(1) == GraphType::SOURCE)
		printf("node1 is in the SOURCE set\n");
	else
		printf("node1 is in the SINK set\n");

	delete g;

	return 0;
}
GraphType* create_graph(std::vector< EdgeType >& edges,
                        std::vector<int>& curr_edge_cap,
                        std::vector<int>& curr_lambda_cap,
                        const std::vector<int>& fg_nodes, const int INFTY,
                        const int NUM_NODES, const bool fg_cap_inf) {
  bool is_fg;
  GraphType *g = new GraphType(NUM_NODES, edges.size());
  g->add_node(NUM_NODES);
  for (unsigned int i = 0; i < NUM_NODES; ++i) {
    is_fg = false;
    for (unsigned int j = 0; j < fg_nodes.size(); ++j) {
      if (i == fg_nodes[j]) {
        is_fg = true;
        break;
      }
    }
    if (is_fg)
      g->add_tweights(i, /* capacities */(fg_cap_inf ? INFTY : curr_lambda_cap[i]), 0);
    else
      g->add_tweights(i, /* capacities */0, curr_lambda_cap[i]);
  }

  /* capacity edges */
  for (unsigned int i = 0; i < edges.size(); ++i) {
    g->add_edge(edges[i].first, edges[i].second, curr_edge_cap[i],
                curr_edge_cap[i]);
  }

  return g;
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    // Variable Initializations
    int *inp_param;
    double *t_links, *n_links;
    int i;
    if ( (nrhs != 3) || ( mxGetClassID(prhs[0]) != mxINT32_CLASS ) ) 
        mexErrMsgTxt("ERROR1");
    inp_param = (int*)mxGetPr(prhs[0]);
    t_links = (double*)mxGetPr(prhs[1]);    
    n_links = (double*)mxGetPr(prhs[2]);
    typedef Graph<double,double,double> GraphType; // Declaring the graph ...
    GraphType *g = new GraphType( inp_param[1],  (2*inp_param[1]) + (2*inp_param[2]) ); 
    
    g -> add_node(inp_param[1]); // Creating the grid of all nodes put together ... 
    for(i=0; i<inp_param[1] ; i++)  
        g -> add_tweights(i, t_links[2*i], t_links[2*i+1] );
    for(i=0;i<inp_param[2];i++)
        g -> add_edge( n_links[3*i] , n_links[3*i+1] , n_links[3*i+2] , n_links[3*i+2]  );
    int flow = g -> maxflow();
    mexPrintf("Value of flow is %d \n",flow);
    // RETURN VARIABLE
    plhs[0] = mxCreateDoubleMatrix(inp_param[1], 1, mxREAL);
    double* outArray = (double*)mxGetPr(plhs[0]);
    for(i=0;i<inp_param[1];i++)
       outArray[i] = g->what_segment(i); 
    delete g;
    return;
}
/**
 * A method that samples uniformly from the given graph without replacement.
 * This sampling scheme is used as a baseline to measure the performance of 
 * other sampling schemes --- they have to perform at least as well as this.
 *
 * \param[in] graph The graph that we are sampling from.
 * \param[in] num_samples The number of samples to take.
 * \param[in] rand_seed The seed for the random number generator.
 * \param[in] sample A vector containing the edges that were sampled.
 */
static void uniform_sample
  (const GraphType& graph,
   const int& num_samples,
   const int& rand_seed,
   const bool& symmetrize,
   std::vector<bool>& samples) { 

  /* The range for the random number generator is [0..num_edges) */
  const int lower = 0;
  const int upper = graph.get_num_edges ();

  /* Keep a record of all the edges that have been sampled */
  samples.resize (upper);
  for (int i=0; i<upper; ++i) samples [i] = false;

  /* Generate 'num_samples' random numbers and pick an edge each time */
  prng rand_gen (rand_seed);

  for (int i=0; i<num_samples; ++i) {
    int current_edge_index;
    do { 
      current_edge_index = floor (rand_gen.next (lower, upper));
    } while (samples [current_edge_index]);

    samples [current_edge_index] = true;
    if (symmetrize) {
      const int reverse_edge_index = 
                graph.get_reverse_target_index (current_edge_index);
      samples[reverse_edge_index] = true;
    }
  }
}
Example #8
0
static typename GraphType::EdgeNodeIterator
sgl_random_edge(GraphType &g)
{
    size_t n = g.nEdges();
    assert(n>0);
    size_t id = rand() % n;
    return g.findEdge(id);
}
Example #9
0
static typename GraphType::VertexNodeIterator
sgl_random_vertex(GraphType &g)
{
    size_t n = g.nVertices();
    assert(n>0);
    size_t id = rand() % n;
    return g.findVertex(id);
}
 /** Set Fixed Constraint.
 * @param[in] g Valid graph.
 * @param[in] t Valid time.
 * @post The velocity of Point(0,0,0) and Point(1,0,0) are 0.
 */
 void operator()(GraphType& g, double t) {
   (void) t;     // silence compiler warnings
   for (GraphType::NodeIterator it = g.node_begin(); it != g.node_end(); ++it) {
     Node n = (*it);
     if (n.position() == Point(0,0,0) || n.position() == Point(1,0,0)) {
       n.value().vel =  Point(0,0,0);
     }
   }
 }
GraphType* FinleyDomain::createTrilinosGraph(bool reducedOrder) const
{
    index_t myNumTargets;
    index_t numTargets;
    const index_t* target;
    const_TrilinosMap_ptr rowMap;
    const_TrilinosMap_ptr colMap;
    if (reducedOrder) {
        myNumTargets = m_nodes->getNumReducedDegreesOfFreedom();
        numTargets = m_nodes->getNumReducedDegreesOfFreedomTargets();
        target = m_nodes->borrowTargetReducedDegreesOfFreedom();
        rowMap = m_nodes->trilinosReducedRowMap;
        colMap = m_nodes->trilinosReducedColMap;
    } else {
        myNumTargets = m_nodes->getNumDegreesOfFreedom();
        numTargets = m_nodes->getNumDegreesOfFreedomTargets();
        target = m_nodes->borrowTargetDegreesOfFreedom();
        rowMap = m_nodes->trilinosRowMap;
        colMap = m_nodes->trilinosColMap;
    }

    boost::scoped_array<IndexList> indexList(new IndexList[numTargets]);

#pragma omp parallel
    {
        // insert contributions from element matrices into columns in
        // index list
        IndexList_insertElements(indexList.get(), m_elements, reducedOrder,
                                 target, reducedOrder, target);
        IndexList_insertElements(indexList.get(), m_faceElements,
                                 reducedOrder, target, reducedOrder, target);
        IndexList_insertElements(indexList.get(), m_contactElements,
                                 reducedOrder, target, reducedOrder, target);
        IndexList_insertElements(indexList.get(), m_points, reducedOrder,
                                 target, reducedOrder, target);
    }

    Teuchos::ArrayRCP<size_t> rowPtr(myNumTargets + 1);
    for (size_t i = 0; i < myNumTargets; i++) {
        rowPtr[i+1] = rowPtr[i] + indexList[i].count(0, numTargets);
    }

    Teuchos::ArrayRCP<LO> colInd(rowPtr[myNumTargets]);

#pragma omp parallel for
    for (index_t i = 0; i < myNumTargets; i++) {
        indexList[i].toArray(&colInd[rowPtr[i]], 0, numTargets, 0);
        std::sort(&colInd[rowPtr[i]], &colInd[rowPtr[i+1]]);
    }

    GraphType* graph = new GraphType(rowMap, colMap, rowPtr, colInd);
    Teuchos::RCP<Teuchos::ParameterList> params = Teuchos::parameterList();
    params->set("Optimize Storage", true);
    graph->fillComplete(rowMap, rowMap, params);
    return graph;
}
Example #12
0
static void
sgl_random_graph(GraphType &g, size_t max_vertices, int vertex_time_limit, double edge_to_vertex_ratio)
{
    start_deadman(vertex_time_limit);
    for (size_t i=0; i<max_vertices && !had_alarm; ++i)
        g.insertVertex(0);

    for (size_t i=g.nVertices()*edge_to_vertex_ratio; i>0; --i)
        g.insertEdge(sgl_random_vertex(g), sgl_random_vertex(g), 0);
}
Example #13
0
static void
yagi_random_graph(GraphType &g, size_t max_vertices, int vertex_time_limit, double edge_to_vertex_ratio)
{
    start_deadman(vertex_time_limit);
    for (size_t i=0; i<max_vertices && !had_alarm; ++i)
        g.add_vertex();

    for (size_t i=g.num_vertices()*edge_to_vertex_ratio; i>0; --i)
        g.add_edge(yagi_random_vertex(g), yagi_random_vertex(g));
}
 /** Horizontal Constraint Setter
 * @param[in] g Valid graph.
 * @param[in] t Valid time.
 * @post Any node violating this constraint has:
 *       velocity in @a z_ direction set to 0
 *       position set to the nearest point to the horizontal plane defined by @a z_.
 */
 void operator()(GraphType& g, double t) {
   (void) t;     // silence compiler warnings
   for (GraphType::NodeIterator it = g.node_begin(); it != g.node_end(); ++it) {
     Node n = (*it);
     if (n.position().z < z_) {
       n.position().z = z_;
       n.value().vel.z = 0;
     }
   }
 }
Example #15
0
void run_GridCut_3D_6C(MFI* mfi,unsigned char* out_label,int* out_maxflow,double* time_init,double* time_maxflow,double* time_output)
{
  const int w = mfi->width;
  const int h = mfi->height;
  const int d = mfi->depth;
  
  const type_terminal_cap* cap_source = (type_terminal_cap*)mfi->cap_source;
  const type_terminal_cap* cap_sink   = (type_terminal_cap*)mfi->cap_sink;
  
  const type_neighbor_cap* cap_neighbor[6] = { (type_neighbor_cap*)(mfi->cap_neighbor[0]),
                                               (type_neighbor_cap*)(mfi->cap_neighbor[1]),
                                               (type_neighbor_cap*)(mfi->cap_neighbor[2]),
                                               (type_neighbor_cap*)(mfi->cap_neighbor[3]),
                                               (type_neighbor_cap*)(mfi->cap_neighbor[4]),
                                               (type_neighbor_cap*)(mfi->cap_neighbor[5]) };
    
  typedef GridGraph_3D_6C<type_terminal_cap,type_neighbor_cap,int> GraphType;

  CLOCK_START();
  GraphType* graph = new GraphType(w,h,d); 

  for(int z=0;z<d;z++)
  for(int y=0;y<h;y++)
  for(int x=0;x<w;x++)
  {
    const int node = graph->node_id(x,y,z);

    graph->set_terminal_cap(node,cap_source[x+y*w+z*(w*h)],cap_sink[x+y*w+z*(w*h)]);
    
    if (x>0  ) graph->set_neighbor_cap(node,-1, 0, 0,cap_neighbor[MFI::ARC_LEE][x+y*w+z*(w*h)]);
    if (x<w-1) graph->set_neighbor_cap(node,+1, 0, 0,cap_neighbor[MFI::ARC_GEE][x+y*w+z*(w*h)]);
    if (y>0  ) graph->set_neighbor_cap(node, 0,-1, 0,cap_neighbor[MFI::ARC_ELE][x+y*w+z*(w*h)]);
    if (y<h-1) graph->set_neighbor_cap(node, 0,+1, 0,cap_neighbor[MFI::ARC_EGE][x+y*w+z*(w*h)]);
    if (z>0  ) graph->set_neighbor_cap(node, 0, 0,-1,cap_neighbor[MFI::ARC_EEL][x+y*w+z*(w*h)]);
    if (z<d-1) graph->set_neighbor_cap(node, 0, 0,+1,cap_neighbor[MFI::ARC_EEG][x+y*w+z*(w*h)]);
  }
  CLOCK_STOP(time_init);

  CLOCK_START();
  graph->compute_maxflow();
  CLOCK_STOP(time_maxflow)
  
  CLOCK_START();
  *out_maxflow = graph->get_flow();

  for(int z=0;z<d;z++)
  for(int y=0;y<h;y++)
  for(int x=0;x<w;x++)
  {
    out_label[x+y*w+z*(w*h)] = graph->get_segment(graph->node_id(x,y,z));
  }
  
  delete graph;
  CLOCK_STOP(time_output);
}
Example #16
0
Totals
sgl_time_add_vertex()
{
    GraphType g;
    start_deadman(2);
    Sawyer::Stopwatch t;
    while (!had_alarm && g.nVertices()<MAX_VERTICES)
        g.insertVertex(0);
    t.stop();
    return report("add vertex", sgl_size(g), g.nVertices(), t, "verts/s");
}
 /** Remove Sphere Setter.
 * @param[in] g Valid graph.
 * @param[in] t Valid time.
 * @post Nodes that move through the sphere are removed from the graph.
 */
 void operator()(GraphType& g, double t) {
   (void) t;     // silence compiler warnings
   for (GraphType::NodeIterator it = g.node_begin(); it != g.node_end(); ++it) {
     Node n = (*it);
     double dist = norm(n.position() - center_);
     // Remove violating nodes
     if (dist < r_){
       g.remove_node(n);
     }
   }
 }
Example #18
0
Totals
sage_time_add_vertex()
{
    GraphType *g = new GraphType;
    start_deadman(2);
    Sawyer::Stopwatch t;
    while (!had_alarm && g->numberOfGraphNodes()<MAX_VERTICES)
        g->addNode(new SgGraphNode);
    t.stop();
    return report("add vertex", sage_size(g), g->numberOfGraphNodes(), t, "verts/s");
}
Example #19
0
typename GraphType::edge_iterator
findEdge(GraphType& g, NodeType src, NodeType dst, bool *hasEdge) {
  typename GraphType::edge_iterator
    ii = g.edge_begin(src, Galois::MethodFlag::NONE),
    ei = g.edge_end(src, Galois::MethodFlag::NONE);
  *hasEdge = false;
  for (; ii != ei; ++ii) {
    if (g.getEdgeDst(ii) == dst) {
      *hasEdge = true;
      break;
    }
  }
  return ii;
}
  /** Sphere Constraint Setter
  * @param[in] g Valid graph.
  * @param[in] t Valid time.
  * @post Any node that moves into the sphere has:
  *       its position set to the nearest point on the sphere.
  *       The component of the node's velocity normal to the sphere's surface
  *       is set to v - (v*R)*R,
  *       where R = (x - center) / |x - center|
  */
  void operator()(GraphType& g, double t) {
    (void) t;     // silence compiler warnings
    for (auto it = g.node_begin(); it != g.node_end(); ++it) {
      Node n = (*it);
      double dist = norm(n.position() - center_);

      // Reset nodes' position to be on the sphere's surface
      if (dist < r_) {
        n.position() = (n.position() - center_) * (r_ / dist) + center_;
        Point R = (n.position() - center_)/dist;
        n.value().vel -= dot(n.value().vel, R) * R;
      }
    }
  }
Example #21
0
void example4() {
  unsigned int node_rows;

  GraphType::FGSeedsType fg_nodes;

  static const int use_seed[] = {-1};
  GraphType* g = generate_example4_graph(fg_nodes, node_rows, use_seed);

  run_print_maxflow(g, fg_nodes, node_rows);

  g->generate_graph_visualization(node_rows);
  g->generate_pdf_graphs();

  delete g;
}
Example #22
0
    bool load_binary(GraphType& g, const std::string& prefix) {
      g.dc().full_barrier();
      std::string fname = prefix + tostr(g.procid()) + ".bin";

      logstream(LOG_INFO) << "Load graph from " << fname << std::endl;
      general_ifstream fin(fname, true);
      if(!fin.good()) {
        logstream(LOG_ERROR) << "\n\tError opening file: " << fname << std::endl;
        return false;
      }
      iarchive iarc(fin);
      iarc >> g;
      logstream(LOG_INFO) << "Finish loading graph from " << fname << std::endl;
      g.dc().full_barrier();
      return true;
    } // end of load
Example #23
0
static typename GraphType::VertexDescriptor
yagi_random_vertex(const GraphType &g)
{
    size_t n = g.num_vertices();
    assert(n>0);
    return rand() % n;
}
Example #24
0
static typename GraphType::EdgeDescriptor
yagi_random_edge(const GraphType &g)
{
    size_t n = g.num_edges();
    assert(n>0);
    return rand() % n;
}
Example #25
0
Totals
sgl_time_vertex_traversal()
{
    GraphType g;
    sgl_random_graph(g, MAX_VERTICES, 2, 4.0);
    size_t niter=0;
    start_deadman(2);
    Sawyer::Stopwatch t;
    while (!had_alarm && niter<MAX_COUNT) {
        boost::iterator_range<typename GraphType::VertexNodeIterator> vi_pair = g.vertices();
        for (typename GraphType::VertexNodeIterator iter=vi_pair.begin(); iter!=vi_pair.end() && !had_alarm; ++iter)
            ++niter;
    }
    t.stop();
    return report("vert iter", sgl_size(g), niter, t, "verts/s");
}
Example #26
0
Totals
sage_time_vertex_traversal()
{
    GraphType *g = new GraphType;
    sage_random_graph(g, MAX_VERTICES, 2, 4.0);
    size_t niter=0;
    start_deadman(2);
    Sawyer::Stopwatch t;
    while (!had_alarm && niter<MAX_COUNT) {
        std::set<SgGraphNode*> vertex_set = g->computeNodeSet();
        for (std::set<SgGraphNode*>::iterator vi=vertex_set.begin(); vi!=vertex_set.end() && !had_alarm; ++vi)
            ++niter;
    }
    t.stop();
    return report("vert iter", sage_size(g), niter, t, "verts/s");
}
Example #27
0
static Totals
sgl_time_remove_edge()
{
    GraphType g;
    sgl_random_graph(g, MAX_VERTICES, 2, 4.0);
    GraphSize gsize = sgl_size(g);

    start_deadman(2);
    Sawyer::Stopwatch t;
    size_t ne_orig = g.nEdges();
    for (size_t i=0; i<ne_orig && !had_alarm; ++i)
        g.eraseEdge(sgl_random_edge(g));
    t.stop();
    size_t nremoved = ne_orig - g.nEdges();
    return report("edge erase", gsize, nremoved, t, "edges/s");
}
Example #28
0
Totals
sgl_time_edge_traversal()
{
    GraphType g;
    sgl_random_graph(g, MAX_VERTICES, 2, 4.0);
    size_t niter=0;
    start_deadman(2);
    Sawyer::Stopwatch t;
    while (!had_alarm && niter<MAX_COUNT) {
        boost::iterator_range<typename GraphType::EdgeNodeIterator> edges = g.edges();
        for (typename GraphType::EdgeNodeIterator edge=edges.begin(); edge!=edges.end() && !had_alarm; ++edge)
            ++niter;
    }
    t.stop();
    return report("edge iter", sgl_size(g), niter, t, "edges/s");
}
Example #29
0
Totals
yagi_time_edge_traversal()
{
    GraphType g;
    yagi_random_graph(g, MAX_VERTICES, 2, 4.0);
    size_t niter=0;
    start_deadman(2);
    Sawyer::Stopwatch t;
    while (!had_alarm && niter<MAX_COUNT) {
        typename GraphType::EdgeIterator ei, ei_end;
        for (boost::tie(ei, ei_end) = g.edges(); ei!=ei_end && !had_alarm; ++ei)
            ++niter;
    }
    t.stop();
    return report("edge iter", yagi_size(g), niter, t, "edges/s");
}
int main(int argc, char** argv)
{
  // Check arguments
  if (argc < 3) {
    std::cerr << "Usage: " << argv[0] << " NODES_FILE TETS_FILE\n";
    exit(1);
  }

  // Construct a Graph
  typedef Graph<int, int> GraphType;
  GraphType graph;
  std::vector<GraphType::node_type> nodes;

  // Create a nodes_file from the first input argument
  std::ifstream nodes_file(argv[1]);
  // Interpret each line of the nodes_file as a 3D Point and add to the Graph
  Point p;
  while (CME212::getline_parsed(nodes_file, p))
    nodes.push_back(graph.add_node(p));

  // Create a tets_file from the second input argument
  std::ifstream tets_file(argv[2]);
  // Interpret each line of the tets_file as four ints which refer to nodes
  std::array<int,4> t;
  while (CME212::getline_parsed(tets_file, t))
    for (unsigned i = 1; i < t.size(); ++i)
      for (unsigned j = 0; j < i; ++j)
        graph.add_edge(nodes[t[i]], nodes[t[j]]);

  // Print out the stats
  std::cout << graph.num_nodes() << " " << graph.num_edges() << std::endl;

  // Launch the SDLViewer
  CME212::SDLViewer viewer;
  viewer.launch();
  auto node_map = viewer.empty_node_map(graph);

  Point pref = Point(-1, 0, 1);
  int path = shortest_path_lengths(graph, pref);
  PathColorFn pcf = PathColorFn(path);
  viewer.add_nodes(graph.node_begin(), graph.node_end(), pcf, node_map);

  // Test the PositionColorFn, the color is presented according to the nodes' x coordinats.
  //PositionColorFn pocf = PositionColorFn();
  //viewer.add_nodes(graph.node_begin(), graph.node_end(), pocf, node_map);

  viewer.add_edges(graph.edge_begin(), graph.edge_end(), node_map);
  viewer.center_view();

  return 0;
}