Program Listing for File digraphs.hpp¶
↰ Return to documentation for file (xnetwork/classes/digraphs.hpp)
#pragma once
#include <boost/any.hpp>
#include <boost/coroutine2/all.hpp>
#include <cassert>
#include <py2cpp/py2cpp.hpp>
#include <type_traits>
#include <utility>
#include <vector>
#include <xnetwork/classes/coreviews.hpp> // import AtlasView, AdjacencyView
#include <xnetwork/classes/graph.hpp>
#include <xnetwork/classes/reportviews.hpp> // import NodeView, EdgeView, DegreeView
namespace xn
{
template <typename nodeview_t,
typename adjlist_t = py::dict<Value_type<nodeview_t>, int>>
class DiGraphS : public Graph<nodeview_t, adjlist_t>
{
using _Base = Graph<nodeview_t, adjlist_t>;
public:
using Node = typename _Base::Node; // luk
using edge_t = std::pair<Node, Node>;
using graph_attr_dict_factory = typename _Base::graph_attr_dict_factory;
using adjlist_outer_dict_factory =
typename _Base::adjlist_outer_dict_factory;
using key_type = typename _Base::key_type;
using value_type = typename _Base::value_type;
public:
adjlist_outer_dict_factory& _succ; // successor
explicit DiGraphS(const nodeview_t& Nodes)
: _Base {Nodes}
, _succ {_Base::_adj}
{
}
explicit DiGraphS(int num_nodes)
: _Base {py::range<int>(num_nodes)}
, _succ {_Base::_adj}
{
}
auto adj() const
{
using T = decltype(this->_succ);
return AdjacencyView<T>(this->_succ);
}
auto succ() const
{
using T = decltype(this->_succ);
return AdjacencyView<T>(this->_succ);
}
template <typename U = key_type>
typename std::enable_if<std::is_same<U, value_type>::value>::type add_edge(
const Node& u, const Node& v)
{
// auto [u, v] = u_of_edge, v_of_edge;
// add nodes
assert(this->_node.contains(u));
assert(this->_node.contains(v));
// add the edge
// datadict = this->_adj[u].get(v, this->edge_attr_dict_factory());
// datadict.update(attr);
this->_succ[u].insert(v);
// this->_prev[v].insert(u);
this->_num_of_edges += 1;
}
template <typename U = key_type>
typename std::enable_if<!std::is_same<U, value_type>::value>::type add_edge(
const Node& u, const Node& v)
{
// auto [u, v] = u_of_edge, v_of_edge;
// add nodes
assert(this->_node.contains(u));
assert(this->_node.contains(v));
// add the edge
// datadict = this->_adj[u].get(v, this->edge_attr_dict_factory());
// datadict.update(attr);
using T = typename adjlist_t::mapped_type;
auto data = this->_adj[u].get(v, T {});
this->_succ[u][v] = data;
// this->_prev[v][u] = data;
this->_num_of_edges += 1;
}
template <typename T>
auto add_edge(const Node& u, const Node& v, const T& data)
{
assert(this->_node.contains(u));
assert(this->_node.contains(v));
this->_succ[u][v] = data;
this->_num_of_edges += 1;
}
template <typename C1, typename C2>
auto add_edges_from(const C1& edges, const C2& data)
{
auto N = edges.size();
for (auto i = 0; i != N; ++i)
{
const auto& e = edges[i];
this->add_edge(e.first, e.second, data[i]);
}
}
auto has_successor(const Node& u, const Node& v) -> bool
{
return this->_node.contains(u) && this->_succ[u].contains(v);
}
auto& successors(const Node& n)
{
return this->_succ[n];
}
const auto& successors(const Node& n) const
{
return this->_succ[n];
}
using coro_t = boost::coroutines2::coroutine<edge_t>;
using pull_t = typename coro_t::pull_type;
auto edges() const -> pull_t
{
auto func = [&](typename coro_t::push_type& yield)
{
for (auto&& rslt : this->_nodes_nbrs())
{
auto&& n = std::get<0>(rslt);
auto&& nbrs = std::get<1>(rslt);
for (auto&& nbr : nbrs)
{
yield(edge_t {Node(n), Node(nbr)});
}
}
};
return pull_t(func);
}
// auto edges() {
// return OutEdgeView(*this);
// }
// auto in_edges() {
// return InEdgeView(*this);
// }
auto degree(const Node& n) const
{
return this->_succ[n].size();
}
auto clear()
{
this->_succ.clear();
// this->_pred.clear()
// this->_node.clear();
this->graph.clear();
}
auto is_multigraph()
{
return false;
}
auto is_directed()
{
return true;
}
};
using SimpleDiGraphS =
DiGraphS<decltype(py::range<int>(1)), py::dict<int, int>>;
// template <typename nodeview_t,
// typename adjlist_t> DiGraphS(int )
// -> DiGraphS<decltype(py::range<int>(1)), py::set<int>>;
} // namespace xn