test/suurballe_test.cc
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 15 Mar 2011 19:32:21 +0100
changeset 1047 ddd3c0d3d9bf
parent 932 9f6ed854d409
child 1173 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.
alpar@463
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
alpar@357
     2
 *
alpar@463
     3
 * This file is a part of LEMON, a generic C++ optimization library.
alpar@357
     4
 *
alpar@956
     5
 * Copyright (C) 2003-2010
alpar@357
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@357
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@357
     8
 *
alpar@357
     9
 * Permission to use, modify and distribute this software is granted
alpar@357
    10
 * provided that this copyright notice appears in all copies. For
alpar@357
    11
 * precise terms see the accompanying LICENSE file.
alpar@357
    12
 *
alpar@357
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@357
    14
 * express or implied, and with no claim as to its suitability for any
alpar@357
    15
 * purpose.
alpar@357
    16
 *
alpar@357
    17
 */
alpar@357
    18
alpar@357
    19
#include <iostream>
alpar@357
    20
alpar@357
    21
#include <lemon/list_graph.h>
alpar@357
    22
#include <lemon/lgf_reader.h>
alpar@357
    23
#include <lemon/path.h>
alpar@357
    24
#include <lemon/suurballe.h>
kpeter@670
    25
#include <lemon/concepts/digraph.h>
kpeter@931
    26
#include <lemon/concepts/heap.h>
alpar@357
    27
alpar@357
    28
#include "test_tools.h"
alpar@357
    29
alpar@357
    30
using namespace lemon;
alpar@357
    31
alpar@442
    32
char test_lgf[] =
alpar@442
    33
  "@nodes\n"
kpeter@670
    34
  "label\n"
kpeter@670
    35
  "1\n"
kpeter@670
    36
  "2\n"
kpeter@670
    37
  "3\n"
kpeter@670
    38
  "4\n"
kpeter@670
    39
  "5\n"
kpeter@670
    40
  "6\n"
kpeter@670
    41
  "7\n"
kpeter@670
    42
  "8\n"
kpeter@670
    43
  "9\n"
kpeter@670
    44
  "10\n"
kpeter@670
    45
  "11\n"
kpeter@670
    46
  "12\n"
alpar@442
    47
  "@arcs\n"
kpeter@670
    48
  "      length\n"
kpeter@670
    49
  " 1  2  70\n"
kpeter@670
    50
  " 1  3 150\n"
kpeter@670
    51
  " 1  4  80\n"
kpeter@670
    52
  " 2  8  80\n"
kpeter@670
    53
  " 3  5 140\n"
kpeter@670
    54
  " 4  6  60\n"
kpeter@670
    55
  " 4  7  80\n"
kpeter@670
    56
  " 4  8 110\n"
kpeter@670
    57
  " 5  7  60\n"
kpeter@670
    58
  " 5 11 120\n"
kpeter@670
    59
  " 6  3   0\n"
kpeter@670
    60
  " 6  9 140\n"
kpeter@670
    61
  " 6 10  90\n"
kpeter@670
    62
  " 7  1  30\n"
kpeter@670
    63
  " 8 12  60\n"
kpeter@670
    64
  " 9 12  50\n"
kpeter@670
    65
  "10 12  70\n"
kpeter@670
    66
  "10  2 100\n"
kpeter@670
    67
  "10  7  60\n"
kpeter@670
    68
  "11 10  20\n"
kpeter@670
    69
  "12 11  30\n"
alpar@442
    70
  "@attributes\n"
alpar@442
    71
  "source  1\n"
alpar@442
    72
  "target 12\n"
alpar@442
    73
  "@end\n";
alpar@442
    74
kpeter@670
    75
// Check the interface of Suurballe
kpeter@670
    76
