github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/test/runtime/nr/gtest_algo.cpp (about)

     1  // Copyright (C) 2018 go-nebulas authors
     2  //
     3  // This file is part of the go-nebulas library.
     4  //
     5  // the go-nebulas library is free software: you can redistribute it and/or
     6  // modify
     7  // it under the terms of the GNU General Public License as published by
     8  // the Free Software Foundation, either version 3 of the License, or
     9  // (at your option) any later version.
    10  //
    11  // the go-nebulas library is distributed in the hope that it will be useful,
    12  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  // GNU General Public License for more details.
    15  //
    16  // You should have received a copy of the GNU General Public License
    17  // along with the go-nebulas library.  If not, see
    18  // <http://www.gnu.org/licenses/>.
    19  //
    20  
    21  #include "common/common.h"
    22  #include "runtime/nr/graph/algo.h"
    23  #include <gtest/gtest.h>
    24  
    25  TEST(test_algo, get_in_out_vals) {
    26    neb::rt::transaction_graph tg;
    27    tg.add_edge(neb::to_address("a"), neb::to_address("b"), 1, 1);
    28    tg.add_edge(neb::to_address("b"), neb::to_address("c"), 2, 2);
    29    tg.add_edge(neb::to_address("b"), neb::to_address("d"), 3, 3);
    30    tg.add_edge(neb::to_address("c"), neb::to_address("d"), 4, 4);
    31  
    32    auto graph = tg.internal_graph();
    33  
    34    auto addr_and_in_out_vals_ptr = neb::rt::graph_algo::get_in_out_vals(graph);
    35    auto addr_and_in_out_vals = *addr_and_in_out_vals_ptr;
    36    EXPECT_TRUE(addr_and_in_out_vals[neb::to_address("a")].m_in_val == 0);
    37    EXPECT_TRUE(addr_and_in_out_vals[neb::to_address("a")].m_out_val == 1);
    38  
    39    EXPECT_TRUE(addr_and_in_out_vals[neb::to_address("b")].m_in_val == 1);
    40    EXPECT_TRUE(addr_and_in_out_vals[neb::to_address("b")].m_out_val == 5);
    41  
    42    EXPECT_TRUE(addr_and_in_out_vals[neb::to_address("c")].m_in_val == 2);
    43    EXPECT_TRUE(addr_and_in_out_vals[neb::to_address("c")].m_out_val == 4);
    44  
    45    EXPECT_TRUE(addr_and_in_out_vals[neb::to_address("d")].m_in_val == 7);
    46    EXPECT_TRUE(addr_and_in_out_vals[neb::to_address("d")].m_out_val == 0);
    47  }
    48  
    49  TEST(test_algo, get_stakes) {
    50    neb::rt::transaction_graph tg;
    51    tg.add_edge(neb::to_address("a"), neb::to_address("b"), 4, 4);
    52    tg.add_edge(neb::to_address("b"), neb::to_address("c"), 3, 3);
    53    tg.add_edge(neb::to_address("b"), neb::to_address("d"), 2, 2);
    54    tg.add_edge(neb::to_address("c"), neb::to_address("d"), 1, 1);
    55  
    56    auto graph = tg.internal_graph();
    57    auto addr_and_stakes_ptr = neb::rt::graph_algo::get_stakes(graph);
    58    auto addr_and_stakes = *addr_and_stakes_ptr;
    59  
    60    EXPECT_TRUE(addr_and_stakes[neb::to_address("a")] == -4);
    61    EXPECT_TRUE(addr_and_stakes[neb::to_address("b")] == -1);
    62    EXPECT_TRUE(addr_and_stakes[neb::to_address("c")] == 2);
    63    EXPECT_TRUE(addr_and_stakes[neb::to_address("d")] == 3);
    64  }
    65  
    66  TEST(test_algo, get_in_out_degree) {
    67    neb::rt::transaction_graph tg;
    68    tg.add_edge(neb::to_address("a"), neb::to_address("b"), 1, 1);
    69    tg.add_edge(neb::to_address("a"), neb::to_address("c"), 2, 2);
    70    tg.add_edge(neb::to_address("b"), neb::to_address("c"), 3, 3);
    71    tg.add_edge(neb::to_address("b"), neb::to_address("d"), 4, 4);
    72    tg.add_edge(neb::to_address("c"), neb::to_address("d"), 5, 5);
    73  
    74    auto graph = tg.internal_graph();
    75  
    76    auto addr_and_in_out_degree_ptr =
    77        neb::rt::graph_algo::get_in_out_degrees(graph);
    78    auto addr_and_in_out_degree = *addr_and_in_out_degree_ptr;
    79    EXPECT_TRUE(addr_and_in_out_degree[neb::to_address("a")].m_in_degree == 0);
    80    EXPECT_TRUE(addr_and_in_out_degree[neb::to_address("a")].m_out_degree == 2);
    81  
    82    EXPECT_TRUE(addr_and_in_out_degree[neb::to_address("b")].m_in_degree == 1);
    83    EXPECT_TRUE(addr_and_in_out_degree[neb::to_address("b")].m_out_degree == 2);
    84  
    85    EXPECT_TRUE(addr_and_in_out_degree[neb::to_address("c")].m_in_degree == 2);
    86    EXPECT_TRUE(addr_and_in_out_degree[neb::to_address("c")].m_out_degree == 1);
    87  
    88    EXPECT_TRUE(addr_and_in_out_degree[neb::to_address("d")].m_in_degree == 2);
    89    EXPECT_TRUE(addr_and_in_out_degree[neb::to_address("d")].m_out_degree == 0);
    90  }
    91  
    92  TEST(test_algo, get_degree_sum) {
    93    neb::rt::transaction_graph tg;
    94    tg.add_edge(neb::to_address("a"), neb::to_address("b"), 1, 1);
    95    tg.add_edge(neb::to_address("a"), neb::to_address("c"), 2, 2);
    96    tg.add_edge(neb::to_address("b"), neb::to_address("c"), 3, 3);
    97    tg.add_edge(neb::to_address("b"), neb::to_address("d"), 4, 4);
    98    tg.add_edge(neb::to_address("c"), neb::to_address("d"), 5, 5);
    99  
   100    auto graph = tg.internal_graph();
   101    auto addr_and_degrees_ptr = neb::rt::graph_algo::get_degree_sum(graph);
   102    auto addr_and_degrees = *addr_and_degrees_ptr;
   103  
   104    EXPECT_TRUE(addr_and_degrees[neb::to_address("a")] == 2);
   105    EXPECT_TRUE(addr_and_degrees[neb::to_address("b")] == 3);
   106    EXPECT_TRUE(addr_and_degrees[neb::to_address("c")] == 3);
   107    EXPECT_TRUE(addr_and_degrees[neb::to_address("d")] == 2);
   108  }
   109  
   110  TEST(test_algo, merge_edges_with_same_from_and_same_to) {
   111    neb::rt::transaction_graph tg;
   112    tg.add_edge(neb::to_address("a"), neb::to_address("a"), 1, 1);
   113    tg.add_edge(neb::to_address("a"), neb::to_address("b"), 2, 2);
   114    tg.add_edge(neb::to_address("a"), neb::to_address("b"), 3, 3);
   115    tg.add_edge(neb::to_address("b"), neb::to_address("a"), 4, 4);
   116  
   117    auto graph = tg.internal_graph();
   118    neb::rt::graph_algo::merge_edges_with_same_from_and_same_to(graph);
   119  
   120    neb::rt::transaction_graph::viterator_t vi, vi_end;
   121  
   122    for (boost::tie(vi, vi_end) = boost::vertices(graph); vi != vi_end; vi++) {
   123      neb::rt::transaction_graph::oeiterator_t oei, oei_end;
   124      for (boost::tie(oei, oei_end) = boost::out_edges(*vi, graph);
   125           oei != oei_end; oei++) {
   126        auto source = boost::source(*oei, graph);
   127        auto target = boost::target(*oei, graph);
   128        std::string source_name =
   129            boost::get(boost::vertex_name_t(), graph, source);
   130        std::string target_name =
   131            boost::get(boost::vertex_name_t(), graph, target);
   132  
   133        neb::wei_t val = boost::get(boost::edge_weight_t(), graph, *oei);
   134        if (source_name.compare("a") == 0 && target_name.compare("a") == 0) {
   135          EXPECT_TRUE(val == 1);
   136        } else if (source_name.compare("a") == 0 &&
   137                   target_name.compare("b") == 0) {
   138          EXPECT_TRUE(val == 5);
   139        } else if (source_name.compare("b") == 0 &&
   140                   target_name.compare("a") == 0) {
   141          EXPECT_TRUE(val == 4);
   142        }
   143      }
   144    }
   145  }
   146  
   147  TEST(test_algo, merge_topk_edges_with_same_from_and_same_to_less_than_k) {
   148    neb::rt::transaction_graph tg;
   149    tg.add_edge(neb::to_address("a"), neb::to_address("b"), 1, 1);
   150    tg.add_edge(neb::to_address("a"), neb::to_address("b"), 2, 2);
   151  
   152    auto graph = tg.internal_graph();
   153    neb::rt::graph_algo::merge_topk_edges_with_same_from_and_same_to(graph);
   154  
   155    neb::rt::transaction_graph::viterator_t vi, vi_end;
   156  
   157    boost::tie(vi, vi_end) = boost::vertices(graph);
   158    neb::rt::transaction_graph::oeiterator_t oei, oei_end;
   159    boost::tie(oei, oei_end) = boost::out_edges(*vi, graph);
   160    auto source = boost::source(*oei, graph);
   161    auto target = boost::target(*oei, graph);
   162    std::string source_name = boost::get(boost::vertex_name_t(), graph, source);
   163    std::string target_name = boost::get(boost::vertex_name_t(), graph, target);
   164    EXPECT_EQ(source_name, "a");
   165    EXPECT_EQ(target_name, "b");
   166  
   167    int64_t timestamp = boost::get(boost::edge_timestamp_t(), graph, *oei);
   168    EXPECT_EQ(timestamp, 0);
   169  
   170    neb::wei_t val = boost::get(boost::edge_weight_t(), graph, *oei);
   171    EXPECT_TRUE(val == 3);
   172  }
   173  
   174  TEST(test_algo, merge_topk_edges_with_same_from_and_same_to_equal_to_k) {
   175    neb::rt::transaction_graph tg1;
   176    tg1.add_edge(neb::to_address("a"), neb::to_address("b"), 1, 1);
   177    tg1.add_edge(neb::to_address("a"), neb::to_address("b"), 2, 2);
   178    tg1.add_edge(neb::to_address("a"), neb::to_address("b"), 3, 3);
   179  
   180    auto graph = tg1.internal_graph();
   181    neb::rt::graph_algo::merge_topk_edges_with_same_from_and_same_to(graph);
   182  
   183    neb::rt::transaction_graph::viterator_t vi, vi_end;
   184    boost::tie(vi, vi_end) = boost::vertices(graph);
   185    neb::rt::transaction_graph::oeiterator_t oei, oei_end;
   186    boost::tie(oei, oei_end) = boost::out_edges(*vi, graph);
   187    auto source = boost::source(*oei, graph);
   188    auto target = boost::target(*oei, graph);
   189    std::string source_name = boost::get(boost::vertex_name_t(), graph, source);
   190    std::string target_name = boost::get(boost::vertex_name_t(), graph, target);
   191    EXPECT_EQ(source_name, "a");
   192    EXPECT_EQ(target_name, "b");
   193  
   194    int64_t timestamp = boost::get(boost::edge_timestamp_t(), graph, *oei);
   195    EXPECT_EQ(timestamp, 0);
   196  
   197    neb::wei_t val = boost::get(boost::edge_weight_t(), graph, *oei);
   198    EXPECT_TRUE(val == 6);
   199  }
   200  
   201  TEST(test_algo, merge_topk_edges_with_same_from_and_same_to_larger_than_k) {
   202    neb::rt::transaction_graph tg2;
   203    tg2.add_edge(neb::to_address("a"), neb::to_address("b"), 1, 1);
   204    tg2.add_edge(neb::to_address("a"), neb::to_address("b"), 2, 2);
   205    tg2.add_edge(neb::to_address("a"), neb::to_address("b"), 3, 3);
   206    tg2.add_edge(neb::to_address("a"), neb::to_address("b"), 4, 4);
   207  
   208    auto graph = tg2.internal_graph();
   209    neb::rt::graph_algo::merge_topk_edges_with_same_from_and_same_to(graph);
   210  
   211    neb::rt::transaction_graph::viterator_t vi, vi_end;
   212    boost::tie(vi, vi_end) = boost::vertices(graph);
   213    neb::rt::transaction_graph::oeiterator_t oei, oei_end;
   214    boost::tie(oei, oei_end) = boost::out_edges(*vi, graph);
   215  
   216    auto source = boost::source(*oei, graph);
   217    auto target = boost::target(*oei, graph);
   218    std::string source_name = boost::get(boost::vertex_name_t(), graph, source);
   219    std::string target_name = boost::get(boost::vertex_name_t(), graph, target);
   220    EXPECT_EQ(source_name, "a");
   221    EXPECT_EQ(target_name, "b");
   222  
   223    int64_t timestamp = boost::get(boost::edge_timestamp_t(), graph, *oei);
   224    EXPECT_EQ(timestamp, 0);
   225  
   226    neb::wei_t val = boost::get(boost::edge_weight_t(), graph, *oei);
   227    EXPECT_TRUE(val != 6);
   228    EXPECT_TRUE(val == 9);
   229  }
   230  
   231  // class private func
   232  TEST(test_algo, merge_two_graphs) {
   233    neb::rt::transaction_graph tg1;
   234    tg1.add_edge(neb::to_address("a"), neb::to_address("b"), 1, 1);
   235    tg1.add_edge(neb::to_address("a"), neb::to_address("c"), 2, 2);
   236  
   237    neb::rt::transaction_graph tg2;
   238    tg2.add_edge(neb::to_address("a"), neb::to_address("c"), 3, 3);
   239    tg2.add_edge(neb::to_address("a"), neb::to_address("d"), 4, 4);
   240    tg2.add_edge(neb::to_address("c"), neb::to_address("d"), 5, 5);
   241  
   242    neb::rt::transaction_graph_ptr_t ptr1 =
   243        std::make_unique<neb::rt::transaction_graph>(tg1);
   244    neb::rt::transaction_graph_ptr_t ptr2 =
   245        std::make_unique<neb::rt::transaction_graph>(tg2);
   246    neb::rt::graph_algo::merge_two_graphs(ptr1.get(), ptr2.get());
   247  
   248    neb::rt::transaction_graph::viterator_t vi, vi_end;
   249  
   250    auto graph = ptr1->internal_graph();
   251    for (boost::tie(vi, vi_end) = boost::vertices(graph); vi != vi_end; vi++) {
   252      neb::rt::transaction_graph::oeiterator_t oei, oei_end;
   253      for (boost::tie(oei, oei_end) = boost::out_edges(*vi, graph);
   254           oei != oei_end; oei++) {
   255        auto source = boost::source(*oei, graph);
   256        auto target = boost::target(*oei, graph);
   257        std::string source_name =
   258            boost::get(boost::vertex_name_t(), graph, source);
   259        std::string target_name =
   260            boost::get(boost::vertex_name_t(), graph, target);
   261  
   262        neb::wei_t val = boost::get(boost::edge_weight_t(), graph, *oei);
   263        if (source_name.compare("a") == 0 && target_name.compare("b") == 0) {
   264          EXPECT_TRUE(val == 1);
   265        } else if (source_name.compare("a") == 0 &&
   266                   target_name.compare("c") == 0) {
   267          EXPECT_TRUE(val == 2 || val == 3);
   268        } else if (source_name.compare("a") == 0 &&
   269                   target_name.compare("d") == 0) {
   270          EXPECT_TRUE(val == 4);
   271        } else if (source_name.compare("c") == 0 &&
   272                   target_name.compare("d") == 0) {
   273          EXPECT_TRUE(val == 5);
   274        }
   275      }
   276    }
   277  }
   278  
   279  TEST(test_algo, merge_graphs) {
   280    neb::rt::transaction_graph tg1;
   281    tg1.add_edge(neb::to_address("a"), neb::to_address("b"), 1, 1);
   282    tg1.add_edge(neb::to_address("a"), neb::to_address("c"), 2, 2);
   283  
   284    neb::rt::transaction_graph tg2;
   285    tg2.add_edge(neb::to_address("a"), neb::to_address("c"), 3, 3);
   286    tg2.add_edge(neb::to_address("a"), neb::to_address("d"), 4, 4);
   287    tg2.add_edge(neb::to_address("c"), neb::to_address("d"), 5, 5);
   288  
   289    neb::rt::transaction_graph tg3;
   290    tg3.add_edge(neb::to_address("e"), neb::to_address("f"), 6, 6);
   291    tg3.add_edge(neb::to_address("f"), neb::to_address("b"), 7, 7);
   292    tg3.add_edge(neb::to_address("c"), neb::to_address("f"), 8, 8);
   293  
   294    neb::rt::transaction_graph_ptr_t ptr1 =
   295        std::make_unique<neb::rt::transaction_graph>(tg1);
   296    neb::rt::transaction_graph_ptr_t ptr2 =
   297        std::make_unique<neb::rt::transaction_graph>(tg2);
   298    neb::rt::transaction_graph_ptr_t ptr3 =
   299        std::make_unique<neb::rt::transaction_graph>(tg3);
   300    std::vector<neb::rt::transaction_graph_ptr_t> v;
   301    v.push_back(std::move(ptr1));
   302    v.push_back(std::move(ptr2));
   303    v.push_back(std::move(ptr3));
   304    auto ptr = neb::rt::graph_algo::merge_graphs(v);
   305  
   306    neb::rt::transaction_graph::viterator_t vi, vi_end;
   307  
   308    auto graph = ptr->internal_graph();
   309    for (boost::tie(vi, vi_end) = boost::vertices(graph); vi != vi_end; vi++) {
   310      neb::rt::transaction_graph::oeiterator_t oei, oei_end;
   311      for (boost::tie(oei, oei_end) = boost::out_edges(*vi, graph);
   312           oei != oei_end; oei++) {
   313        auto source = boost::source(*oei, graph);
   314        auto target = boost::target(*oei, graph);
   315        std::string source_name =
   316            boost::get(boost::vertex_name_t(), graph, source);
   317        std::string target_name =
   318            boost::get(boost::vertex_name_t(), graph, target);
   319  
   320        neb::wei_t val = boost::get(boost::edge_weight_t(), graph, *oei);
   321        if (source_name.compare("a") == 0 && target_name.compare("b") == 0) {
   322          EXPECT_TRUE(val == 1);
   323        } else if (source_name.compare("a") == 0 &&
   324                   target_name.compare("c") == 0) {
   325          EXPECT_TRUE(val == 2 || val == 3);
   326        } else if (source_name.compare("a") == 0 &&
   327                   target_name.compare("d") == 0) {
   328          EXPECT_TRUE(val == 4);
   329        } else if (source_name.compare("c") == 0 &&
   330                   target_name.compare("d") == 0) {
   331          EXPECT_TRUE(val == 5);
   332        } else if (source_name.compare("e") == 0 &&
   333                   target_name.compare("f") == 0) {
   334          EXPECT_TRUE(val == 6);
   335        } else if (source_name.compare("f") == 0 &&
   336                   target_name.compare("b") == 0) {
   337          EXPECT_TRUE(val == 7);
   338        } else if (source_name.compare("c") == 0 &&
   339                   target_name.compare("f") == 0) {
   340          EXPECT_TRUE(val == 8);
   341        }
   342      }
   343    }
   344  }
   345  
   346  TEST(test_algo, find_a_cycle_based_on_time_sequence) {
   347    neb::rt::transaction_graph tg;
   348    tg.add_edge(neb::to_address("a"), neb::to_address("b"), 1, 5);
   349    tg.add_edge(neb::to_address("d"), neb::to_address("a"), 2, 1);
   350    tg.add_edge(neb::to_address("b"), neb::to_address("d"), 3, 2);
   351    tg.add_edge(neb::to_address("c"), neb::to_address("b"), 4, 4);
   352    tg.add_edge(neb::to_address("d"), neb::to_address("c"), 5, 3);
   353  
   354    auto graph = tg.internal_graph();
   355    auto cycle =
   356        neb::rt::graph_algo::find_a_cycle_based_on_time_sequence(graph, {});
   357  
   358    auto it = cycle.begin();
   359    auto source = boost::source(*it, graph);
   360    auto target = boost::target(*it, graph);
   361    std::string source_name = boost::get(boost::vertex_name_t(), graph, source);
   362    std::string target_name = boost::get(boost::vertex_name_t(), graph, target);
   363    auto ts = boost::get(boost::edge_timestamp_t(), graph, *it);
   364    EXPECT_TRUE(source_name.compare("b") == 0 && target_name.compare("d") == 0 &&
   365                ts == 2);
   366    it++;
   367  
   368    source = boost::source(*it, graph);
   369    target = boost::target(*it, graph);
   370    source_name = boost::get(boost::vertex_name_t(), graph, source);
   371    target_name = boost::get(boost::vertex_name_t(), graph, target);
   372    ts = boost::get(boost::edge_timestamp_t(), graph, *it);
   373    EXPECT_TRUE(source_name.compare("d") == 0 && target_name.compare("c") == 0 &&
   374                ts == 3);
   375    it++;
   376  
   377    source = boost::source(*it, graph);
   378    target = boost::target(*it, graph);
   379    source_name = boost::get(boost::vertex_name_t(), graph, source);
   380    target_name = boost::get(boost::vertex_name_t(), graph, target);
   381    ts = boost::get(boost::edge_timestamp_t(), graph, *it);
   382    EXPECT_TRUE(source_name.compare("c") == 0 && target_name.compare("b") == 0 &&
   383                ts == 4);
   384    it++;
   385  }
   386  
   387  TEST(test_algo, remove_cycles_based_on_time_sequence_case1) {
   388    neb::rt::transaction_graph tg1;
   389    tg1.add_edge(neb::to_address("a"), neb::to_address("a"), 1, 1);
   390    tg1.add_edge(neb::to_address("a"), neb::to_address("b"), 2, 2);
   391    tg1.add_edge(neb::to_address("b"), neb::to_address("a"), 3, 3);
   392    tg1.add_edge(neb::to_address("b"), neb::to_address("c"), 4, 4);
   393    tg1.add_edge(neb::to_address("c"), neb::to_address("a"), 5, 5);
   394  
   395    auto graph = tg1.internal_graph();
   396    neb::rt::graph_algo::remove_cycles_based_on_time_sequence(graph);
   397  
   398    neb::rt::transaction_graph::viterator_t vi, vi_end;
   399  
   400    for (boost::tie(vi, vi_end) = boost::vertices(graph); vi != vi_end; vi++) {
   401      neb::rt::transaction_graph::oeiterator_t oei, oei_end;
   402      for (boost::tie(oei, oei_end) = boost::out_edges(*vi, graph);
   403           oei != oei_end; oei++) {
   404        auto source = boost::source(*oei, graph);
   405        auto target = boost::target(*oei, graph);
   406        std::string source_name =
   407            boost::get(boost::vertex_name_t(), graph, source);
   408        std::string target_name =
   409            boost::get(boost::vertex_name_t(), graph, target);
   410  
   411        neb::wei_t val = boost::get(boost::edge_weight_t(), graph, *oei);
   412        int64_t ts = boost::get(boost::edge_timestamp_t(), graph, *oei);
   413        if (source_name.compare("b") == 0 && target_name.compare("a") == 0) {
   414          EXPECT_TRUE(val == 1 && ts == 3);
   415        } else if (source_name.compare("b") == 0 &&
   416                   target_name.compare("c") == 0) {
   417          EXPECT_TRUE(val == 4 && ts == 4);
   418        } else if (source_name.compare("c") == 0 &&
   419                   target_name.compare("a") == 0) {
   420          EXPECT_TRUE(val == 5 && ts == 5);
   421        }
   422      }
   423    }
   424  }
   425  
   426  TEST(test_algo, remove_cycles_based_on_time_sequence_case2) {
   427    neb::rt::transaction_graph tg2;
   428    tg2.add_edge(neb::to_address("a"), neb::to_address("a"), 1, 1);
   429    tg2.add_edge(neb::to_address("a"), neb::to_address("c"), 2, 3);
   430    tg2.add_edge(neb::to_address("c"), neb::to_address("a"), 3, 2);
   431    tg2.add_edge(neb::to_address("c"), neb::to_address("b"), 4, 4);
   432    tg2.add_edge(neb::to_address("b"), neb::to_address("a"), 5, 5);
   433  
   434    auto graph = tg2.internal_graph();
   435    neb::rt::graph_algo::remove_cycles_based_on_time_sequence(graph);
   436  
   437    neb::rt::transaction_graph::viterator_t vi, vi_end;
   438  
   439    for (boost::tie(vi, vi_end) = boost::vertices(graph); vi != vi_end; vi++) {
   440      neb::rt::transaction_graph::oeiterator_t oei, oei_end;
   441      for (boost::tie(oei, oei_end) = boost::out_edges(*vi, graph);
   442           oei != oei_end; oei++) {
   443        auto source = boost::source(*oei, graph);
   444        auto target = boost::target(*oei, graph);
   445        std::string source_name =
   446            boost::get(boost::vertex_name_t(), graph, source);
   447        std::string target_name =
   448            boost::get(boost::vertex_name_t(), graph, target);
   449  
   450        neb::wei_t val = boost::get(boost::edge_weight_t(), graph, *oei);
   451        int64_t ts = boost::get(boost::edge_timestamp_t(), graph, *oei);
   452        if (source_name.compare("c") == 0 && target_name.compare("a") == 0) {
   453          EXPECT_TRUE(val == 3 && ts == 2);
   454        } else if (source_name.compare("c") == 0 &&
   455                   target_name.compare("b") == 0) {
   456          EXPECT_TRUE(val == 2 && ts == 4);
   457        } else if (source_name.compare("b") == 0 &&
   458                   target_name.compare("a") == 0) {
   459          EXPECT_TRUE(val == 3 && ts == 5);
   460        }
   461      }
   462    }
   463  }
   464  
   465  TEST(test_algo, remove_cycles_based_on_time_sequence_case3) {
   466    neb::rt::transaction_graph tg3;
   467    tg3.add_edge(neb::to_address("a"), neb::to_address("a"), 1, 1);
   468    tg3.add_edge(neb::to_address("a"), neb::to_address("b"), 3, 2);
   469    tg3.add_edge(neb::to_address("b"), neb::to_address("a"), 1, 3);
   470    tg3.add_edge(neb::to_address("b"), neb::to_address("c"), 2, 4);
   471    tg3.add_edge(neb::to_address("c"), neb::to_address("a"), 2, 5);
   472  
   473    auto graph = tg3.internal_graph();
   474    neb::rt::graph_algo::remove_cycles_based_on_time_sequence(graph);
   475  
   476    neb::rt::transaction_graph::viterator_t vi, vi_end;
   477  
   478    for (boost::tie(vi, vi_end) = boost::vertices(graph); vi != vi_end; vi++) {
   479      neb::rt::transaction_graph::oeiterator_t oei, oei_end;
   480      boost::tie(oei, oei_end) = boost::out_edges(*vi, graph);
   481      EXPECT_TRUE(oei == oei_end);
   482    }
   483  }
   484  
   485  TEST(test_algo, remove_cycles_based_on_time_sequence_case4) {
   486    neb::rt::transaction_graph tg4;
   487    tg4.add_edge(neb::to_address("a"), neb::to_address("a"), 1, 1);
   488    tg4.add_edge(neb::to_address("a"), neb::to_address("b"), 2, 2);
   489    tg4.add_edge(neb::to_address("b"), neb::to_address("a"), 3, 1);
   490    tg4.add_edge(neb::to_address("b"), neb::to_address("c"), 2, 3);
   491    tg4.add_edge(neb::to_address("c"), neb::to_address("a"), 1, 4);
   492    tg4.add_edge(neb::to_address("c"), neb::to_address("a"), 2, 4);
   493  
   494    auto graph = tg4.internal_graph();
   495    neb::rt::graph_algo::remove_cycles_based_on_time_sequence(graph);
   496  
   497    neb::rt::transaction_graph::viterator_t vi, vi_end;
   498  
   499    for (boost::tie(vi, vi_end) = boost::vertices(graph); vi != vi_end; vi++) {
   500      neb::rt::transaction_graph::oeiterator_t oei, oei_end;
   501      for (boost::tie(oei, oei_end) = boost::out_edges(*vi, graph);
   502           oei != oei_end; oei++) {
   503        auto source = boost::source(*oei, graph);
   504        auto target = boost::target(*oei, graph);
   505        std::string source_name =
   506            boost::get(boost::vertex_name_t(), graph, source);
   507        std::string target_name =
   508            boost::get(boost::vertex_name_t(), graph, target);
   509  
   510        neb::wei_t val = boost::get(boost::edge_weight_t(), graph, *oei);
   511        int64_t ts = boost::get(boost::edge_timestamp_t(), graph, *oei);
   512        if (source_name.compare("b") == 0 && target_name.compare("a") == 0) {
   513          EXPECT_TRUE(val == 3 && ts == 1);
   514        } else if (source_name.compare("c") == 0 &&
   515                   target_name.compare("a") == 0) {
   516          EXPECT_TRUE(val == 1 && ts == 4);
   517        }
   518      }
   519    }
   520  }
   521  
   522  TEST(test_algo, remove_cycles_based_on_time_sequence_case5) {
   523    neb::rt::transaction_graph tg5;
   524    tg5.add_edge(neb::to_address("a"), neb::to_address("b"), 2, 2);
   525    tg5.add_edge(neb::to_address("b"), neb::to_address("c"), 3, 1);
   526    tg5.add_edge(neb::to_address("c"), neb::to_address("d"), 1, 4);
   527    tg5.add_edge(neb::to_address("d"), neb::to_address("b"), 2, 4);
   528  
   529    auto graph = tg5.internal_graph();
   530    neb::rt::graph_algo::remove_cycles_based_on_time_sequence(graph);
   531  
   532    neb::rt::transaction_graph::viterator_t vi, vi_end;
   533    for (boost::tie(vi, vi_end) = boost::vertices(graph); vi != vi_end; vi++) {
   534      neb::rt::transaction_graph::oeiterator_t oei, oei_end;
   535      for (boost::tie(oei, oei_end) = boost::out_edges(*vi, graph);
   536           oei != oei_end; oei++) {
   537        auto source = boost::source(*oei, graph);
   538        auto target = boost::target(*oei, graph);
   539        std::string source_name =
   540            boost::get(boost::vertex_name_t(), graph, source);
   541        std::string target_name =
   542            boost::get(boost::vertex_name_t(), graph, target);
   543  
   544        neb::wei_t val = boost::get(boost::edge_weight_t(), graph, *oei);
   545        int64_t ts = boost::get(boost::edge_timestamp_t(), graph, *oei);
   546        if (source_name.compare("a") == 0 && target_name.compare("b") == 0) {
   547          EXPECT_TRUE(val == 2 && ts == 2);
   548        } else if (source_name.compare("b") == 0 &&
   549                   target_name.compare("c") == 0) {
   550          EXPECT_TRUE(val == 3 && ts == 1);
   551        } else if (source_name.compare("c") == 0 &&
   552                   target_name.compare("d") == 0) {
   553          EXPECT_TRUE(val == 1 && ts == 4);
   554        } else if (source_name.compare("d") == 0 &&
   555                   target_name.compare("b") == 0) {
   556          EXPECT_TRUE(val == 2 && ts == 4);
   557        }
   558      }
   559    }
   560  }
   561  
   562  TEST(test_algo, remove_cycles_based_on_time_sequence_case6) {
   563    neb::rt::transaction_graph tg6;
   564    char cc = 'b';
   565    int32_t n = 3;
   566    for (char ch = 'a'; ch < cc; ch++) {
   567      for (int32_t i = 0; i < n; i++) {
   568        tg6.add_edge(neb::to_address(std::string(1, ch)),
   569                     neb::to_address(std::string(1, ch + 1)), ch - 'a' + 1,
   570                     ch - 'a' + 1);
   571      }
   572    }
   573    for (int32_t i = 0; i < n; i++) {
   574      tg6.add_edge(neb::to_address(std::string(1, cc)),
   575                   neb::to_address(std::string(1, 'a')), cc - 'a' + 1,
   576                   cc - 'a' + 1);
   577    }
   578  
   579    auto graph = tg6.internal_graph();
   580    neb::rt::graph_algo::remove_cycles_based_on_time_sequence(graph);
   581  
   582    neb::rt::transaction_graph::viterator_t vi, vi_end;
   583    for (boost::tie(vi, vi_end) = boost::vertices(graph); vi != vi_end; vi++) {
   584      neb::rt::transaction_graph::oeiterator_t oei, oei_end;
   585      for (boost::tie(oei, oei_end) = boost::out_edges(*vi, graph);
   586           oei != oei_end; oei++) {
   587        auto source = boost::source(*oei, graph);
   588        auto target = boost::target(*oei, graph);
   589        std::string source_name =
   590            boost::get(boost::vertex_name_t(), graph, source);
   591        std::string target_name =
   592            boost::get(boost::vertex_name_t(), graph, target);
   593        EXPECT_EQ(source_name, "b");
   594        EXPECT_EQ(target_name, "a");
   595  
   596        neb::wei_t val = boost::get(boost::edge_weight_t(), graph, *oei);
   597        LOG(INFO) << val;
   598        int64_t ts = boost::get(boost::edge_timestamp_t(), graph, *oei);
   599        EXPECT_EQ(ts, 2);
   600      }
   601    }
   602  }
   603