test/min_cost_arborescence_test.cc
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 15 Mar 2011 19:32:21 +0100
changeset 936 ddd3c0d3d9bf
parent 625 029a48052c67
child 1008 d216e1c8b3fa
permissions -rw-r--r--
Implement the scaling Price Refinement heuristic in CostScaling (#417)
instead of Early Termination.

These two heuristics are similar, but the newer one is faster
and not only makes it possible to skip some epsilon phases, but
it can improve the performance of the other phases, as well.
     1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library.
     4  *
     5  * Copyright (C) 2003-2010
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     9  * Permission to use, modify and distribute this software is granted
    10  * provided that this copyright notice appears in all copies. For
    11  * precise terms see the accompanying LICENSE file.
    12  *
    13  * This software is provided "AS IS" with no warranty of any kind,
    14  * express or implied, and with no claim as to its suitability for any
    15  * purpose.
    16  *
    17  */
    18 
    19 #include <iostream>
    20 #include <set>
    21 #include <vector>
    22 #include <iterator>
    23 
    24 #include <lemon/smart_graph.h>
    25 #include <lemon/min_cost_arborescence.h>
    26 #include <lemon/lgf_reader.h>
    27 #include <lemon/concepts/digraph.h>
    28 
    29 #include "test_tools.h"
    30 
    31 using namespace lemon;
    32 using namespace std;
    33 
    34 const char test_lgf[] =
    35   "@nodes\n"
    36   "label\n"
    37   "0\n"
    38   "1\n"
    39   "2\n"
    40   "3\n"
    41   "4\n"
    42   "5\n"
    43   "6\n"
    44   "7\n"
    45   "8\n"
    46   "9\n"
    47   "@arcs\n"
    48   "     label  cost\n"
    49   "1 8  0      107\n"
    50   "0 3  1      70\n"
    51   "2 1  2      46\n"
    52   "4 1  3      28\n"
    53   "4 4  4      91\n"
    54   "3 9  5      76\n"
    55   "9 8  6      61\n"
    56   "8 1  7      39\n"
    57   "9 8  8      74\n"
    58   "8 0  9      39\n"
    59   "4 3  10     45\n"
    60   "2 2  11     34\n"
    61   "0 1  12     100\n"
    62   "6 3  13     95\n"
    63   "4 1  14     22\n"
    64   "1 1  15     31\n"
    65   "7 2  16     51\n"
    66   "2 6  17     29\n"
    67   "8 3  18     115\n"
    68   "6 9  19     32\n"
    69   "1 1  20     60\n"
    70   "0 3  21     40\n"
    71   "@attributes\n"
    72   "source 0\n";
    73 
    74 
    75 void checkMinCostArborescenceCompile()
    76 {
    77   typedef double VType;
    78   typedef concepts::Digraph Digraph;
    79   typedef concepts::ReadMap<Digraph::Arc, VType> CostMap;
    80   typedef Digraph::Node Node;
    81   typedef Digraph::Arc Arc;
    82   typedef concepts::WriteMap<Digraph::Arc, bool> ArbMap;
    83   typedef concepts::ReadWriteMap<Digraph::Node, Digraph::Arc> PredMap;
    84 
    85   typedef MinCostArborescence<Digraph, CostMap>::
    86             SetArborescenceMap<ArbMap>::
    87             SetPredMap<PredMap>::Create MinCostArbType;
    88 
    89   Digraph g;
    90   Node s, n;
    91   Arc e;
    92   VType c;
    93   bool b;
    94   int i;
    95   CostMap cost;
    96   ArbMap arb;
    97   PredMap pred;
    98 
    99   MinCostArbType mcarb_test(g, cost);
   100   const MinCostArbType& const_mcarb_test = mcarb_test;
   101 
   102   mcarb_test
   103     .arborescenceMap(arb)
   104     .predMap(pred)
   105     .run(s);
   106 
   107   mcarb_test.init();
   108   mcarb_test.addSource(s);
   109   mcarb_test.start();
   110   n = mcarb_test.processNextNode();
   111   b = const_mcarb_test.emptyQueue();
   112   i = const_mcarb_test.queueSize();
   113 
   114   c = const_mcarb_test.arborescenceCost();
   115   b = const_mcarb_test.arborescence(e);
   116   e = const_mcarb_test.pred(n);
   117   const MinCostArbType::ArborescenceMap &am =
   118     const_mcarb_test.arborescenceMap();
   119   const MinCostArbType::PredMap &pm =
   120     const_mcarb_test.predMap();
   121   b = const_mcarb_test.reached(n);
   122   b = const_mcarb_test.processed(n);
   123 
   124   i = const_mcarb_test.dualNum();
   125   c = const_mcarb_test.dualValue();
   126   i = const_mcarb_test.dualSize(i);
   127   c = const_mcarb_test.dualValue(i);
   128 
   129   ignore_unused_variable_warning(am);
   130   ignore_unused_variable_warning(pm);
   131 }
   132 
   133 int main() {
   134   typedef SmartDigraph Digraph;
   135   DIGRAPH_TYPEDEFS(Digraph);
   136 
   137   typedef Digraph::ArcMap<double> CostMap;
   138 
   139   Digraph digraph;
   140   CostMap cost(digraph);
   141   Node source;
   142 
   143   std::istringstream is(test_lgf);
   144   digraphReader(digraph, is).
   145     arcMap("cost", cost).
   146     node("source", source).run();
   147 
   148   MinCostArborescence<Digraph, CostMap> mca(digraph, cost);
   149   mca.run(source);
   150 
   151   vector<pair<double, set<Node> > > dualSolution(mca.dualNum());
   152 
   153   for (int i = 0; i < mca.dualNum(); ++i) {
   154     dualSolution[i].first = mca.dualValue(i);
   155     for (MinCostArborescence<Digraph, CostMap>::DualIt it(mca, i);
   156          it != INVALID; ++it) {
   157       dualSolution[i].second.insert(it);
   158     }
   159   }
   160 
   161   for (ArcIt it(digraph); it != INVALID; ++it) {
   162     if (mca.reached(digraph.source(it))) {
   163       double sum = 0.0;
   164       for (int i = 0; i < int(dualSolution.size()); ++i) {
   165         if (dualSolution[i].second.find(digraph.target(it))
   166             != dualSolution[i].second.end() &&
   167             dualSolution[i].second.find(digraph.source(it))
   168             == dualSolution[i].second.end()) {
   169           sum += dualSolution[i].first;
   170         }
   171       }
   172       if (mca.arborescence(it)) {
   173         check(sum == cost[it], "Invalid dual solution");
   174       }
   175       check(sum <= cost[it], "Invalid dual solution");
   176     }
   177   }
   178 
   179 
   180   check(mca.dualValue() == mca.arborescenceCost(), "Invalid dual solution");
   181 
   182   check(mca.reached(source), "Invalid arborescence");
   183   for (ArcIt a(digraph); a != INVALID; ++a) {
   184     check(!mca.reached(digraph.source(a)) ||
   185           mca.reached(digraph.target(a)), "Invalid arborescence");
   186   }
   187 
   188   for (NodeIt n(digraph); n != INVALID; ++n) {
   189     if (!mca.reached(n)) continue;
   190     int cnt = 0;
   191     for (InArcIt a(digraph, n); a != INVALID; ++a) {
   192       if (mca.arborescence(a)) {
   193         check(mca.pred(n) == a, "Invalid arborescence");
   194         ++cnt;
   195       }
   196     }
   197     check((n == source ? cnt == 0 : cnt == 1), "Invalid arborescence");
   198   }
   199 
   200   Digraph::ArcMap<bool> arborescence(digraph);
   201   check(mca.arborescenceCost() ==
   202         minCostArborescence(digraph, cost, source, arborescence),
   203         "Wrong result of the function interface");
   204 
   205   return 0;
   206 }