void checkSuurballeCompile()
kpeter@670
    77
{
kpeter@670
    78
  typedef int VType;
kpeter@670
    79
  typedef concepts::Digraph Digraph;
kpeter@670
    80
kpeter@670
    81
  typedef Digraph::Node Node;
kpeter@670
    82
  typedef Digraph::Arc Arc;
kpeter@670
    83
  typedef concepts::ReadMap<Arc, VType> LengthMap;
alpar@956
    84
kpeter@931
    85
  typedef Suurballe<Digraph, LengthMap> ST;
kpeter@931
    86
  typedef Suurballe<Digraph, LengthMap>
kpeter@931
    87
    ::SetFlowMap<ST::FlowMap>
kpeter@931
    88
    ::SetPotentialMap<ST::PotentialMap>
kpeter@931
    89
    ::SetPath<SimplePath<Digraph> >
kpeter@931
    90
    ::SetHeap<concepts::Heap<VType, Digraph::NodeMap<int> > >
kpeter@931
    91
    ::Create SuurballeType;
kpeter@670
    92
kpeter@670
    93
  Digraph g;
kpeter@670
    94
  Node n;
kpeter@670
    95
  Arc e;
kpeter@670
    96
  LengthMap len;
kpeter@670
    97
  SuurballeType::FlowMap flow(g);
kpeter@670
    98
  SuurballeType::PotentialMap pi(g);
kpeter@670
    99
kpeter@670
   100
  SuurballeType suurb_test(g, len);
kpeter@670
   101
  const SuurballeType& const_suurb_test = suurb_test;
kpeter@670
   102
kpeter@670
   103
  suurb_test
kpeter@670
   104
    .flowMap(flow)
kpeter@670
   105
    .potentialMap(pi);
kpeter@670
   106
kpeter@670
   107
  int k;
kpeter@670
   108
  k = suurb_test.run(n, n);
kpeter@670
   109
  k = suurb_test.run(n, n, k);
kpeter@670
   110
  suurb_test.init(n);
kpeter@927
   111
  suurb_test.fullInit(n);
kpeter@927
   112
  suurb_test.start(n);
kpeter@927
   113
  suurb_test.start(n, k);
kpeter@670
   114
  k = suurb_test.findFlow(n);
kpeter@670
   115
  k = suurb_test.findFlow(n, k);
kpeter@670
   116
  suurb_test.findPaths();
alpar@956
   117
kpeter@670
   118
  int f;
kpeter@670
   119
  VType c;
kpeter@670
   120
  c = const_suurb_test.totalLength();
kpeter@670
   121
  f = const_suurb_test.flow(e);
kpeter@670
   122
  const SuurballeType::FlowMap& fm =
kpeter@670
   123
    const_suurb_test.flowMap();
kpeter@670
   124
  c = const_suurb_test.potential(n);
kpeter@670
   125
  const SuurballeType::PotentialMap& pm =
kpeter@670
   126
    const_suurb_test.potentialMap();
kpeter@670
   127
  k = const_suurb_test.pathNum();
kpeter@670
   128
  Path<Digraph> p = const_suurb_test.path(k);
alpar@956
   129
kpeter@670
   130
  ignore_unused_variable_warning(fm);
kpeter@670
   131
  ignore_unused_variable_warning(pm);
kpeter@670
   132
}
kpeter@670
   133
kpeter@358
   134
// Check the feasibility of the flow
alpar@357
   135
template <typename Digraph, typename FlowMap>
alpar@463
   136
bool checkFlow( const Digraph& gr, const FlowMap& flow,
alpar@357
   137
                typename Digraph::Node s, typename Digraph::Node t,
alpar@357
   138
                int value )
alpar@357
   139
{
alpar@357
   140
  TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
alpar@357
   141
  for (ArcIt e(gr); e != INVALID; ++e)
alpar@357
   142
    if (!(flow[e] == 0 || flow[e] == 1)) return false;
alpar@357
   143
alpar@357
   144
  for (NodeIt n(gr); n != INVALID; ++n) {
alpar@357
   145
    int sum = 0;
alpar@357
   146
    for (OutArcIt e(gr, n); e != INVALID; ++e)
alpar@357
   147
      sum += flow[e];
alpar@357
   148
    for (InArcIt e(gr, n); e != INVALID; ++e)
alpar@357
   149
      sum -= flow[e];
alpar@357
   150
    if (n == s && sum != value) return false;
alpar@357
   151
    if (n == t && sum != -value) return false;
alpar@357
   152
    if (n != s && n != t && sum != 0) return false;
alpar@357
   153
  }
alpar@357
   154
alpar@357
   155
  return true;
alpar@357
   156
}
alpar@357
   157
kpeter@358
   158
// Check the optimalitiy of the flow
alpar@463
   159
template < typename Digraph, typename CostMap,
alpar@357
   160
           typename FlowMap, typename PotentialMap >
alpar@357
   161
bool checkOptimality( const Digraph& gr, const CostMap& cost,
alpar@357
   162
                      const FlowMap& flow, const PotentialMap& pi )
alpar@357
   163
{
kpeter@358
   164
  // Check the "Complementary Slackness" optimality condition
alpar@357
   165
  TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
alpar@357
   166
  bool opt = true;
alpar@357
   167
  for (ArcIt e(gr); e != INVALID; ++e) {
alpar@357
   168
    typename CostMap::Value red_cost =
alpar@357
   169
      cost[e] + pi[gr.source(e)] - pi[gr.target(e)];
alpar@357
   170
    opt = (flow[e] == 0 && red_cost >= 0) ||
alpar@357
   171
          (flow[e] == 1 && red_cost <= 0);
alpar@357
   172
    if (!opt) break;
alpar@357
   173
  }
alpar@357
   174
  return opt;
alpar@357
   175
}
alpar@357
   176
kpeter@358
   177
// Check a path
kpeter@358
   178
template <typename Digraph, typename Path>
alpar@357
   179
bool checkPath( const Digraph& gr, const Path& path,
alpar@357
   180
                typename Digraph::Node s, typename Digraph::Node t)
