From 530be96b3686b7f86efee0f48394fbee1e37f67a Mon Sep 17 00:00:00 2001 From: Kruno Tomola Fabro Date: Mon, 15 Aug 2016 13:21:38 +0100 Subject: [PATCH] .FIX T68 .FIX T67 .FIX T65 Modifed astar main for benchmark. Experimented with map of best visited and confirmed: -it is faster by 25% -observed that it founds best resoult -loses some non best resoults Added convinent method at() to get property from RecordAccessor. Method requires value_ref() method on property object. --- include/storage/model/properties/bool.hpp | 13 ++- include/storage/model/properties/double.hpp | 3 +- include/storage/model/properties/float.hpp | 9 +- include/storage/model/properties/int32.hpp | 10 +- include/storage/model/properties/int64.hpp | 3 +- include/storage/model/properties/string.hpp | 22 ++-- include/storage/record_accessor.hpp | 6 + poc/astar.cpp | 115 ++++++++++++++++---- src/storage/model/properties/bool.cpp | 26 ++--- 9 files changed, 144 insertions(+), 63 deletions(-) diff --git a/include/storage/model/properties/bool.hpp b/include/storage/model/properties/bool.hpp index c551ee3e6..8bffb2e86 100644 --- a/include/storage/model/properties/bool.hpp +++ b/include/storage/model/properties/bool.hpp @@ -8,20 +8,21 @@ public: static constexpr Flags type = Flags::Bool; Bool(bool value); - Bool(const Bool& other) = default; + Bool(const Bool &other) = default; bool value() const; + bool const &value_ref() const; + explicit operator bool() const; - bool operator==(const Property& other) const override; + bool operator==(const Property &other) const override; - bool operator==(const Bool& other) const; + bool operator==(const Bool &other) const; bool operator==(bool v) const; - std::ostream& print(std::ostream& stream) const override; + std::ostream &print(std::ostream &stream) const override; - friend std::ostream& operator<<(std::ostream& stream, const Bool& prop); + friend std::ostream &operator<<(std::ostream &stream, const Bool &prop); }; - diff --git a/include/storage/model/properties/double.hpp b/include/storage/model/properties/double.hpp index 6c4e8e9e7..a6c50bb47 100644 --- a/include/storage/model/properties/double.hpp +++ b/include/storage/model/properties/double.hpp @@ -8,6 +8,7 @@ struct Double : public Floating Double(double value) : Floating(Flags::Double), value(value) {} + double const &value_ref() const { return value; } + double value; }; - diff --git a/include/storage/model/properties/float.hpp b/include/storage/model/properties/float.hpp index 25d812c42..2961593cb 100644 --- a/include/storage/model/properties/float.hpp +++ b/include/storage/model/properties/float.hpp @@ -1,7 +1,7 @@ #pragma once -#include "storage/model/properties/floating.hpp" #include "storage/model/properties/double.hpp" +#include "storage/model/properties/floating.hpp" class Float : public Floating { @@ -10,10 +10,9 @@ public: Float(float value) : Floating(Flags::Float), value(value) {} - operator Double() const - { - return Double(value); - } + operator Double() const { return Double(value); } + + float const &value_ref() const { return value; } float value; }; diff --git a/include/storage/model/properties/int32.hpp b/include/storage/model/properties/int32.hpp index 644bd8c98..1312ea5f6 100644 --- a/include/storage/model/properties/int32.hpp +++ b/include/storage/model/properties/int32.hpp @@ -1,7 +1,7 @@ #pragma once -#include "storage/model/properties/integral.hpp" #include "storage/model/properties/int64.hpp" +#include "storage/model/properties/integral.hpp" class Int32 : public Integral { @@ -10,11 +10,9 @@ public: Int32(int32_t value) : Integral(Flags::Int32), value(value) {} - operator Int64() const - { - return Int64(value); - } + operator Int64() const { return Int64(value); } + + int32_t const &value_ref() const { return value; } int32_t value; }; - diff --git a/include/storage/model/properties/int64.hpp b/include/storage/model/properties/int64.hpp index 333a0f8aa..ea6be55cc 100644 --- a/include/storage/model/properties/int64.hpp +++ b/include/storage/model/properties/int64.hpp @@ -9,6 +9,7 @@ public: Int64(int64_t value) : Integral(Flags::Int64), value(value) {} + int64_t const &value_ref() const { return value; } + int64_t value; }; - diff --git a/include/storage/model/properties/string.hpp b/include/storage/model/properties/string.hpp index 6230c9d98..e23460101 100644 --- a/include/storage/model/properties/string.hpp +++ b/include/storage/model/properties/string.hpp @@ -7,23 +7,25 @@ class String : public Property public: static constexpr Flags type = Flags::String; - String(const String&) = default; - String(String&&) = default; + String(const String &) = default; + String(String &&) = default; - String(const std::string& value); - String(std::string&& value); + String(const std::string &value); + String(std::string &&value); - operator const std::string&() const; + operator const std::string &() const; - bool operator==(const Property& other) const override; + bool operator==(const Property &other) const override; - bool operator==(const String& other) const; + bool operator==(const String &other) const; - bool operator==(const std::string& other) const; + bool operator==(const std::string &other) const; - friend std::ostream& operator<<(std::ostream& stream, const String& prop); + friend std::ostream &operator<<(std::ostream &stream, const String &prop); - std::ostream& print(std::ostream& stream) const override; + std::ostream &print(std::ostream &stream) const override; + + std::string const &value_ref() const { return value; } std::string value; }; diff --git a/include/storage/record_accessor.hpp b/include/storage/record_accessor.hpp index e07f6da6f..cb7350c1a 100644 --- a/include/storage/record_accessor.hpp +++ b/include/storage/record_accessor.hpp @@ -75,6 +75,12 @@ public: Properties &properties() const { return record->data.props; } + template + auto at(const std::string &key) const + { + return properties().at(key).template as().value_ref(); + } + explicit operator bool() const { return record != nullptr; } T const *operator->() const { return record; } diff --git a/poc/astar.cpp b/poc/astar.cpp index f22918129..7e9be0e03 100644 --- a/poc/astar.cpp +++ b/poc/astar.cpp @@ -17,7 +17,7 @@ using namespace std; typedef Vertex::Accessor VertexAccessor; void load_graph_dummy(Db &db); -void load_csv(Db &db, char *file_path, char *edge_file_path); +int load_csv(Db &db, char *file_path, char *edge_file_path); class Node { @@ -32,6 +32,25 @@ public: : cost(cost), vacc(vacc), parent(parent), depth(parent->depth + 1) { } + + double sum_vertex_score() + { + auto now = this; + double sum = 0; + do { + sum += now->vacc.at("score"); + now = now->parent; + } while (now != nullptr); + return sum; + } +}; + +class Score +{ +public: + Score() : value(std::numeric_limits::max()) {} + Score(double v) : value(v) {} + double value; }; // class Iterator : public Crtp @@ -74,9 +93,12 @@ public: // Node *head; // }; -void found_result(Node *bef) +void found_result(Node *res) { - std::cout << "{score: " << bef->cost << endl; + 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; @@ -86,7 +108,7 @@ void found_result(Node *bef) double calc_heuristic_cost_dummy(Edge::Accessor &edge, Vertex::Accessor &vertex) { assert(!vertex.empty()); - return 1 - vertex->data.props.at("score").as().value; + return 1 - vertex.at("score"); } typedef bool (*EdgeFilter)(DbAccessor &t, Edge::Accessor &, Node *before); @@ -144,14 +166,16 @@ bool vertex_filter_contained(DbAccessor &t, Vertex::Accessor &v, Node *before) // Vertex filter ima max_depth funkcija te edge filter ima max_depth funkcija. // Jedan za svaku dubinu. // Filtri vracaju true ako element zadovoljava uvjete. -void a_star(Db &db, int64_t sys_id_start, uint max_depth, EdgeFilter e_filter[], +auto a_star(Db &db, int64_t sys_id_start, uint max_depth, EdgeFilter e_filter[], VertexFilter v_filter[], double (*calc_heuristic_cost)(Edge::Accessor &edge, Vertex::Accessor &vertex), int limit) { DbAccessor t(db); + 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); @@ -169,14 +193,22 @@ void a_star(Db &db, int64_t sys_id_start, uint max_depth, EdgeFilter e_filter[], // } if (max_depth <= now->depth) { - found_result(now); + best.push_back(now); count++; if (count >= limit) { - return; + 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(); @@ -188,10 +220,11 @@ void a_star(Db &db, int64_t sys_id_start, uint max_depth, EdgeFilter e_filter[], } }); } while (!queue.empty()); - std::cout << "Found: " << count << " resoults\n"; + // std::cout << "Found: " << count << " resoults\n"; // TODO: GUBI SE MEMORIJA JER SE NODOVI NEBRISU t.commit(); + return best; } // class Data @@ -207,23 +240,66 @@ void a_star(Db &db, int64_t sys_id_start, uint max_depth, EdgeFilter e_filter[], // const int &get_key() { return key; } // }; -int main() +int main(int argc, char **argv) { + if (argc < 3) { + std::cout << "Not enough input values\n"; + return 0; + } else if (argc > 4) { + std::cout << "To much input values\n"; + return 0; + } + Db db; - load_csv(db, "neo4j_nodes_export_2000.csv", "neo4j_edges_export_2000.csv"); - // - // load_graph_dummy(db); - // + auto vertex_no = load_csv(db, argv[argc - 2], argv[argc - 1]); + 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}; - auto begin = clock(); - a_star(db, 0, 3, e_filters, f_filters, &calc_heuristic_cost_dummy, 10); - clock_t end = clock(); - double elapsed_ms = (double(end - begin) / CLOCKS_PER_SEC) * 1000; - std::cout << "A-star: " << elapsed_ms << " [ms]\n"; + + // CONF + std::srand(time(0)); + auto best_n = 10; + auto bench_n = 1000; + auto best_print_n = 10; + bool pick_best_found = argc > 3 ? true : false; + + double sum = 0; + std::vector best; + for (int i = 0; i < bench_n; i++) { + auto start_vertex_index = std::rand() % vertex_no; + + 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()); + } // RhHashMultiMap benchmark // const int n_pow2 = 20; @@ -262,7 +338,7 @@ vector split(const string &s, char delim) return elems; } -void load_csv(Db &db, char *file_path, char *edge_file_path) +int load_csv(Db &db, char *file_path, char *edge_file_path) { std::fstream file(file_path); std::fstream e_file(edge_file_path); @@ -341,6 +417,7 @@ void load_csv(Db &db, char *file_path, char *edge_file_path) << endl; t.commit(); + return v_count; } void load_graph_dummy(Db &db) diff --git a/src/storage/model/properties/bool.cpp b/src/storage/model/properties/bool.cpp index 83c8cf152..70bbc74cb 100644 --- a/src/storage/model/properties/bool.cpp +++ b/src/storage/model/properties/bool.cpp @@ -1,5 +1,8 @@ #include "storage/model/properties/bool.hpp" +const bool TRUE = true; +const bool FALSE = false; + Bool::Bool(bool value) : Property(value ? Flags::True : Flags::False) {} bool Bool::value() const @@ -15,32 +18,25 @@ bool Bool::value() const return (underlying_cast(flags) - underlying_cast(Flags::True)) == 0; } -Bool::operator bool() const -{ - return value(); -} +bool const &Bool::value_ref() const { return value() ? TRUE : FALSE; } -bool Bool::operator==(const Property& other) const +Bool::operator bool() const { return value(); } + +bool Bool::operator==(const Property &other) const { return other.is() && operator==(other.as()); } -bool Bool::operator==(const Bool& other) const -{ - return other.flags == flags; -} +bool Bool::operator==(const Bool &other) const { return other.flags == flags; } -bool Bool::operator==(bool v) const -{ - return value() == v; -} +bool Bool::operator==(bool v) const { return value() == v; } -std::ostream& Bool::print(std::ostream& stream) const +std::ostream &Bool::print(std::ostream &stream) const { return operator<<(stream, *this); } -std::ostream& operator<<(std::ostream& stream, const Bool& prop) +std::ostream &operator<<(std::ostream &stream, const Bool &prop) { return stream << prop.value(); }