Added cells customizer
This commit is contained in:
		
							parent
							
								
									aa1c4eb262
								
							
						
					
					
						commit
						bc2e06502e
					
				
							
								
								
									
										148
									
								
								include/customizer/cell_customizer.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								include/customizer/cell_customizer.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,148 @@
 | 
				
			|||||||
 | 
					#ifndef OSRM_CELLS_CUSTOMIZER_HPP
 | 
				
			||||||
 | 
					#define OSRM_CELLS_CUSTOMIZER_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "partition/cell_storage.hpp"
 | 
				
			||||||
 | 
					#include "partition/multi_level_partition.hpp"
 | 
				
			||||||
 | 
					#include "util/binary_heap.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <boost/thread/tss.hpp>
 | 
				
			||||||
 | 
					#include <unordered_set>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace osrm
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					namespace customizer
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CellCustomizer
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public:
 | 
				
			||||||
 | 
					    CellCustomizer(const partition::MultiLevelPartition &partition) : partition(partition) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template <typename GraphT>
 | 
				
			||||||
 | 
					    void Customize(const GraphT &graph,
 | 
				
			||||||
 | 
					                   partition::CellStorage &cells,
 | 
				
			||||||
 | 
					                   partition::LevelID level,
 | 
				
			||||||
 | 
					                   partition::CellID id)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        auto cell = cells.GetCell(level, id);
 | 
				
			||||||
 | 
					        auto destinations = cell.GetDestinationNodes();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // for each source do forward search
 | 
				
			||||||
 | 
					        for (auto source : cell.GetSourceNodes())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::unordered_set<NodeID> destinations_set(destinations.begin(), destinations.end());
 | 
				
			||||||
 | 
					            Heap heap(graph.GetNumberOfNodes());
 | 
				
			||||||
 | 
					            heap.Insert(source, 0, {});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // explore search space
 | 
				
			||||||
 | 
					            while (!heap.Empty() && !destinations_set.empty())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                const NodeID node = heap.DeleteMin();
 | 
				
			||||||
 | 
					                const EdgeWeight weight = heap.GetKey(node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (level == 1)
 | 
				
			||||||
 | 
					                    RelaxNode<true>(graph, cells, heap, level, id, node, weight);
 | 
				
			||||||
 | 
					                else
 | 
				
			||||||
 | 
					                    RelaxNode<false>(graph, cells, heap, level, id, node, weight);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                destinations_set.erase(node);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // fill a map of destination nodes to placeholder pointers
 | 
				
			||||||
 | 
					            auto destination_iter = destinations.begin();
 | 
				
			||||||
 | 
					            for (auto &weight : cell.GetOutWeight(source))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                BOOST_ASSERT(destination_iter != destinations.end());
 | 
				
			||||||
 | 
					                const auto destination = *destination_iter++;
 | 
				
			||||||
 | 
					                weight =
 | 
				
			||||||
 | 
					                    heap.WasInserted(destination) ? heap.GetKey(destination) : INVALID_EDGE_WEIGHT;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template <typename GraphT> void Customize(const GraphT &graph, partition::CellStorage &cells)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        for (std::size_t level = 1; level < partition.GetNumberOfLevels(); ++level)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            tbb::parallel_for(tbb::blocked_range<std::size_t>(0, partition.GetNumberOfCells(level)),
 | 
				
			||||||
 | 
					                              [&](const tbb::blocked_range<std::size_t> &range) {
 | 
				
			||||||
 | 
					                                  for (auto id = range.begin(), end = range.end(); id != end; ++id)
 | 
				
			||||||
 | 
					                                  {
 | 
				
			||||||
 | 
					                                      Customize(graph, cells, level, id);
 | 
				
			||||||
 | 
					                                  }
 | 
				
			||||||
 | 
					                              });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private:
 | 
				
			||||||
 | 
					    struct HeapData
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    using Heap = util::
 | 
				
			||||||
 | 
					        BinaryHeap<NodeID, NodeID, EdgeWeight, HeapData, util::UnorderedMapStorage<NodeID, int>>;
 | 
				
			||||||
 | 
					    using HeapPtr = boost::thread_specific_ptr<Heap>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template <bool first_level, typename GraphT>
 | 
				
			||||||
 | 
					    void RelaxNode(const GraphT &graph,
 | 
				
			||||||
 | 
					                   const partition::CellStorage &cells,
 | 
				
			||||||
 | 
					                   Heap &heap,
 | 
				
			||||||
 | 
					                   partition::LevelID level,
 | 
				
			||||||
 | 
					                   partition::CellID id,
 | 
				
			||||||
 | 
					                   NodeID node,
 | 
				
			||||||
 | 
					                   EdgeWeight weight) const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (!first_level)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // Relax sub-cell nodes
 | 
				
			||||||
 | 
					            auto subcell_id = partition.GetCell(level - 1, node);
 | 
				
			||||||
 | 
					            auto subcell = cells.GetCell(level - 1, subcell_id);
 | 
				
			||||||
 | 
					            auto subcell_destination = subcell.GetDestinationNodes().begin();
 | 
				
			||||||
 | 
					            for (auto subcell_weight : subcell.GetOutWeight(node))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (subcell_weight != INVALID_EDGE_WEIGHT)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    const NodeID to = *subcell_destination;
 | 
				
			||||||
 | 
					                    const EdgeWeight to_weight = subcell_weight + weight;
 | 
				
			||||||
 | 
					                    if (!heap.WasInserted(to))
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        heap.Insert(to, to_weight, {});
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    else if (to_weight < heap.GetKey(to))
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        heap.DecreaseKey(to, to_weight);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                ++subcell_destination;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Relax base graph edges if a sub-cell border edge
 | 
				
			||||||
 | 
					        for (auto edge : graph.GetAdjacentEdgeRange(node))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            const NodeID to = graph.GetTarget(edge);
 | 
				
			||||||
 | 
					            const auto &data = graph.GetEdgeData(edge);
 | 
				
			||||||
 | 
					            if (data.forward && partition.GetCell(level, to) == id &&
 | 
				
			||||||
 | 
					                (first_level ||
 | 
				
			||||||
 | 
					                 partition.GetCell(level - 1, node) != partition.GetCell(level - 1, to)))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                const EdgeWeight to_weight = data.weight + weight;
 | 
				
			||||||
 | 
					                if (!heap.WasInserted(to))
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    heap.Insert(to, to_weight, {});
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else if (to_weight < heap.GetKey(to))
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    heap.DecreaseKey(to, to_weight);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const partition::MultiLevelPartition &partition;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // OSRM_CELLS_CUSTOMIZER_HPP
 | 
				
			||||||
@ -83,13 +83,19 @@ template <bool UseShareMemory> class CellStorageImpl
 | 
				
			|||||||
        class ColumnIterator : public std::iterator<std::random_access_iterator_tag, EdgeWeight>
 | 
					        class ColumnIterator : public std::iterator<std::random_access_iterator_tag, EdgeWeight>
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          public:
 | 
					          public:
 | 
				
			||||||
 | 
					            explicit ColumnIterator() : current(nullptr), stride(1) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            explicit ColumnIterator(WeightPtrT begin, std::size_t row_length)
 | 
					            explicit ColumnIterator(WeightPtrT begin, std::size_t row_length)
 | 
				
			||||||
                : current(begin), stride(row_length)
 | 
					                : current(begin), stride(row_length)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                BOOST_ASSERT(begin != nullptr);
 | 
					                BOOST_ASSERT(begin != nullptr);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            WeightRefT operator*() const { return *current; }
 | 
					            WeightRefT operator*() const
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                BOOST_ASSERT(current);
 | 
				
			||||||
 | 
					                return *current;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            ColumnIterator &operator++()
 | 
					            ColumnIterator &operator++()
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@ -117,25 +123,14 @@ template <bool UseShareMemory> class CellStorageImpl
 | 
				
			|||||||
            std::size_t stride;
 | 
					            std::size_t stride;
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::size_t GetRow(NodeID node) const
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            auto iter = std::find(source_boundary, source_boundary + num_source_nodes, node);
 | 
					 | 
				
			||||||
            BOOST_ASSERT(iter != source_boundary + num_source_nodes);
 | 
					 | 
				
			||||||
            return iter - source_boundary;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        std::size_t GetColumn(NodeID node) const
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            auto iter =
 | 
					 | 
				
			||||||
                std::find(destination_boundary, destination_boundary + num_destination_nodes, node);
 | 
					 | 
				
			||||||
            BOOST_ASSERT(iter != destination_boundary + num_destination_nodes);
 | 
					 | 
				
			||||||
            return iter - destination_boundary;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      public:
 | 
					      public:
 | 
				
			||||||
        auto GetOutWeight(NodeID node) const
 | 
					        auto GetOutWeight(NodeID node) const
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            auto row = GetRow(node);
 | 
					            auto iter = std::find(source_boundary, source_boundary + num_source_nodes, node);
 | 
				
			||||||
 | 
					            if (iter == source_boundary + num_source_nodes)
 | 
				
			||||||
 | 
					                return boost::make_iterator_range(weights, weights);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            auto row = std::distance(source_boundary, iter);
 | 
				
			||||||
            auto begin = weights + num_destination_nodes * row;
 | 
					            auto begin = weights + num_destination_nodes * row;
 | 
				
			||||||
            auto end = begin + num_destination_nodes;
 | 
					            auto end = begin + num_destination_nodes;
 | 
				
			||||||
            return boost::make_iterator_range(begin, end);
 | 
					            return boost::make_iterator_range(begin, end);
 | 
				
			||||||
@ -143,7 +138,12 @@ template <bool UseShareMemory> class CellStorageImpl
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        auto GetInWeight(NodeID node) const
 | 
					        auto GetInWeight(NodeID node) const
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            auto column = GetColumn(node);
 | 
					            auto iter =
 | 
				
			||||||
 | 
					                std::find(destination_boundary, destination_boundary + num_destination_nodes, node);
 | 
				
			||||||
 | 
					            if (iter == destination_boundary + num_destination_nodes)
 | 
				
			||||||
 | 
					                return boost::make_iterator_range(ColumnIterator{}, ColumnIterator{});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            auto column = std::distance(destination_boundary, iter);
 | 
				
			||||||
            auto begin = ColumnIterator{weights + column, num_destination_nodes};
 | 
					            auto begin = ColumnIterator{weights + column, num_destination_nodes};
 | 
				
			||||||
            auto end = ColumnIterator{weights + column + num_source_nodes * num_destination_nodes,
 | 
					            auto end = ColumnIterator{weights + column + num_source_nodes * num_destination_nodes,
 | 
				
			||||||
                                      num_destination_nodes};
 | 
					                                      num_destination_nodes};
 | 
				
			||||||
 | 
				
			|||||||
@ -16,6 +16,8 @@
 | 
				
			|||||||
using namespace osrm;
 | 
					using namespace osrm;
 | 
				
			||||||
using namespace osrm::partition;
 | 
					using namespace osrm::partition;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
struct MockEdge
 | 
					struct MockEdge
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    NodeID start;
 | 
					    NodeID start;
 | 
				
			||||||
@ -41,6 +43,7 @@ auto makeGraph(const std::vector<MockEdge> &mock_edges)
 | 
				
			|||||||
    std::sort(edges.begin(), edges.end());
 | 
					    std::sort(edges.begin(), edges.end());
 | 
				
			||||||
    return util::StaticGraph<EdgeData>(max_id + 1, edges);
 | 
					    return util::StaticGraph<EdgeData>(max_id + 1, edges);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BOOST_AUTO_TEST_SUITE(cell_storage_tests)
 | 
					BOOST_AUTO_TEST_SUITE(cell_storage_tests)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										277
									
								
								unit_tests/util/cell_customization.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										277
									
								
								unit_tests/util/cell_customization.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,277 @@
 | 
				
			|||||||
 | 
					#include <boost/numeric/conversion/cast.hpp>
 | 
				
			||||||
 | 
					#include <boost/test/unit_test.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "customizer/cell_customizer.hpp"
 | 
				
			||||||
 | 
					#include "partition/cell_storage.hpp"
 | 
				
			||||||
 | 
					#include "partition/multi_level_partition.hpp"
 | 
				
			||||||
 | 
					#include "util/static_graph.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define REQUIRE_SIZE_RANGE(range, ref) BOOST_REQUIRE_EQUAL(range.size(), ref)
 | 
				
			||||||
 | 
					#define CHECK_EQUAL_RANGE(range, ...)                                                              \
 | 
				
			||||||
 | 
					    do                                                                                             \
 | 
				
			||||||
 | 
					    {                                                                                              \
 | 
				
			||||||
 | 
					        const auto &lhs = range;                                                                   \
 | 
				
			||||||
 | 
					        const auto &rhs = {__VA_ARGS__};                                                           \
 | 
				
			||||||
 | 
					        BOOST_CHECK_EQUAL_COLLECTIONS(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());             \
 | 
				
			||||||
 | 
					    } while (0)
 | 
				
			||||||
 | 
					#define CHECK_EQUAL_COLLECTIONS(lhs, rhs)                                                          \
 | 
				
			||||||
 | 
					    do                                                                                             \
 | 
				
			||||||
 | 
					    {                                                                                              \
 | 
				
			||||||
 | 
					        BOOST_CHECK_EQUAL_COLLECTIONS(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());             \
 | 
				
			||||||
 | 
					    } while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace osrm;
 | 
				
			||||||
 | 
					using namespace osrm::customizer;
 | 
				
			||||||
 | 
					using namespace osrm::partition;
 | 
				
			||||||
 | 
					using namespace osrm::util;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					struct MockEdge
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    NodeID start;
 | 
				
			||||||
 | 
					    NodeID target;
 | 
				
			||||||
 | 
					    EdgeWeight weight;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					auto makeGraph(const std::vector<MockEdge> &mock_edges)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct EdgeData
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        EdgeWeight weight;
 | 
				
			||||||
 | 
					        bool forward;
 | 
				
			||||||
 | 
					        bool backward;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    using Edge = static_graph_details::SortableEdgeWithData<EdgeData>;
 | 
				
			||||||
 | 
					    std::vector<Edge> edges;
 | 
				
			||||||
 | 
					    std::size_t max_id = 0;
 | 
				
			||||||
 | 
					    for (const auto &m : mock_edges)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        max_id = std::max<std::size_t>(max_id, std::max(m.start, m.target));
 | 
				
			||||||
 | 
					        edges.push_back(Edge{m.start, m.target, m.weight, true, false});
 | 
				
			||||||
 | 
					        edges.push_back(Edge{m.target, m.start, m.weight, false, true});
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    std::sort(edges.begin(), edges.end());
 | 
				
			||||||
 | 
					    return util::StaticGraph<EdgeData>(max_id + 1, edges);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_SUITE(cell_customization_tests)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(two_level_test)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // node:                0  1  2  3
 | 
				
			||||||
 | 
					    std::vector<CellID> l1{{0, 0, 1, 1}};
 | 
				
			||||||
 | 
					    MultiLevelPartition mlp{{l1}, {2}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BOOST_REQUIRE_EQUAL(mlp.GetNumberOfLevels(), 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::vector<MockEdge> edges = {{0, 1, 1}, {0, 2, 1}, {2, 3, 1}, {3, 1, 1}, {3, 2, 1}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto graph = makeGraph(edges);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    CellStorage storage(mlp, graph);
 | 
				
			||||||
 | 
					    CellCustomizer customizer(mlp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto cell_1_0 = storage.GetCell(1, 0);
 | 
				
			||||||
 | 
					    auto cell_1_1 = storage.GetCell(1, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_0.GetSourceNodes(), 1);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_0.GetDestinationNodes(), 1);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_1.GetSourceNodes(), 2);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_1.GetDestinationNodes(), 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_0.GetSourceNodes(), 0);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_0.GetDestinationNodes(), 1);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_1.GetSourceNodes(), 2, 3);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_1.GetDestinationNodes(), 2, 3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_0.GetOutWeight(0), 1);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_0.GetOutWeight(1), 0);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_0.GetInWeight(1), 1);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_0.GetInWeight(0), 0);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_1.GetOutWeight(2), 2);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_1.GetInWeight(3), 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    customizer.Customize(graph, storage, 1, 0);
 | 
				
			||||||
 | 
					    customizer.Customize(graph, storage, 1, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // cell 0
 | 
				
			||||||
 | 
					    // check row source -> destination
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_0.GetOutWeight(0), 1);
 | 
				
			||||||
 | 
					    // check column destination -> source
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_0.GetInWeight(1), 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // cell 1
 | 
				
			||||||
 | 
					    // check row source -> destination
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_1.GetOutWeight(2), 0, 1);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_1.GetOutWeight(3), 1, 0);
 | 
				
			||||||
 | 
					    // check column destination -> source
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_1.GetInWeight(2), 0, 1);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_1.GetInWeight(3), 1, 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(four_levels_test)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // node:                0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
 | 
				
			||||||
 | 
					    std::vector<CellID> l1{{0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3}};
 | 
				
			||||||
 | 
					    std::vector<CellID> l2{{0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}};
 | 
				
			||||||
 | 
					    std::vector<CellID> l3{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
 | 
				
			||||||
 | 
					    MultiLevelPartition mlp{{l1, l2, l3}, {4, 2, 1}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BOOST_REQUIRE_EQUAL(mlp.GetNumberOfLevels(), 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::vector<MockEdge> edges = {
 | 
				
			||||||
 | 
					        {0, 1, 1}, // cell (0, 0, 0)
 | 
				
			||||||
 | 
					        {0, 2, 1},    {3, 1, 1},   {3, 2, 1},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        {4, 5, 1}, // cell (1, 0, 0)
 | 
				
			||||||
 | 
					        {4, 6, 1},    {4, 7, 1},   {5, 4, 1}, {5, 6, 1}, {5, 7, 1}, {6, 4, 1},
 | 
				
			||||||
 | 
					        {6, 5, 1},    {6, 7, 1},   {7, 4, 1}, {7, 5, 1}, {7, 6, 1},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        {9, 11, 1}, // cell (2, 1, 0)
 | 
				
			||||||
 | 
					        {10, 8, 1},   {11, 10, 1},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        {13, 12, 10}, // cell (3, 1, 0)
 | 
				
			||||||
 | 
					        {15, 14, 1},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        {2, 4, 1},  // edge between cells (0, 0, 0) -> (1, 0, 0)
 | 
				
			||||||
 | 
					        {5, 12, 1}, // edge between cells (1, 0, 0) -> (3, 1, 0)
 | 
				
			||||||
 | 
					        {8, 3, 1},  // edge between cells (2, 1, 0) -> (0, 0, 0)
 | 
				
			||||||
 | 
					        {9, 3, 1},  // edge between cells (2, 1, 0) -> (0, 0, 0)
 | 
				
			||||||
 | 
					        {12, 5, 1}, // edge between cells (3, 1, 0) -> (1, 0, 0)
 | 
				
			||||||
 | 
					        {13, 7, 1}, // edge between cells (3, 1, 0) -> (1, 0, 0)
 | 
				
			||||||
 | 
					        {14, 9, 1}, // edge between cells (2, 1, 0) -> (0, 0, 0)
 | 
				
			||||||
 | 
					        {14, 11, 1} // edge between cells (2, 1, 0) -> (0, 0, 0)
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto graph = makeGraph(edges);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    CellStorage storage(mlp, graph);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto cell_1_0 = storage.GetCell(1, 0);
 | 
				
			||||||
 | 
					    auto cell_1_1 = storage.GetCell(1, 1);
 | 
				
			||||||
 | 
					    auto cell_1_2 = storage.GetCell(1, 2);
 | 
				
			||||||
 | 
					    auto cell_1_3 = storage.GetCell(1, 3);
 | 
				
			||||||
 | 
					    auto cell_2_0 = storage.GetCell(2, 0);
 | 
				
			||||||
 | 
					    auto cell_2_1 = storage.GetCell(2, 1);
 | 
				
			||||||
 | 
					    auto cell_3_0 = storage.GetCell(3, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_0.GetSourceNodes(), 1);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_0.GetDestinationNodes(), 1);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_0.GetSourceNodes(), 3);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_0.GetDestinationNodes(), 2);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_0.GetOutWeight(3), 1);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_0.GetInWeight(2), 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_1.GetSourceNodes(), 3);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_1.GetDestinationNodes(), 3);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_1.GetSourceNodes(), 4, 5, 7);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_1.GetDestinationNodes(), 4, 5, 7);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_1.GetOutWeight(4), 3);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_1.GetOutWeight(5), 3);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_1.GetOutWeight(7), 3);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_1.GetInWeight(4), 3);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_1.GetInWeight(5), 3);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_1.GetInWeight(7), 3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_2.GetSourceNodes(), 2);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_2.GetDestinationNodes(), 2);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_2.GetSourceNodes(), 9, 11);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_2.GetDestinationNodes(), 8, 11);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_2.GetOutWeight(9), 2);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_2.GetOutWeight(11), 2);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_2.GetInWeight(8), 2);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_2.GetInWeight(11), 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_3.GetSourceNodes(), 1);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_3.GetDestinationNodes(), 2);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_3.GetSourceNodes(), 13);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_3.GetDestinationNodes(), 12, 14);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_3.GetOutWeight(13), 2);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_3.GetInWeight(12), 1);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_1_3.GetInWeight(14), 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_2_0.GetSourceNodes(), 3);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_2_0.GetDestinationNodes(), 2);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_2_0.GetSourceNodes(), 3, 5, 7);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_2_0.GetDestinationNodes(), 5, 7);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_2_0.GetOutWeight(3), 2);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_2_0.GetOutWeight(5), 2);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_2_0.GetOutWeight(7), 2);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_2_0.GetInWeight(5), 3);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_2_0.GetInWeight(7), 3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_2_1.GetSourceNodes(), 2);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_2_1.GetDestinationNodes(), 3);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_2_1.GetSourceNodes(), 9, 13);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_2_1.GetDestinationNodes(), 8, 9, 12);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_2_1.GetOutWeight(9), 3);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_2_1.GetOutWeight(13), 3);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_2_1.GetInWeight(8), 2);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_2_1.GetInWeight(9), 2);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_2_1.GetInWeight(12), 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_3_0.GetSourceNodes(), 0);
 | 
				
			||||||
 | 
					    REQUIRE_SIZE_RANGE(cell_3_0.GetDestinationNodes(), 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    CellCustomizer customizer(mlp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    customizer.Customize(graph, storage, 1, 0);
 | 
				
			||||||
 | 
					    customizer.Customize(graph, storage, 1, 1);
 | 
				
			||||||
 | 
					    customizer.Customize(graph, storage, 1, 2);
 | 
				
			||||||
 | 
					    customizer.Customize(graph, storage, 1, 3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    customizer.Customize(graph, storage, 2, 0);
 | 
				
			||||||
 | 
					    customizer.Customize(graph, storage, 2, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // level 1
 | 
				
			||||||
 | 
					    // cell 0
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_0.GetOutWeight(3), 1);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_0.GetInWeight(2), 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // cell 1
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_1.GetOutWeight(4), 0, 1, 1);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_1.GetOutWeight(5), 1, 0, 1);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_1.GetOutWeight(7), 1, 1, 0);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_1.GetInWeight(4), 0, 1, 1);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_1.GetInWeight(5), 1, 0, 1);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_1.GetInWeight(7), 1, 1, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // cell 2
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_2.GetOutWeight(9), 3, 1);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_2.GetOutWeight(11), 2, 0);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_2.GetInWeight(8), 3, 2);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_2.GetInWeight(11), 1, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // cell 3
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_3.GetOutWeight(13), 10, INVALID_EDGE_WEIGHT);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_3.GetInWeight(12), 10);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_1_3.GetInWeight(14), INVALID_EDGE_WEIGHT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // level 2
 | 
				
			||||||
 | 
					    // cell 0
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_2_0.GetOutWeight(3), 3, 3);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_2_0.GetOutWeight(5), 0, 1);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_2_0.GetOutWeight(7), 1, 0);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_2_0.GetInWeight(5), 3, 0, 1);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_2_0.GetInWeight(7), 3, 1, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // cell 1
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_2_1.GetOutWeight(9), 3, 0, INVALID_EDGE_WEIGHT);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_2_1.GetOutWeight(13), INVALID_EDGE_WEIGHT, INVALID_EDGE_WEIGHT, 10);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_2_1.GetInWeight(8), 3, INVALID_EDGE_WEIGHT);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_2_1.GetInWeight(9), 0, INVALID_EDGE_WEIGHT);
 | 
				
			||||||
 | 
					    CHECK_EQUAL_RANGE(cell_2_1.GetInWeight(12), INVALID_EDGE_WEIGHT, 10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    CellStorage storage_rec(mlp, graph);
 | 
				
			||||||
 | 
					    customizer.Customize(graph, storage_rec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    CHECK_EQUAL_COLLECTIONS(cell_2_1.GetOutWeight(9), storage_rec.GetCell(2, 1).GetOutWeight(9));
 | 
				
			||||||
 | 
					    CHECK_EQUAL_COLLECTIONS(cell_2_1.GetOutWeight(13), storage_rec.GetCell(2, 1).GetOutWeight(13));
 | 
				
			||||||
 | 
					    CHECK_EQUAL_COLLECTIONS(cell_2_1.GetInWeight(8), storage_rec.GetCell(2, 1).GetInWeight(8));
 | 
				
			||||||
 | 
					    CHECK_EQUAL_COLLECTIONS(cell_2_1.GetInWeight(9), storage_rec.GetCell(2, 1).GetInWeight(9));
 | 
				
			||||||
 | 
					    CHECK_EQUAL_COLLECTIONS(cell_2_1.GetInWeight(12), storage_rec.GetCell(2, 1).GetInWeight(12));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_SUITE_END()
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user