#include #include #include #include #include #include #include #include #include #include #include "communication/bolt/v1/serialization/bolt_serializer.hpp" #include "data_structures/map/rh_hashmap.hpp" #include "database/db.hpp" #include "database/db_accessor.cpp" #include "database/db_accessor.hpp" #include "import/csv_import.hpp" #include "logging/default.hpp" #include "logging/streams/stdout.hpp" #include "storage/edge_x_vertex.hpp" #include "storage/edges.cpp" #include "storage/edges.hpp" #include "storage/indexes/impl/nonunique_unordered_index.cpp" #include "storage/model/properties/properties.cpp" #include "storage/record_accessor.cpp" #include "storage/vertex_accessor.hpp" #include "storage/vertices.cpp" #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()); 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; 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); 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 << " 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(); }