Skip to content

Instantly share code, notes, and snippets.

@hexorer
Created January 26, 2022 18:13
Show Gist options
  • Save hexorer/bef4a5f5d15d02a8f4c56f48edc18c0a to your computer and use it in GitHub Desktop.
Save hexorer/bef4a5f5d15d02a8f4c56f48edc18c0a to your computer and use it in GitHub Desktop.
A Draft showing how libgvizard's graph class' public is gonna be...
#ifndef GVIZARD_GRAPH_GRAPH_HPP_
#define GVIZARD_GRAPH_GRAPH_HPP_
#include <cstddef>
#include <optional>
#include <type_traits>
#include <variant>
#include "gvizard/registry/attrset.hpp"
#include "gvizard/registry/attrset_registry.hpp"
#include "gvizard/views.hpp"
#include "gvizard/utils.hpp"
#include "gvizard/graph/dynamic_square_matrix.hpp"
#include "gvizard/graph/dynamic_half_square_matrix.hpp"
/** an adjancency-matrix implementation of graph with internal registry.
*/
namespace gvizard::graph {
struct no_view_t {};
enum class GraphDir { directed, undirected };
enum class EdgeDir { in = 1, out = 2, inout = 3 };
template <GraphDir DirV = GraphDir::undirected,
typename NodeT = std::monostate,
typename EdgeT = std::monostate,
typename ClusterT = std::monostate>
class Graph {
public:
using NodeId = std::size_t;
using EdgeId = std::size_t;
using ClusterId = std::size_t;
private:
constexpr static bool is_undirected = DirV == GraphDir::undirected;
enum class EntityTypeEnum { node, edge, cluster };
struct NodeItem {
NodeT value;
std::optional<ClusterId> cluster_id = std::nullopt;
};
// TODO how to store clusters and nodes' relation to cluster?
//
using value_variant_type = std::variant<NodeT, EdgeT, ClusterT>;
using id_variant_type = std::variant<NodeId, ...>;
using attrset_type = registry::AttrSet<value_variant_type, ClusterId>;
using registry_type = registry::AttrSetRegistry<attrset_type>;
using optional_entity_type =
std::optional<typename registry_type::entity_type>;
using matrix_type =
std::conditional_t<
is_undirected,
detail::DynamicSquareMatrix<optional_entity_type>,
detail::DynamicHalfSquareMatrix<optional_entity_type>
>;
matrix_type matrix_{};
registry_type registry_{};
public:
auto create_cluster(ClusterT cluster) -> std::optional<ClusterId> {
auto cluster_id = registry_.create();
if (!registry_.template set<attr_type>(cluster_id, std::move(cluster)))
return std::nullopt;
return cluster_id;
}
auto add_to_cluster(ClusterId cluster_id, NodeId node_id) -> bool
{
//
}
auto create_node(NodeT node) -> NodeId;
auto create_node(NodeT node, ClusterId cluster_id) -> NodeId;
auto create_edge(NodeId node_a_id, NodeId node_b_id, EdgeT edge) -> EdgeId;
auto get_cluster(ClusterId cluster_id) -> utils::OptionalRef<ClusterT>;
auto get_cluster(ClusterId cluster_id) const
-> utils::OptionalRef<const ClusterT>;
auto get_cluster_nodes(ClusterId cluster_id) const
-> IteratorView<NodeId>;
auto get_node(NodeId node_id) -> utils::OptionalRef<NodeT>;
auto get_node(NodeId node_id) const -> utils::OptionalRef<const NodeT>;
auto has_edge(NodeId node_a_id, NodeId node_b_id) const -> bool;
auto get_edge(NodeId node_a_id, NodeId node_b_id)
-> utils::OptionalRef<EdgeT>;
auto get_edge(NodeId node_a_id, NodeId node_b_id) const
-> utils::OptionalRef<const EdgeT>;
auto get_edge(EdgeId edge_id) -> utils::OptionalRef<EdgeT>;
auto get_edge(EdgeId edge_id) const -> utils::OptionalRef<const EdgeT>;
auto get_edge_nodes(EdgeId edge_id)
-> std::optional<std::pair<NodeId, NodeId>>;
auto remove_cluster(ClusterId cluster_id) -> bool;
auto remove_node(NodeId node_id) -> bool;
auto remove_edge(NodeId node_a_id, NodeId node_b_id) -> bool;
auto remove_edge(EdgeId edge_id) -> bool;
auto get_degree(NodeId node_id, EdgeDir dir = EdgeDir::inout)
-> std::size_t;
auto get_edges(NodeId node_id)
-> IteratorView<std::tuple<NodeId, NodeId, EdgeT&>>;
auto get_edges(NodeId node_id) const
-> IteratorView<std::tuple<NodeId, NodeId, const EdgeT&>>;
auto get_neighbors(NodeId node_id, EdgeDir dir = EdgeDir::inout) const
-> IteratorView<NodeId>;
template <typename ...IdTs>
auto subgraph(IdTs... ids) -> Graph;
template <typename Iter, typename Sentinel>
auto subgraph(Iter begin, Sentinel end) -> Graph;
auto nodes_view() const -> IteratorView<NodeId>;
auto edges_view() const -> IteratorView<EdgeId>;
auto clusters_view() const -> IteratorView<ClusterId>;
auto node_count() const -> std::size_t;
auto edge_count() const -> std::size_t;
auto cluster_count() const -> std::size_t;
template <typename Callable>
auto traversal(Callable&& func, NodeId node_id)
-> CallbackView<NodeId, Callable>;
template <typename Callable>
void traversal(no_view_t, Callable&& func, NodeId node_id);
};
} // namespace gvizard::graph
#endif // GVIZARD_GRAPH_GRAPH_HPP_
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment