test/min_cost_arborescence_test.cc
author Balazs Dezso <deba@inf.elte.hu>
Thu, 24 Jun 2010 09:27:53 +0200
changeset 891 bb70ad62c95f
parent 501 7f8560cb9d65
child 877 141f9c0db4a3
child 1007 7e368d9b67f7
permissions -rw-r--r--
Fix critical bug in preflow (#372)

The wrong transition between the bound decrease and highest active
heuristics caused the bug. The last node chosen in bound decrease mode
is used in the first iteration in highest active mode.
     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-2008
     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 }