diff --git a/flex/engines/graph_db/app/builtin/TVSP.cc b/flex/engines/graph_db/app/builtin/TVSP.cc new file mode 100644 index 000000000000..17efb1af639f --- /dev/null +++ b/flex/engines/graph_db/app/builtin/TVSP.cc @@ -0,0 +1,228 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + * + * Licensed 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 "flex/engines/graph_db/app/builtin/TVSP.h" + +namespace gs { + +bool TVSP::DoQuery(GraphDBSession& sess, Decoder& input,Encoder& output) { + ReadTransaction txn = sess.GetReadTransaction(); + if (input.empty()) { + return false; + } + Schema schema_ = txn.schema(); + std::string label_name1{input.get_string()}; + vid_t vid1=input.get_int(); + std::string label_name2{input.get_string()}; + vid_t vid2=input.get_int(); + std::string label_name3{input.get_string()}; + vid_t vid3=input.get_int(); + + if(!schema_.has_vertex_label(label_name1)||!schema_.has_vertex_label(label_name2) + ||!schema_.has_vertex_label(label_name3)){ + output.put_string_view("The requested label doesn't exits."); + return false; // The requested label doesn't exits. + } + label_t label_v1=schema_.get_vertex_label_id(label_name1); + label_t label_v2=schema_.get_vertex_label_id(label_name2); + label_t label_v3=schema_.get_vertex_label_id(label_name3); + vid_t index_v1{}; + vid_t index_v2{}; + vid_t index_v3{}; + if(!txn.GetVertexIndex(label_v1, (int64_t)vid1, index_v1)|| + !txn.GetVertexIndex(label_v2, (int64_t)vid2, index_v2)|| + !txn.GetVertexIndex(label_v3, (int64_t)vid3, index_v3)) + { + output.put_string_view("get index fail."); + return false; + } + + uint vertex_num = 0 ; + for(label_t i = 0 ; i v1v2result_; + std::vector v2v3result_; + std::vector v1v3result_; + + bool find_flag = true; + if(!ShortestPath(txn,label_v1,index_v1,label_v2,index_v2,v1v2result_,vertex_num)){ + find_flag=false; + } + if(find_flag&&!ShortestPath(txn,label_v2,index_v2,label_v3,index_v3,v2v3result_,vertex_num)){ + find_flag=false; + } + if(find_flag&&!ShortestPath(txn,label_v1,index_v1,label_v3,index_v3,v1v3result_,vertex_num)){ + find_flag=false; + } + std::string result_path = ""; + if(find_flag){ + //选择最短的两条路径进行连接 + std::vector TSP = ConnectPath(v1v2result_,v2v3result_,v1v3result_); + for(auto it = TSP.begin(); it != TSP.end(); ++it){ + if (std::next(it) != TSP.end()) { + result_path += std::to_string(*it)+"--"; // 如果当前元素不是最后一个,则添加空格 + } + else{ + result_path += std::to_string(*it); + } + } + } + else{ + result_path="no path find!"; + } + + // 向CollectiveResults中添加多个Results对象 + results::CollectiveResults results; + auto result = results.add_results(); + result->mutable_record() + ->add_columns() + ->mutable_entry() + ->mutable_element() + ->mutable_object() + ->set_str(result_path); + + output.put_string_view(results.SerializeAsString()); + txn.Commit(); + return true; +} + +bool TVSP::ShortestPath(const gs::ReadTransaction& txn, label_t v1_l,vid_t v1_index,label_t v2_l,vid_t v2_index,std::vector &result_, uint vertex_num){ + Schema schema_ = txn.schema(); + int vertex_size_ = (int)schema_.vertex_label_num(); + int edge_size_ = (int)schema_.edge_label_num(); + + std::vector visited(vertex_num+1, false); + std::unordered_map parent; + std::vector nei_label_; + std::vector nei_index_; + int64_t v1_id = txn.GetVertexId(v1_l, v1_index).AsInt64(); + int64_t v2_id = txn.GetVertexId(v2_l, v2_index).AsInt64(); + + // std::cout<<"v1: "< next_nei_labels_; + std::vector next_nei_indexs_; + bool find = false; + while(!nei_label_.empty()&&!find) { + for(long unsigned int i = 0 ; i< nei_index_.size();i++){ + for(int j = 0 ; j TVSP::ConnectPath(std::vector &path1,std::vector &path2, + std::vector &path3){ + std::vector TSP; + int v1v2size = (int)path1.size(); + int v2v3size = (int)path2.size(); + int v1v3size = (int)path3.size(); + if(v1v2size<=v2v3size&&v1v3size<=v2v3size){ + for(int i =v1v2size-1;i>=0;i--){ + TSP.push_back(path1[i]); + } + for(int i = 1;i=0;i--){ + TSP.push_back(path3[i]); + } + } + return TSP; +} +AppWrapper TVSPFactory::CreateApp(const GraphDB& db) { + return AppWrapper(new TVSP(), NULL); +} +} // namespace gs diff --git a/flex/engines/graph_db/app/builtin/TVSP.h b/flex/engines/graph_db/app/builtin/TVSP.h new file mode 100644 index 000000000000..0c43c2c378d9 --- /dev/null +++ b/flex/engines/graph_db/app/builtin/TVSP.h @@ -0,0 +1,50 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + * + * Licensed 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. + */ + +#ifndef ENGINES_GRAPH_DB_APP_BUILDIN_TVSP_H_ +#define ENGINES_GRAPH_DB_APP_BUILDIN_TVSP_H_ +#include "flex/engines/graph_db/database/graph_db_session.h" +#include "flex/engines/hqps_db/app/interactive_app_base.h" + +namespace gs { +// A simple app to count the number of vertices of a given label. +class TVSP : public CypherInternalPbWriteAppBase { + private: +// std::string label_name1; +// int32_t vid1; +// std::string label_name2; +// int32_t vid2; +// std::string label_name3; +// int32_t vid3; + + public: + TVSP() {} + bool DoQuery(GraphDBSession& sess, Decoder& input, Encoder& output) override; + bool ShortestPath(const gs::ReadTransaction& txn, label_t v1_l,vid_t v1_index,label_t v2_l,vid_t v2_index,std::vector &result_, uint vertex_num); + std::vector ConnectPath(std::vector &path1,std::vector &path2,std::vector &path3); + +}; + +class TVSPFactory : public AppFactoryBase { + public: + TVSPFactory() = default; + ~TVSPFactory() = default; + + AppWrapper CreateApp(const GraphDB& db) override; +}; + +} // namespace gs + +#endif // ENGINES_GRAPH_DB_APP_BUILDIN_TVSP_H_ \ No newline at end of file diff --git a/flex/engines/graph_db/app/builtin/k_degree_neighbors.cc b/flex/engines/graph_db/app/builtin/k_degree_neighbors.cc new file mode 100644 index 000000000000..f5fa5deaeeb5 --- /dev/null +++ b/flex/engines/graph_db/app/builtin/k_degree_neighbors.cc @@ -0,0 +1,116 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + * + * Licensed 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 "flex/engines/graph_db/app/builtin/k_degree_neighbors.h" + +namespace gs { + +bool KNeighbors::DoQuery(GraphDBSession& sess, Decoder& input, + Encoder& output) { + // 创建一个CollectiveResults对象 + auto txn = sess.GetReadTransaction(); + Schema schema_ = txn.schema(); + if (input.empty()) { + return false; + } + this->vertex_id_=input.get_int(); + std::string label_name { input.get_string()}; + this->k=input.get_int(); + + if(k<=0) { + output.put_string_view("k must be greater than 0."); + return false; + } + if(!schema_.has_vertex_label(label_name)){ + output.put_string_view("The requested label doesn't exits."); + return false; // The requested label doesn't exits. + } + this->vertex_label_=schema_.get_vertex_label_id(label_name); + + + std::set k_neighbors; + + int vertex_size_ = (int)schema_.vertex_label_num(); + int edge_size_ = (int)schema_.edge_label_num(); + + std::vector nei_index_; + std::vector nei_label_; + std::vector next_nei_indexs_; + std::vector next_nei_label_; + + nei_label_.push_back(vertex_label_); + vid_t vertex_index{}; + if(!txn.GetVertexIndex(vertex_label_, (int64_t)vertex_id_, vertex_index)){ + output.put_string_view("get index fail."); + return false; + } + nei_index_.push_back(vertex_index); + //层次遍历得到k跳邻居 + while(!nei_index_.empty() && k > 0) { + for(long unsigned int i = 0 ; imutable_record() + ->add_columns() + ->mutable_entry() + ->mutable_element() + ->mutable_object() + ->set_str(res); + output.put_string_view(results.SerializeAsString()); + txn.Commit(); + return true; +} + +AppWrapper KNeighborsFactory::CreateApp(const GraphDB& db) { + return AppWrapper(new KNeighbors(), NULL); +} +} // namespace gs diff --git a/flex/engines/graph_db/app/builtin/k_degree_neighbors.h b/flex/engines/graph_db/app/builtin/k_degree_neighbors.h new file mode 100644 index 000000000000..543c4212ddb8 --- /dev/null +++ b/flex/engines/graph_db/app/builtin/k_degree_neighbors.h @@ -0,0 +1,43 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + * + * Licensed 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. + */ + +#ifndef ENGINES_GRAPH_DB_APP_BUILDIN_K_DEGREE_NEI_ +#define ENGINES_GRAPH_DB_APP_BUILDIN_K_DEGREE_NEI_ +#include "flex/engines/graph_db/database/graph_db_session.h" +#include "flex/engines/hqps_db/app/interactive_app_base.h" + +namespace gs { +// A simple app to count the number of vertices of a given label. +class KNeighbors : public CypherInternalPbWriteAppBase { + private: + vid_t vertex_id_; + label_t vertex_label_; + int32_t k; + public: + KNeighbors() {} + bool DoQuery(GraphDBSession& sess, Decoder& input, Encoder& output) override; +}; + +class KNeighborsFactory : public AppFactoryBase { + public: + KNeighborsFactory() = default; + ~KNeighborsFactory() = default; + + AppWrapper CreateApp(const GraphDB& db) override; +}; + +} // namespace gs + +#endif // ENGINES_GRAPH_DB_APP_BUILDIN_COUNT_VERTICES_H_ \ No newline at end of file diff --git a/flex/engines/graph_db/app/builtin/pagerank.cc b/flex/engines/graph_db/app/builtin/pagerank.cc new file mode 100644 index 000000000000..d32e6cdbff9a --- /dev/null +++ b/flex/engines/graph_db/app/builtin/pagerank.cc @@ -0,0 +1,134 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + * + * Licensed 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 "flex/engines/graph_db/app/builtin/pagerank.h" + +namespace gs { + + +bool PageRank::DoQuery(GraphDBSession& sess, Decoder& input, + Encoder& output) { + // First get the read transaction. + auto txn = sess.GetReadTransaction(); + // We expect one param of type string from decoder. + if (input.empty()) { + return false; + } + std::string vertex_label{input.get_string()}; + std::string edge_label{input.get_string()}; + + if(!input.empty()) { + damping_factor_ = input.get_double(); + max_iterations_ = input.get_int(); + epsilon_ = input.get_double(); + } + + vertex_label_id_ = sess.schema().get_vertex_label_id(vertex_label); + edge_label_id_ = sess.schema().get_edge_label_id(edge_label); + + // 统计顶点数量 + auto num_vertices = txn.GetVertexNum(vertex_label_id_); + + // 初始化每个顶点的PageRank值为 1.0 / num_vertices + std::unordered_map pagerank; + std::unordered_map new_pagerank; + + auto vertex_iter = txn.GetVertexIterator(vertex_label_id_); + + while (vertex_iter.IsValid()) { + vid_t vid = vertex_iter.GetIndex(); + pagerank[vid] = 1.0 / num_vertices; + new_pagerank[vid] = 0.0; + vertex_iter.Next(); + } + + // 获取点的出度 + std::unordered_map outdegree; + + // 开始迭代计算PageRank值 + for (int iter = 0; iter < max_iterations_; ++iter) { + // 初始化新的PageRank值 + for (auto& kv : new_pagerank) { + kv.second = 0.0; + } + + // 遍历所有顶点 + auto vertex_iter = txn.GetVertexIterator(vertex_label_id_); + while (vertex_iter.IsValid()) { + vid_t v = vertex_iter.GetIndex(); + + // 遍历所有出边并累加其PageRank贡献值 + double sum = 0.0; + auto edges = txn.GetInEdgeIterator(vertex_label_id_, v, vertex_label_id_, edge_label_id_); + while(edges.IsValid()){ + auto neighbor = edges.GetNeighbor(); + if(outdegree[neighbor] == 0){ + auto out_edges = txn.GetOutEdgeIterator(vertex_label_id_, neighbor, vertex_label_id_, edge_label_id_); + while(out_edges.IsValid()){ + outdegree[neighbor]++; + out_edges.Next(); + } + } + sum += pagerank[neighbor] / outdegree[neighbor]; + edges.Next(); + } + + // 计算新的PageRank值 + new_pagerank[v] = damping_factor_ * sum + (1.0 - damping_factor_) / num_vertices; + vertex_iter.Next(); + } + + // 检查收敛 + double diff = 0.0; + for (const auto& kv : pagerank) { + diff += std::abs(new_pagerank[kv.first] - kv.second); + } + + // 如果收敛,则停止迭代 + if (diff < epsilon_) { + break; + } + + // 交换pagerank与new_pagerank的内容 + std::swap(pagerank, new_pagerank); + } + + std::ostringstream output_stream; + for(auto kv : pagerank) { + auto id =txn.GetVertexId(vertex_label_id_, kv.first).AsInt64(); + // output.put_int(static_cast(id)); + // output.put_double(kv.second); + output_stream << "vertex: " << id << ", pagerank: " << kv.second << "\n"; + } + std::string res_string = output_stream.str(); + results::CollectiveResults results; + auto result = results.add_results(); + + result->mutable_record() + ->add_columns() + ->mutable_entry() + ->mutable_element() + ->mutable_object() + ->set_str(res_string); + + output.put_string_view(results.SerializeAsString()); + + txn.Commit(); + return true; +} + +AppWrapper PageRankFactory::CreateApp(const GraphDB& db) { + return AppWrapper(new PageRank(), NULL); +} +} // namespace gs diff --git a/flex/engines/graph_db/app/builtin/pagerank.h b/flex/engines/graph_db/app/builtin/pagerank.h new file mode 100644 index 000000000000..46d31bce78e6 --- /dev/null +++ b/flex/engines/graph_db/app/builtin/pagerank.h @@ -0,0 +1,52 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + * + * Licensed 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. + */ + +#ifndef ENGINES_GRAPH_DB_APP_BUILDIN_PAGERANK_H_ +#define ENGINES_GRAPH_DB_APP_BUILDIN_PAGERANK_H_ +#include "flex/engines/graph_db/database/graph_db_session.h" +#include "flex/engines/hqps_db/app/interactive_app_base.h" + +namespace gs { +// A simple app to count the number of vertices of a given label. +class PageRank : public CypherInternalPbWriteAppBase { + public: + PageRank() + : damping_factor_(0.85), + max_iterations_(100), + epsilon_(1e-6), + vertex_label_id_(0), + edge_label_id_(0) {} + bool DoQuery(GraphDBSession& sess, Decoder& input, Encoder& output) override; + + private: + double damping_factor_; + int max_iterations_; + double epsilon_; + + label_t vertex_label_id_; + label_t edge_label_id_; +}; + +class PageRankFactory : public AppFactoryBase { + public: + PageRankFactory() = default; + ~PageRankFactory() = default; + + AppWrapper CreateApp(const GraphDB& db) override; +}; + +} // namespace gs + +#endif // ENGINES_GRAPH_DB_APP_BUILDIN_PAGERANK_H_ \ No newline at end of file diff --git a/flex/engines/graph_db/database/graph_db.cc b/flex/engines/graph_db/database/graph_db.cc index 0aa50c6b0624..286674abba2a 100644 --- a/flex/engines/graph_db/database/graph_db.cc +++ b/flex/engines/graph_db/database/graph_db.cc @@ -16,6 +16,9 @@ #include "flex/engines/graph_db/database/graph_db.h" #include "flex/engines/graph_db/app/adhoc_app.h" #include "flex/engines/graph_db/app/builtin/count_vertices.h" +#include "flex/engines/graph_db/app/builtin/pagerank.h" +#include "flex/engines/graph_db/app/builtin/k_degree_neighbors.h" +#include "flex/engines/graph_db/app/builtin/TVSP.h" #include "flex/engines/graph_db/app/hqps_app.h" #include "flex/engines/graph_db/app/server_app.h" #include "flex/engines/graph_db/database/graph_db_session.h" @@ -408,6 +411,13 @@ void GraphDB::initApps( app_factories_[0] = std::make_shared(); app_factories_[Schema::BUILTIN_COUNT_VERTICES_PLUGIN_ID] = std::make_shared(); + app_factories_[Schema::BUILTIN_PAGERANK_PLUGIN_ID] = + std::make_shared(); + app_factories_[Schema::BUILTIN_K_DEGREE_NEIGHBORS_PLUGIN_ID] = + std::make_shared(); + app_factories_[Schema::BUILTIN_TVSP_PLUGIN_ID] = + std::make_shared(); + app_factories_[Schema::HQPS_ADHOC_READ_PLUGIN_ID] = std::make_shared(); app_factories_[Schema::HQPS_ADHOC_WRITE_PLUGIN_ID] = diff --git a/flex/storages/metadata/graph_meta_store.cc b/flex/storages/metadata/graph_meta_store.cc index 8a9041c272b2..ef7eff176fb3 100644 --- a/flex/storages/metadata/graph_meta_store.cc +++ b/flex/storages/metadata/graph_meta_store.cc @@ -56,6 +56,8 @@ const std::vector& get_builtin_plugin_metas() { static std::vector builtin_plugins; static bool initialized = false; if (!initialized) { + + // count_vertices PluginMeta count_vertices; count_vertices.id = "count_vertices"; count_vertices.name = "count_vertices"; @@ -69,6 +71,64 @@ const std::vector& get_builtin_plugin_metas() { count_vertices.returns.push_back({"count", PropertyType::kInt32}); initialized = true; builtin_plugins.push_back(count_vertices); + + // pagerank + PluginMeta pagerank; + pagerank.id = "pagerank"; + pagerank.name = "pagerank"; + pagerank.description = "A builtin plugin to calculate pagerank"; + pagerank.enable = true; + pagerank.runnable = true; + pagerank.type = "cypher"; + pagerank.creation_time = GetCurrentTimeStamp(); + pagerank.update_time = GetCurrentTimeStamp(); + pagerank.params.push_back({"vertex_label", PropertyType::kString}); + pagerank.params.push_back({"edge_label", PropertyType::kString}); + pagerank.params.push_back({"damping_factor_", PropertyType::kDouble}); + pagerank.params.push_back({"max_iterations_", PropertyType::kInt32}); + pagerank.params.push_back({"epsilon_", PropertyType::kDouble}); + pagerank.returns.push_back({"pagerank", PropertyType::kString}); + initialized = true; + builtin_plugins.push_back(pagerank); + + // k_neighbors + PluginMeta k_neighbors; + k_neighbors.id = "k_neighbors"; + k_neighbors.name = "k_neighbors"; + k_neighbors.description = "A builtin plugin to calculate k_neighbors"; + k_neighbors.enable = true; + k_neighbors.runnable = true; + k_neighbors.type = "cypher"; + k_neighbors.creation_time = GetCurrentTimeStamp(); + k_neighbors.update_time = GetCurrentTimeStamp(); + k_neighbors.params.push_back({"vid", PropertyType::kInt32}); + k_neighbors.params.push_back({"label_name", PropertyType::kString}); + k_neighbors.params.push_back({"k", PropertyType::kInt32}); + k_neighbors.returns.push_back({"k_neighbors", PropertyType::kString}); + initialized = true; + builtin_plugins.push_back(k_neighbors); + + // TVSP + PluginMeta TVSP; + TVSP.id = "TVSP"; + TVSP.name = "TVSP"; + TVSP.description = "A builtin plugin to calculate TVSP"; + TVSP.enable = true; + TVSP.runnable = true; + TVSP.type = "cypher"; + TVSP.creation_time = GetCurrentTimeStamp(); + TVSP.update_time = GetCurrentTimeStamp(); + TVSP.params.push_back({"label_name1", PropertyType::kString}); + TVSP.params.push_back({"vid1", PropertyType::kInt32}); + TVSP.params.push_back({"label_name2", PropertyType::kString}); + TVSP.params.push_back({"vid2", PropertyType::kInt32}); + TVSP.params.push_back({"label_name3", PropertyType::kString}); + TVSP.params.push_back({"vid3", PropertyType::kInt32}); + TVSP.returns.push_back({"TVSP", PropertyType::kString}); + initialized = true; + builtin_plugins.push_back(TVSP); + + initialized = true; } return builtin_plugins; }