blob: 6cbb574d0743ea5ee1389c80b65030ae67cbc27e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <iostream>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/connected_components.hpp>
#include <boost/graph/graph_traits.hpp>
#include "arrow/api.h"
#include "./config.h"
#include "graphar/api/arrow_writer.h"
#include "graphar/api/high_level_reader.h"
#include "graphar/api/high_level_writer.h"
int main(int argc, char* argv[]) {
// read file and construct graph info
std::string path =
GetTestingResourceRoot() + "/ldbc_sample/parquet/ldbc_sample.graph.yml";
auto graph_info = graphar::GraphInfo::Load(path).value();
ASSERT(graph_info->GetVertexInfos().size() == 1);
ASSERT(graph_info->GetEdgeInfos().size() == 1);
// construct vertices collection
std::string type = "person";
ASSERT(graph_info->GetVertexInfo(type) != nullptr);
auto maybe_vertices = graphar::VerticesCollection::Make(graph_info, type);
ASSERT(maybe_vertices.status().ok());
auto& vertices = maybe_vertices.value();
int num_vertices = vertices->size();
std::cout << "num_vertices: " << num_vertices << std::endl;
// construct edges collection
std::string src_type = "person", edge_type = "knows", dst_type = "person";
auto maybe_edges =
graphar::EdgesCollection::Make(graph_info, src_type, edge_type, dst_type,
graphar::AdjListType::ordered_by_source);
ASSERT(!maybe_edges.has_error());
auto& edges = maybe_edges.value();
// define the Graph type
typedef boost::adjacency_list<
boost::vecS, // use vector to store edges
boost::vecS, // use vector to store vertices
boost::undirectedS, // options: directionalS/bidirectionalS/undirectedS
boost::property<boost::vertex_name_t, int64_t>, // vertex property
boost::no_property>
Graph; // no edge property
// descriptors for vertex and edge
typedef typename boost::graph_traits<Graph>::vertex_descriptor Vertex;
// declare a graph object with (num_vertices) vertices and a edge iterator
std::vector<std::pair<graphar::IdType, graphar::IdType>> edges_array;
auto it_end = edges->end();
for (auto it = edges->begin(); it != it_end; ++it) {
edges_array.push_back(std::make_pair(it.source(), it.destination()));
}
Graph g(edges_array.begin(), edges_array.end(), num_vertices);
// access the vertex set
typedef boost::property_map<Graph, boost::vertex_index_t>::type IndexMap;
IndexMap index = boost::get(boost::vertex_index, g);
typedef boost::graph_traits<Graph>::vertex_iterator vertex_iter;
std::pair<vertex_iter, vertex_iter> vp;
// add vertex properties (internal)
boost::property_map<Graph, boost::vertex_name_t>::type id =
get(boost::vertex_name_t(), g);
auto v_it_end = vertices->end();
for (auto it = vertices->begin(); it != v_it_end; ++it) {
// FIXME(@acezen): double free error when get string property
boost::put(id, it.id(), it.property<int64_t>("id").value());
}
// define vertex property (external)
std::vector<int> component(num_vertices);
// call algorithm: connected components
int cc_num = boost::connected_components(g, &component[0]);
std::cout << "Total number of components: " << cc_num << std::endl;
for (vp = boost::vertices(g); vp.first != vp.second; ++vp.first) {
Vertex v = *vp.first;
std::cout << index[v] << " original id: " << boost::get(id, v)
<< ", component id: " << component[index[v]] << std::endl;
}
// method 1 for writing results: construct new vertex type and write results
// using vertex builder construct new property group
graphar::Property cc("cc", graphar::int32(), false);
std::vector<graphar::Property> property_vector = {cc};
auto group =
graphar::CreatePropertyGroup(property_vector, graphar::FileType::PARQUET);
// construct new vertex info
std::string vertex_type = "cc_result", vertex_prefix = "result/";
int chunk_size = 100;
auto version = graphar::InfoVersion::Parse("gar/v1").value();
auto new_info = graphar::CreateVertexInfo(vertex_type, chunk_size, {group},
{}, vertex_prefix, version);
// dump new vertex info
ASSERT(new_info->IsValidated());
ASSERT(new_info->Dump().status().ok());
ASSERT(new_info->Save("/tmp/cc_result.vertex.yml").ok());
// construct vertices builder
graphar::builder::VerticesBuilder builder(new_info, "/tmp/");
// add vertices to the builder
for (vp = boost::vertices(g); vp.first != vp.second; ++vp.first) {
Vertex v = *vp.first;
graphar::builder::Vertex vertex(index[v]);
vertex.AddProperty(cc.name, component[index[v]]);
builder.AddVertex(vertex);
}
ASSERT(builder.GetNum() == num_vertices);
// dump the results through builder
ASSERT(builder.Dump().ok());
// method 2 for writing results: extend the original vertex info and write
// results using writer extend the vertex_info
auto vertex_info = graph_info->GetVertexInfo(vertex_type);
auto maybe_extend_info = vertex_info->AddPropertyGroup(group);
ASSERT(maybe_extend_info.status().ok());
auto extend_info = maybe_extend_info.value();
// dump the extened vertex info
ASSERT(extend_info->IsValidated());
ASSERT(extend_info->Dump().status().ok());
ASSERT(extend_info->Save("/tmp/person-new.vertex.yml").ok());
// construct vertex property writer
graphar::VertexPropertyWriter writer(extend_info, "/tmp/");
// convert results to arrow::Table
std::vector<std::shared_ptr<arrow::Array>> arrays;
std::vector<std::shared_ptr<arrow::Field>> schema_vector;
schema_vector.push_back(arrow::field(
cc.name, graphar::DataType::DataTypeToArrowDataType(cc.type)));
arrow::MemoryPool* pool = arrow::default_memory_pool();
typename arrow::TypeTraits<arrow::Int32Type>::BuilderType array_builder(pool);
ASSERT(array_builder.Reserve(num_vertices).ok());
ASSERT(array_builder.AppendValues(component).ok());
std::shared_ptr<arrow::Array> array = array_builder.Finish().ValueOrDie();
arrays.push_back(array);
auto schema = std::make_shared<arrow::Schema>(schema_vector);
std::shared_ptr<arrow::Table> table = arrow::Table::Make(schema, arrays);
// dump the results through writer
ASSERT(writer.WriteTable(table, group, 0).ok());
}