.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.
This commit is contained in:
Kruno Tomola Fabro 2016-08-15 13:21:38 +01:00
parent df0bf6fa5f
commit 530be96b36
9 changed files with 144 additions and 63 deletions

View File

@ -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);
};

View File

@ -8,6 +8,7 @@ struct Double : public Floating<Double>
Double(double value) : Floating(Flags::Double), value(value) {}
double const &value_ref() const { return value; }
double value;
};

View File

@ -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<Float>
{
@ -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;
};

View File

@ -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<Int32>
{
@ -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;
};

View File

@ -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;
};

View File

@ -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;
};

View File

@ -75,6 +75,12 @@ public:
Properties &properties() const { return record->data.props; }
template <class V>
auto at(const std::string &key) const
{
return properties().at(key).template as<V>().value_ref();
}
explicit operator bool() const { return record != nullptr; }
T const *operator->() const { return record; }

View File

@ -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<Double>("score");
now = now->parent;
} while (now != nullptr);
return sum;
}
};
class Score
{
public:
Score() : value(std::numeric_limits<double>::max()) {}
Score(double v) : value(v) {}
double value;
};
// class Iterator : public Crtp<Iterator>
@ -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<Double>().value;
return 1 - vertex.at<Double>("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<Id, Score>[max_depth];
std::vector<Node *> best;
auto cmp = [](Node *left, Node *right) { return left->cost > right->cost; };
std::priority_queue<Node *, std::vector<Node *>, 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<Node *> 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<string> 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)

View File

@ -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<Bool>() && operator==(other.as<Bool>());
}
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();
}