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