Skip to content
This repository has been archived by the owner on Dec 10, 2024. It is now read-only.

Commit

Permalink
WIP: New split path algo
Browse files Browse the repository at this point in the history
  • Loading branch information
iopapamanoglou committed Nov 14, 2024
1 parent 347a88d commit 81b56fe
Show file tree
Hide file tree
Showing 14 changed files with 546 additions and 203 deletions.
33 changes: 19 additions & 14 deletions src/faebryk/core/cpp/include/graph/graph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ class GraphInterface {

template <typename T> static std::shared_ptr<T> factory();
std::unordered_set<GI_ref_weak> get_gif_edges();
std::unordered_map<GI_ref_weak, Link_ref> &get_edges();
Map<GI_ref_weak, Link_ref> &get_edges();
std::optional<Link_ref> is_connected(GI_ref_weak to);
Graph_ref get_graph();
std::unordered_set<Node_ref> get_connected_nodes(std::vector<nb::type_object> types);
Expand Down Expand Up @@ -200,23 +200,28 @@ class Path {
public:
Path(/*const*/ GI_ref_weak path_head);
Path(std::vector<GI_ref_weak> path);
Path(std::vector<GI_ref_weak> path, GI_ref_weak head);
Path(const Path &other);
Path(Path &&other);
~Path();

std::vector</*const*/ GI_ref_weak> path;
const std::vector</*const*/ GI_ref_weak> path;

/*const*/ Link_weak_ref get_link(Edge edge) /*const*/;
std::optional<Edge> last_edge() /*const*/;
std::optional<TriEdge> last_tri_edge() /*const*/;
/*const*/ GI_ref_weak last() /*const*/;
/*const*/ GI_ref_weak first() /*const*/;
/*const*/ GI_ref_weak operator[](int idx) /*const*/;
size_t size() /*const*/;
bool contains(/*const*/ GI_ref_weak gif) /*const*/;
void iterate_edges(std::function<bool(Edge &)> visitor) /*const*/;
/*const*/ std::vector</*const*/ GI_ref_weak> &get_path() /*const*/;
size_t index(/*const*/ GI_ref_weak gif) /*const*/;
/*const*/ Link_weak_ref get_link(Edge edge) const;
std::optional<Edge> last_edge() const;
std::optional<TriEdge> last_tri_edge() const;
/*const*/ GI_ref_weak last() const;
/*const*/ GI_ref_weak first() const;
/*const*/ GI_ref_weak operator[](int idx) const;
size_t size() const;
bool contains(/*const*/ GI_ref_weak gif) const;
void iterate_edges(std::function<bool(Edge &)> visitor) const;
const std::vector</*const*/ GI_ref_weak> &get_path() const;
std::vector</*const*/ GI_ref_weak> get_path_mut() const;
size_t index(/*const*/ GI_ref_weak gif) const;

bool operator==(const Path &other) const;
bool starts_with(const Path &other) const;

std::string str() const;
};
Expand All @@ -237,7 +242,7 @@ class Graph {
static Graph_ref merge_graphs(Graph_ref g1, Graph_ref g2);

std::unordered_set<GI_ref_weak> get_gif_edges(GI_ref_weak from);
std::unordered_map<GI_ref_weak, Link_ref> &get_edges(GI_ref_weak from);
Map<GI_ref_weak, Link_ref> &get_edges(GI_ref_weak from);

Graph();
~Graph();
Expand Down
52 changes: 50 additions & 2 deletions src/faebryk/core/cpp/include/pathfinder/bfs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ struct PathStackElement {
Node::Type parent_type;
Node::Type child_type;
/*const*/ GI_parent_ref_weak parent_gif;
GI_parent_ref_weak child_gif;
std::string name;
bool up;

Expand All @@ -37,20 +38,67 @@ using UnresolvedStack = std::vector<UnresolvedStackElement>;
struct PathData {
UnresolvedStack unresolved_stack;
PathStack split_stack;
bool not_complete = false;
};

class BFSPath : public Path {
namespace std {
template <> struct hash<Path> {
size_t operator()(const Path &p) const noexcept {
const GI_refs_weak &path = p.get_path();
size_t hash = 0;
for (auto &gif : path) {
hash = hash * 31 + std::hash<GI_ref_weak>{}(gif);
}
return hash;
}
};
} // namespace std

class BFSPath : public Path, public std::enable_shared_from_this<BFSPath> {
std::shared_ptr<PathData> path_data;

public:
/**
* @brief Confidence that this path might become 'valid' path
*
* 0 < confidence <= 1
*
* confidence < 1 := weak path
*/
double confidence = 1.0;
/**
* @brief Removes the path from the search
*
*/
bool filtered = false;
/**
* @brief Hibernates the path
*
* Hibernated BFS paths are not visited as long as they are hibernated.
*/
bool hibernated = false;
/**
* @brief Stops the BFS search
*
*/
bool stop = false;

/**
* @brief Notifies BFS that it woke up other paths
*
*/
bool wake_signal = false;

/**
* @brief Notifies BFS that the path has become strong after being weak
*
*/
bool strong_signal = false;

BFSPath(/*const*/ GI_ref_weak path_head);
BFSPath(const BFSPath &other);
BFSPath(const BFSPath &other, /*const*/ GI_ref_weak new_head);
BFSPath(BFSPath &&other);
BFSPath(BFSPath &&other) = delete;
BFSPath operator+(/*const*/ GI_ref_weak gif);

PathData &get_path_data_mut();
Expand Down
47 changes: 45 additions & 2 deletions src/faebryk/core/cpp/include/pathfinder/pathfinder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,64 @@ struct Filter {
bool exec(PathFinder *pf, BFSPath &p);
};

struct SplitState {

/**
* @brief Path that led to this split
*
*/
Path split_prefix;

/**
* @brief Branch complete
*
* All children have complete suffix path from here on
*/
bool complete = false;

bool waiting = false;

/**
* @brief All paths that are from this split on complete further (& fully valid)
*
*/
Map<GI_ref_weak, std::vector<std::shared_ptr<BFSPath>>> suffix_complete_paths;

/**
* @brief All paths that are hibernated per child
*
*/
Map<GI_ref_weak, std::vector<std::shared_ptr<BFSPath>>> wait_paths;

SplitState(const BFSPath &path);

/**
* @brief Parent gif of this split
*
* (always split_prefix.last())
*/
GI_ref_weak split_point() const;
};

class PathFinder {
std::vector<BFSPath> multi_paths;
// TODO I think we should use PathStack (slightly modified) instead of Path
// since non-hierarchical links have no influence on the split
Map<GI_ref_weak, Map<Path, SplitState>> split;
size_t path_cnt = 0;

bool _count(BFSPath &p);
bool _filter_path_by_node_type(BFSPath &p);
bool _filter_path_gif_type(BFSPath &p);
bool _filter_path_by_dead_end_split(BFSPath &p);
bool _build_path_stack(BFSPath &p);
bool _build_path_stack_and_handle_splits(BFSPath &p);
bool _filter_path_by_end_in_self_gif(BFSPath &p);
bool _filter_path_same_end_type(BFSPath &p);
bool _filter_path_by_stack(BFSPath &p);
bool _filter_shallow(BFSPath &p);
bool _filter_conditional_link(BFSPath &p);
bool _handle_valid_split_branch(BFSPath &p);
std::vector<BFSPath> _filter_paths_by_split_join(std::vector<BFSPath> &paths);
bool _filter_incomplete(BFSPath &p);

public:
PathFinder();
Expand Down
12 changes: 12 additions & 0 deletions src/faebryk/core/cpp/include/util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
#pragma once

#include <cxxabi.h>
#include <functional>
#include <memory>
#include <sstream>
#include <string>
#include <unordered_map>
#include <vector>

#if GLOBAL_PRINTF_DEBUG
#else
Expand Down Expand Up @@ -53,4 +56,13 @@ inline std::string formatted_ptr(void *ptr) {
// return ss.str();
//}

template <typename T, typename U>
inline std::unordered_map<U, std::vector<T>> groupby(const std::vector<T> &vec,
std::function<U(T)> f) {
std::unordered_map<U, std::vector<T>> out;
for (auto &t : vec) {
out[f(t)].push_back(t);
}
return out;
}
} // namespace util
2 changes: 1 addition & 1 deletion src/faebryk/core/cpp/src/graph/graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ std::unordered_set<GI_ref_weak> Graph::get_gif_edges(GI_ref_weak from) {
return this->e_cache_simple[from];
}

std::unordered_map<GI_ref_weak, Link_ref> &Graph::get_edges(GI_ref_weak from) {
Map<GI_ref_weak, Link_ref> &Graph::get_edges(GI_ref_weak from) {
return this->e_cache[from];
}

Expand Down
2 changes: 1 addition & 1 deletion src/faebryk/core/cpp/src/graph/graphinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ Set<GI_ref_weak> GraphInterface::get_gif_edges() {
return this->G->get_gif_edges(this);
}

std::unordered_map<GI_ref_weak, Link_ref> &GraphInterface::get_edges() {
Map<GI_ref_weak, Link_ref> &GraphInterface::get_edges() {
return this->G->get_edges(this);
}

Expand Down
15 changes: 15 additions & 0 deletions src/faebryk/core/cpp/src/graph/links.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,13 @@ LinkDirectConditional::LinkDirectConditional(FilterF filter,
: LinkDirect()
, filter(filter)
, needs_only_first_in_path(needs_only_first_in_path) {

// TODO 1 actually check implied is on
// TODO 2 implement this
// not easy, needs some changes in how split paths are handled
if (!needs_only_first_in_path) {
throw std::runtime_error("No support for path conditions with implied links on");
}
}

LinkDirectConditional::LinkDirectConditional(FilterF filter,
Expand All @@ -216,6 +223,14 @@ LinkDirectConditional::LinkDirectConditional(FilterF filter,
: LinkDirect(from, to)
, filter(filter)
, needs_only_first_in_path(needs_only_first_in_path) {

// TODO 1 actually check implied is on
// TODO 2 implement this
// not easy, needs some changes in how split paths are handled
if (!needs_only_first_in_path) {
throw std::runtime_error("No support for path conditions with implied links on");
}

this->set_connections(from, to);
}

Expand Down
47 changes: 35 additions & 12 deletions src/faebryk/core/cpp/src/graph/path.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,38 +22,46 @@ Path::Path(Path &&other)
: path(std::move(other.path)) {
}

Path::Path(std::vector<GI_ref_weak> path, GI_ref_weak head)
: path([&path, &head]() {
auto new_path = path;
new_path.push_back(head);
return new_path;
}()) {
}

Path::~Path() {
}

/*const*/ Link_weak_ref Path::get_link(Edge edge) /*const*/ {
/*const*/ Link_weak_ref Path::get_link(Edge edge) const {
auto out = edge.from->is_connected(edge.to);
assert(out);
return out->get();
}

std::optional<Edge> Path::last_edge() /*const*/ {
std::optional<Edge> Path::last_edge() const {
if (path.size() < 2) {
return {};
}
return Edge{path[path.size() - 2], path.back()};
}

std::optional<TriEdge> Path::last_tri_edge() /*const*/ {
std::optional<TriEdge> Path::last_tri_edge() const {
if (path.size() < 3) {
return {};
}
return std::make_tuple(path[path.size() - 3], path[path.size() - 2], path.back());
}

/*const*/ GI_ref_weak Path::last() /*const*/ {
/*const*/ GI_ref_weak Path::last() const {
return path.back();
}

/*const*/ GI_ref_weak Path::first() /*const*/ {
/*const*/ GI_ref_weak Path::first() const {
return path.front();
}

/*const*/ GI_ref_weak Path::operator[](int idx) /*const*/ {
/*const*/ GI_ref_weak Path::operator[](int idx) const {
if (idx < 0) {
idx = path.size() + idx;
}
Expand All @@ -63,15 +71,15 @@ std::optional<TriEdge> Path::last_tri_edge() /*const*/ {
return path[idx];
}

size_t Path::size() /*const*/ {
size_t Path::size() const {
return path.size();
}

bool Path::contains(/*const*/ GI_ref_weak gif) /*const*/ {
bool Path::contains(/*const*/ GI_ref_weak gif) const {
return std::find(path.begin(), path.end(), gif) != path.end();
}

void Path::iterate_edges(std::function<bool(Edge &)> visitor) /*const*/ {
void Path::iterate_edges(std::function<bool(Edge &)> visitor) const {
for (size_t i = 1; i < path.size(); i++) {
Edge edge{path[i - 1], path[i]};
bool res = visitor(edge);
Expand All @@ -81,11 +89,15 @@ void Path::iterate_edges(std::function<bool(Edge &)> visitor) /*const*/ {
}
}

/*const*/ std::vector</*const*/ GI_ref_weak> &Path::get_path() /*const*/ {
return path;
const std::vector</*const*/ GI_ref_weak> &Path::get_path() const {
return this->path;
}

size_t Path::index(/*const*/ GI_ref_weak gif) /*const*/ {
std::vector</*const*/ GI_ref_weak> Path::get_path_mut() const {
return std::vector<GI_ref_weak>(this->path);
}

size_t Path::index(/*const*/ GI_ref_weak gif) const {
return std::distance(path.begin(), std::find(path.begin(), path.end(), gif));
}

Expand All @@ -99,3 +111,14 @@ std::string Path::str() const {
ss << "]";
return ss.str();
}

bool Path::operator==(const Path &other) const {
return this->path == other.path;
}

bool Path::starts_with(const Path &other) const {
if (other.path.size() > this->path.size()) {
return false;
}
return std::equal(other.path.begin(), other.path.end(), this->path.begin());
}
Loading

0 comments on commit 81b56fe

Please sign in to comment.