test/suurballe_test.cc
changeset 357 2f64c4a692a8
child 358 7f26c4b32651
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/test/suurballe_test.cc	Tue Oct 28 18:39:53 2008 +0000
     1.3 @@ -0,0 +1,160 @@
     1.4 +/* -*- C++ -*-
     1.5 + *
     1.6 + * This file is a part of LEMON, a generic C++ optimization library
     1.7 + *
     1.8 + * Copyright (C) 2003-2008
     1.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
    1.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
    1.11 + *
    1.12 + * Permission to use, modify and distribute this software is granted
    1.13 + * provided that this copyright notice appears in all copies. For
    1.14 + * precise terms see the accompanying LICENSE file.
    1.15 + *
    1.16 + * This software is provided "AS IS" with no warranty of any kind,
    1.17 + * express or implied, and with no claim as to its suitability for any
    1.18 + * purpose.
    1.19 + *
    1.20 + */
    1.21 +
    1.22 +#include <iostream>
    1.23 +#include <fstream>
    1.24 +
    1.25 +#include <lemon/list_graph.h>
    1.26 +#include <lemon/lgf_reader.h>
    1.27 +#include <lemon/path.h>
    1.28 +#include <lemon/suurballe.h>
    1.29 +
    1.30 +#include "test_tools.h"
    1.31 +
    1.32 +using namespace lemon;
    1.33 +
    1.34 +// Checks the feasibility of the flow
    1.35 +template <typename Digraph, typename FlowMap>
    1.36 +bool checkFlow( const Digraph& gr, const FlowMap& flow, 
    1.37 +                typename Digraph::Node s, typename Digraph::Node t,
    1.38 +                int value )
    1.39 +{
    1.40 +  TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
    1.41 +  for (ArcIt e(gr); e != INVALID; ++e)
    1.42 +    if (!(flow[e] == 0 || flow[e] == 1)) return false;
    1.43 +
    1.44 +  for (NodeIt n(gr); n != INVALID; ++n) {
    1.45 +    int sum = 0;
    1.46 +    for (OutArcIt e(gr, n); e != INVALID; ++e)
    1.47 +      sum += flow[e];
    1.48 +    for (InArcIt e(gr, n); e != INVALID; ++e)
    1.49 +      sum -= flow[e];
    1.50 +    if (n == s && sum != value) return false;
    1.51 +    if (n == t && sum != -value) return false;
    1.52 +    if (n != s && n != t && sum != 0) return false;
    1.53 +  }
    1.54 +
    1.55 +  return true;
    1.56 +}
    1.57 +
    1.58 +// Checks the optimalitiy of the flow
    1.59 +template < typename Digraph, typename CostMap, 
    1.60 +           typename FlowMap, typename PotentialMap >
    1.61 +bool checkOptimality( const Digraph& gr, const CostMap& cost,
    1.62 +                      const FlowMap& flow, const PotentialMap& pi )
    1.63 +{
    1.64 +  // Checking the Complementary Slackness optimality condition
    1.65 +  TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
    1.66 +  bool opt = true;
    1.67 +  for (ArcIt e(gr); e != INVALID; ++e) {
    1.68 +    typename CostMap::Value red_cost =
    1.69 +      cost[e] + pi[gr.source(e)] - pi[gr.target(e)];
    1.70 +    opt = (flow[e] == 0 && red_cost >= 0) ||
    1.71 +          (flow[e] == 1 && red_cost <= 0);
    1.72 +    if (!opt) break;
    1.73 +  }
    1.74 +  return opt;
    1.75 +}
    1.76 +
    1.77 +// Checks a path
    1.78 +template < typename Digraph, typename Path >
    1.79 +bool checkPath( const Digraph& gr, const Path& path,
    1.80 +                typename Digraph::Node s, typename Digraph::Node t)
    1.81 +{
    1.82 +  // Checking the Complementary Slackness optimality condition
    1.83 +  TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
    1.84 +  Node n = s;
    1.85 +  for (int i = 0; i < path.length(); ++i) {
    1.86 +    if (gr.source(path.nth(i)) != n) return false;
    1.87 +    n = gr.target(path.nth(i));
    1.88 +  }
    1.89 +  return n == t;
    1.90 +}
    1.91 +
    1.92 +
    1.93 +int main()
    1.94 +{
    1.95 +  DIGRAPH_TYPEDEFS(ListDigraph);
    1.96 +
    1.97 +  // Reading the test digraph
    1.98 +  ListDigraph digraph;
    1.99 +  ListDigraph::ArcMap<int> length(digraph);
   1.100 +  Node source, target;
   1.101 +
   1.102 +  std::string fname;
   1.103 +  if(getenv("srcdir"))
   1.104 +    fname = std::string(getenv("srcdir"));
   1.105 +  else fname = ".";
   1.106 +  fname += "/test/min_cost_flow_test.lgf";
   1.107 +
   1.108 +  std::ifstream input(fname.c_str());
   1.109 +  check(input, "Input file '" << fname << "' not found");
   1.110 +  DigraphReader<ListDigraph>(digraph, input).
   1.111 +    arcMap("cost", length).
   1.112 +    node("source", source).
   1.113 +    node("target", target).
   1.114 +    run();
   1.115 +  input.close();
   1.116 +  
   1.117 +  // Finding 2 paths
   1.118 +  {
   1.119 +    Suurballe<ListDigraph> suurballe(digraph, length, source, target);
   1.120 +    check(suurballe.run(2) == 2, "Wrong number of paths");
   1.121 +    check(checkFlow(digraph, suurballe.flowMap(), source, target, 2),
   1.122 +          "The flow is not feasible");
   1.123 +    check(suurballe.totalLength() == 510, "The flow is not optimal");
   1.124 +    check(checkOptimality(digraph, length, suurballe.flowMap(), 
   1.125 +                          suurballe.potentialMap()),
   1.126 +          "Wrong potentials");
   1.127 +    for (int i = 0; i < suurballe.pathNum(); ++i)
   1.128 +      check(checkPath(digraph, suurballe.path(i), source, target),
   1.129 +            "Wrong path");
   1.130 +  }
   1.131 +
   1.132 +  // Finding 3 paths
   1.133 +  {
   1.134 +    Suurballe<ListDigraph> suurballe(digraph, length, source, target);
   1.135 +    check(suurballe.run(3) == 3, "Wrong number of paths");
   1.136 +    check(checkFlow(digraph, suurballe.flowMap(), source, target, 3),
   1.137 +          "The flow is not feasible");
   1.138 +    check(suurballe.totalLength() == 1040, "The flow is not optimal");
   1.139 +    check(checkOptimality(digraph, length, suurballe.flowMap(), 
   1.140 +                          suurballe.potentialMap()),
   1.141 +          "Wrong potentials");
   1.142 +    for (int i = 0; i < suurballe.pathNum(); ++i)
   1.143 +      check(checkPath(digraph, suurballe.path(i), source, target),
   1.144 +            "Wrong path");
   1.145 +  }
   1.146 +
   1.147 +  // Finding 5 paths (only 3 can be found)
   1.148 +  {
   1.149 +    Suurballe<ListDigraph> suurballe(digraph, length, source, target);
   1.150 +    check(suurballe.run(5) == 3, "Wrong number of paths");
   1.151 +    check(checkFlow(digraph, suurballe.flowMap(), source, target, 3),
   1.152 +          "The flow is not feasible");
   1.153 +    check(suurballe.totalLength() == 1040, "The flow is not optimal");
   1.154 +    check(checkOptimality(digraph, length, suurballe.flowMap(), 
   1.155 +                          suurballe.potentialMap()),
   1.156 +          "Wrong potentials");
   1.157 +    for (int i = 0; i < suurballe.pathNum(); ++i)
   1.158 +      check(checkPath(digraph, suurballe.path(i), source, target),
   1.159 +            "Wrong path");
   1.160 +  }
   1.161 +
   1.162 +  return 0;
   1.163 +}