From 266d8ed055cdce826775153d1e3d3c1423efbd77 Mon Sep 17 00:00:00 2001 From: Kruno Tomola Fabro Date: Tue, 13 Sep 2016 14:17:50 +0100 Subject: [PATCH] Transformed dressipi astar into a query. --- include/database/db.hpp | 3 +- poc/CMakeLists.txt | 1 + poc/astar_query.cpp | 262 +++------------------------------------- poc/queries/astar.cpp | 143 ++++++++++++++++++++++ src/barrier/barrier.cpp | 4 + src/database/db.cpp | 7 +- 6 files changed, 170 insertions(+), 250 deletions(-) create mode 100644 poc/queries/astar.cpp diff --git a/include/database/db.hpp b/include/database/db.hpp index 1c98fd5bb..2ddd20a3d 100644 --- a/include/database/db.hpp +++ b/include/database/db.hpp @@ -20,7 +20,8 @@ class Db public: using sptr = std::shared_ptr; - Db(bool import_snapshot = true); + explicit Db(bool import_snapshot = true); + Db(const char *name, bool import_snapshot = true); Db(const std::string &name, bool import_snapshot = true); Db(const Db &db) = delete; diff --git a/poc/CMakeLists.txt b/poc/CMakeLists.txt index 7ccc564fd..10ea30e24 100644 --- a/poc/CMakeLists.txt +++ b/poc/CMakeLists.txt @@ -4,6 +4,7 @@ project(memgraph_poc) include_directories(${CMAKE_SOURCE_DIR}/poc) +include_directories(${CMAKE_SOURCE_DIR}/queries) add_executable(poc_astar astar.cpp) diff --git a/poc/astar_query.cpp b/poc/astar_query.cpp index b854929fa..7bbea816c 100644 --- a/poc/astar_query.cpp +++ b/poc/astar_query.cpp @@ -1,3 +1,7 @@ +#include "queries/astar.cpp" + +#include "barrier/barrier.cpp" + #include #include #include @@ -28,276 +32,38 @@ #include "storage/vertices.hpp" #include "utils/command_line/arguments.hpp" -const int max_score = 1000000; - -using namespace std; -typedef VertexAccessor VertexAccessor; - -void add_scores(Db &db); - -class Node -{ -public: - Node *parent = {nullptr}; - type_key_t tkey; - double cost; - int depth = {0}; - VertexAccessor vacc; - - Node(VertexAccessor vacc, double cost, - type_key_t tkey) - : cost(cost), vacc(vacc), tkey(tkey) - { - } - Node(VertexAccessor vacc, double cost, Node *parent, - type_key_t tkey) - : cost(cost), vacc(vacc), parent(parent), depth(parent->depth + 1), - tkey(tkey) - { - } - - double sum_vertex_score() - { - auto now = this; - double sum = 0; - do { - sum += (now->vacc.at(tkey).get())->value(); - now = now->parent; - } while (now != nullptr); - return sum; - } -}; - -class Score -{ -public: - Score() : value(std::numeric_limits::max()) {} - Score(double v) : value(v) {} - double value; -}; - -void found_result(Node *res) -{ - double sum = res->sum_vertex_score(); - - std::cout << "{score: " << sum << endl; - auto bef = res; - while (bef != nullptr) { - std::cout << " " << *(bef->vacc.operator->()) << endl; - bef = bef->parent; - } -} - -double calc_heuristic_cost_dummy(type_key_t tkey, - EdgeAccessor &edge, VertexAccessor &vertex) -{ - assert(!vertex.empty()); - return 1 - vertex.at(tkey).get()->value(); -} - -typedef bool (*EdgeFilter)(DbAccessor &t, EdgeAccessor &, Node *before); -typedef bool (*VertexFilter)(DbAccessor &t, VertexAccessor &, Node *before); - -bool edge_filter_dummy(DbAccessor &t, EdgeAccessor &e, Node *before) -{ - return true; -} - -bool vertex_filter_dummy(DbAccessor &t, VertexAccessor &va, Node *before) -{ - return va.fill(); -} - -bool vertex_filter_contained_dummy(DbAccessor &t, VertexAccessor &v, - Node *before) -{ - if (v.fill()) { - bool found; - do { - found = false; - before = before->parent; - if (before == nullptr) { - return true; - } - auto it = before->vacc.out(); - for (auto e = it.next(); e.is_present(); e = it.next()) { - VertexAccessor va = e.get().to(); - if (va == v) { - found = true; - break; - } - } - } while (found); - } - return false; -} - -bool vertex_filter_contained(DbAccessor &t, VertexAccessor &v, Node *before) -{ - if (v.fill()) { - bool found; - do { - found = false; - before = before->parent; - if (before == nullptr) { - return true; - } - } while (v.in_contains(before->vacc)); - } - return false; -} - -// Vertex filter ima max_depth funkcija te edge filter ima max_depth funkcija. -// Jedan za svaku dubinu. -// Filtri vracaju true ako element zadovoljava uvjete. -auto a_star( - Db &db, int64_t sys_id_start, uint max_depth, EdgeFilter e_filter[], - VertexFilter v_filter[], - double (*calc_heuristic_cost)(type_key_t tkey, - EdgeAccessor &edge, VertexAccessor &vertex), - int limit) -{ - DbAccessor t(db); - type_key_t tkey = - t.vertex_property_family_get("score") - .get(Flags::Double) - .type_key(); - - auto best_found = new std::map[max_depth]; - - std::vector best; - auto cmp = [](Node *left, Node *right) { return left->cost > right->cost; }; - std::priority_queue, decltype(cmp)> queue(cmp); - - auto start_vr = t.vertex_find(sys_id_start); - assert(start_vr); - start_vr.get().fill(); - Node *start = new Node(start_vr.take(), 0, tkey); - queue.push(start); - int count = 0; - do { - auto now = queue.top(); - queue.pop(); - // if(!visited.insert(now)){ - // continue; - // } - - if (max_depth <= now->depth) { - best.push_back(now); - count++; - if (count >= limit) { - return best; - } - continue; - } - - // { // FOUND FILTER - // Score &bef = best_found[now->depth][now->vacc.id()]; - // if (bef.value <= now->cost) { - // continue; - // } - // bef.value = now->cost; - // } - - iter::for_all(now->vacc.out(), [&](auto edge) { - if (e_filter[now->depth](t, edge, now)) { - VertexAccessor va = edge.to(); - if (v_filter[now->depth](t, va, now)) { - auto cost = calc_heuristic_cost(tkey, edge, va); - Node *n = new Node(va, now->cost + cost, now, tkey); - queue.push(n); - } - } - }); - } while (!queue.empty()); - - // TODO: GUBI SE MEMORIJA JER SE NODOVI NEBRISU - - t.commit(); - return best; -} - int main(int argc, char **argv) { logging::init_async(); logging::log->pipe(std::make_unique()); + std::srand(time(0)); auto para = all_arguments(argc, argv); Db db("astar"); - - EdgeFilter e_filters[] = {&edge_filter_dummy, &edge_filter_dummy, - &edge_filter_dummy, &edge_filter_dummy}; - VertexFilter f_filters[] = { - &vertex_filter_contained, &vertex_filter_contained, - &vertex_filter_contained, &vertex_filter_contained}; - - // CONF - std::srand(time(0)); - auto best_n = 10; - auto bench_n = 1000; - auto best_print_n = 10; - bool pick_best_found = - strcmp(get_argument(para, "-p", "true").c_str(), "true") == 0; - + barrier::CodeCPU cp; + int bench_n = 1000; double sum = 0; - std::vector best; for (int i = 0; i < bench_n; i++) { auto start_vertex_index = std::rand() % db.graph.vertices.access().size(); auto begin = clock(); - auto found = a_star(db, start_vertex_index, 3, e_filters, f_filters, - &calc_heuristic_cost_dummy, best_n); + + code_args_t args; + args.push_back(Property(Int64(start_vertex_index), Int64::type)); + + cp.run(barrier::trans(db), args, std::cout); + clock_t end = clock(); double elapsed_ms = (double(end - begin) / CLOCKS_PER_SEC) * 1000; sum += elapsed_ms; - - if ((best.size() < best_print_n && found.size() > best.size()) || - (pick_best_found && found.size() > 0 && - found.front()->sum_vertex_score() > - best.front()->sum_vertex_score())) { - best = found; - } - - // Just to be safe - if (i + 1 == bench_n && best.size() == 0) { - bench_n++; - } } - std::cout << "\nSearch for best " << best_n + std::cout << "\nSearch for best " << barrier::limit << " results has runing time of:\n avg: " << sum / bench_n << " [ms]\n"; - std::cout << "\nExample of best result:\n"; - for (int i = 0; i < best_print_n && best.size() > 0; i++) { - found_result(best.front()); - best.erase(best.begin()); - } return 0; } - -// Adds property score to all vertices. -void add_scores(Db &db) -{ - DbAccessor t(db); - - auto key_score = - t.vertex_property_family_get("score").get(Flags::Double).family_key(); - - int i = 1; - iter::for_all(t.vertex_access(), [&](auto v) { - if (v.fill()) { - // from Kruno's head :) (could be ALMOST anything else) - std::srand(i ^ 0x7482616); - v.set(StoredProperty( - Double((std::rand() % max_score) / (max_score + 0.0)), - key_score)); - i++; - } - }); - - t.commit(); -} diff --git a/poc/queries/astar.cpp b/poc/queries/astar.cpp new file mode 100644 index 000000000..6f1243217 --- /dev/null +++ b/poc/queries/astar.cpp @@ -0,0 +1,143 @@ +#include +#include +#include +#include + +#include "query_engine/i_code_cpu.hpp" +#include "storage/model/properties/all.hpp" + +using std::cout; +using std::endl; + +// Dressipi astar query of 4 clicks. + +// BARRIER! +namespace barrier +{ + +using STREAM = std::ostream; // RecordStream<::io::Socket>; + +constexpr size_t max_depth = 3; +constexpr size_t limit = 10; + +class Node +{ +public: + Node *parent = {nullptr}; + VertexPropertyType tkey; + double cost; + int depth = {0}; + VertexAccessor vacc; + + Node(VertexAccessor vacc, double cost, + VertexPropertyType const &tkey) + : cost(cost), vacc(vacc), tkey(tkey) + { + } + Node(VertexAccessor vacc, double cost, Node *parent, + VertexPropertyType const &tkey) + : cost(cost), vacc(vacc), parent(parent), depth(parent->depth + 1), + tkey(tkey) + { + } + + double sum_vertex_score() + { + auto now = this; + double sum = 0; + do { + sum += (now->vacc.at(tkey).get())->value(); + now = now->parent; + } while (now != nullptr); + return sum; + } +}; + +bool vertex_filter_contained(DbAccessor &t, VertexAccessor &v, Node *before) +{ + if (v.fill()) { + bool found; + do { + found = false; + before = before->parent; + if (before == nullptr) { + return true; + } + } while (v.in_contains(before->vacc)); + } + return false; +} + +void astar(DbAccessor &t, code_args_t &args, STREAM &stream) +{ + VertexPropertyType tkey = t.vertex_property_key("score"); + + auto cmp = [](Node *left, Node *right) { return left->cost > right->cost; }; + std::priority_queue, decltype(cmp)> queue(cmp); + std::vector all_nodes; + + auto start_vr = t.vertex_find(Id(args[0].as().value())); + if (!start_vr.is_present()) { + // stream.write_failure({{}}); + return; + } + + start_vr.get().fill(); + Node *start = new Node(start_vr.take(), 0, tkey); + queue.push(start); + all_nodes.push_back(start); + + int count = 0; + do { + auto now = queue.top(); + queue.pop(); + + if (max_depth <= now->depth) { + // stream.write_success_empty(); + // best.push_back(now); + count++; + if (count >= limit) { + break; + } + continue; + } + + iter::for_all(now->vacc.out(), [&](auto edge) { + VertexAccessor va = edge.to(); + if (vertex_filter_contained(t, va, now)) { + auto cost = 1 - va.at(tkey).get()->value(); + Node *n = new Node(va, now->cost + cost, now, tkey); + queue.push(n); + all_nodes.push_back(n); + } + }); + } while (!queue.empty()); + + for (auto n : all_nodes) { + delete n; + } +} + +class CodeCPU : public ICodeCPU +{ +public: + bool run(Db &db, code_args_t &args, STREAM &stream) override + { + DbAccessor t(db); + + astar(t, args, stream); + + return t.commit(); + } + + ~CodeCPU() {} +}; +} + +extern "C" ICodeCPU *produce() +{ + // BARRIER! + return new barrier::CodeCPU(); +} + +extern "C" void destruct(ICodeCPU *p) { delete p; } diff --git a/src/barrier/barrier.cpp b/src/barrier/barrier.cpp index 0c21fbef2..4a9ab5320 100644 --- a/src/barrier/barrier.cpp +++ b/src/barrier/barrier.cpp @@ -482,6 +482,10 @@ DESTRUCTOR(VertexPropertyKey, PropertyFamilyKey); // ************************* EdgePropertyKey DESTRUCTOR(EdgePropertyKey, PropertyFamilyKey); +// ************************* VertexPropertyType +#define VERTEX_PROPERTY_TYPE(x) template class VertexPropertyType; +INSTANTIATE_FOR_PROPERTY(VERTEX_PROPERTY_TYPE) + // ************************* VertexPropertyFamily OptionPtr> VertexPropertyFamily::index() { diff --git a/src/database/db.cpp b/src/database/db.cpp index 3dd6a3d06..16086a23e 100644 --- a/src/database/db.cpp +++ b/src/database/db.cpp @@ -6,7 +6,12 @@ Db::Db(bool import_snapshot) : Db("default", import_snapshot) {} -Db::Db(const std::string &name, bool import_snapshot) : name_(name) +Db::Db(const std::string &name, bool import_snapshot) + : Db(name.c_str(), import_snapshot) +{ +} + +Db::Db(const char *name, bool import_snapshot) : name_(name) { if (import_snapshot) snap_engine.import(); }