alpar@357
   181
{
alpar@357
   182
  TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
alpar@357
   183
  Node n = s;
alpar@357
   184
  for (int i = 0; i < path.length(); ++i) {
alpar@357
   185
    if (gr.source(path.nth(i)) != n) return false;
alpar@357
   186
    n = gr.target(path.nth(i));
alpar@357
   187
  }
alpar@357
   188
  return n == t;
alpar@357
   189
}
alpar@357
   190
alpar@357
   191
alpar@357
   192
int main()
alpar@357
   193
{
alpar@357
   194
  DIGRAPH_TYPEDEFS(ListDigraph);
alpar@357
   195
kpeter@358
   196
  // Read the test digraph
alpar@357
   197
  ListDigraph digraph;
alpar@357
   198
  ListDigraph::ArcMap<int> length(digraph);
kpeter@670
   199
  Node s, t;
alpar@357
   200
alpar@442
   201
  std::istringstream input(test_lgf);
alpar@357
   202
  DigraphReader<ListDigraph>(digraph, input).
kpeter@670
   203
    arcMap("length", length).
kpeter@670
   204
    node("source", s).
kpeter@670
   205
    node("target", t).
alpar@357
   206
    run();
alpar@463
   207
kpeter@932
   208
  // Check run()
alpar@357
   209
  {
kpeter@670
   210
    Suurballe<ListDigraph> suurballe(digraph, length);
alpar@956
   211
kpeter@932
   212
    // Find 2 paths
kpeter@670
   213
    check(suurballe.run(s, t) == 2, "Wrong number of paths");
kpeter@670
   214
    check(checkFlow(digraph, suurballe.flowMap(), s, t, 2),
alpar@357
   215
          "The flow is not feasible");
alpar@357
   216
    check(suurballe.totalLength() == 510, "The flow is not optimal");
alpar@463
   217
    check(checkOptimality(digraph, length, suurballe.flowMap(),
alpar@357
   218
                          suurballe.potentialMap()),
alpar@357
   219
          "Wrong potentials");
alpar@357
   220
    for (int i = 0; i < suurballe.pathNum(); ++i)
kpeter@670
   221
      check(checkPath(digraph, suurballe.path(i), s, t), "Wrong path");
alpar@956
   222
kpeter@932
   223
    // Find 3 paths
kpeter@670
   224
    check(suurballe.run(s, t, 3) == 3, "Wrong number of paths");
kpeter@670
   225
    check(checkFlow(digraph, suurballe.flowMap(), s, t, 3),
alpar@357
   226
          "The flow is not feasible");
alpar@357
   227
    check(suurballe.totalLength() == 1040, "The flow is not optimal");
alpar@463
   228
    check(checkOptimality(digraph, length, suurballe.flowMap(),
alpar@357
   229
                          suurballe.potentialMap()),
alpar@357
   230
          "Wrong potentials");
alpar@357
   231
    for (int i = 0; i < suurballe.pathNum(); ++i)
kpeter@670
   232
      check(checkPath(digraph, suurballe.path(i), s, t), "Wrong path");
alpar@956
   233
kpeter@932
   234
    // Find 5 paths (only 3 can be found)
kpeter@670
   235
    check(suurballe.run(s, t, 5) == 3, "Wrong number of paths");
kpeter@670
   236
    check(checkFlow(digraph, suurballe.flowMap(), s, t, 3),
alpar@357
   237
          "The flow is not feasible");
alpar@357
   238
    check(suurballe.totalLength() == 1040, "The flow is not optimal");
alpar@463
   239
    check(checkOptimality(digraph, length, suurballe.flowMap(),
alpar@357
   240
                          suurballe.potentialMap()),
alpar@357
   241
          "Wrong potentials");
alpar@357
   242
    for (int i = 0; i < suurballe.pathNum(); ++i)
kpeter@670
   243
      check(checkPath(digraph, suurballe.path(i), s, t), "Wrong path");
alpar@357
   244
  }
alpar@956
   245
kpeter@932
   246
  // Check fullInit() + start()
kpeter@932
   247
  {
kpeter@932
   248
    Suurballe<ListDigraph> suurballe(digraph, length);
kpeter@932
   249
    suurballe.fullInit(s);
alpar@956
   250
kpeter@932
   251
    // Find 2 paths
kpeter@932
   252
    check(suurballe.start(t) == 2, "Wrong number of paths");
kpeter@932
   253
    check(suurballe.totalLength() == 510, "The flow is not optimal");
kpeter@932
   254
kpeter@932
   255
    // Find 3 paths
kpeter@932
   256
    check(suurballe.start(t, 3) == 3, "Wrong number of paths");
kpeter@932
   257
    check(suurballe.totalLength() == 1040, "The flow is not optimal");
kpeter@932
   258
kpeter@932
   259
    // Find 5 paths (only 3 can be found)
kpeter@932
   260
    check(suurballe.start(t, 5) == 3, "Wrong number of paths");
kpeter@932
   261
    check(suurballe.totalLength() == 1040, "The flow is not optimal");
kpeter@932
   262
  }
alpar@357
   263
alpar@357
   264
  return 0;
alpar@357
   265
}