gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Merge
0 3 0
merge default
1 file changed with 32 insertions and 18 deletions:
↑ Collapse diff ↑
Ignore white space 256 line context
... ...
@@ -1022,314 +1022,315 @@
1022 1022
    ///
1023 1023
    /// \pre \ref run() must be called before using this function.
1024 1024
    Flow flow(const Arc& a) const {
1025 1025
      return (*_flow_map)[a];
1026 1026
    }
1027 1027

	
1028 1028
    /// \brief Return a const reference to the flow map.
1029 1029
    ///
1030 1030
    /// This function returns a const reference to an arc map storing
1031 1031
    /// the found flow.
1032 1032
    ///
1033 1033
    /// \pre \ref run() must be called before using this function.
1034 1034
    const FlowMap& flowMap() const {
1035 1035
      return *_flow_map;
1036 1036
    }
1037 1037

	
1038 1038
    /// \brief Return the potential (dual value) of the given node.
1039 1039
    ///
1040 1040
    /// This function returns the potential (dual value) of the
1041 1041
    /// given node.
1042 1042
    ///
1043 1043
    /// \pre \ref run() must be called before using this function.
1044 1044
    Cost potential(const Node& n) const {
1045 1045
      return (*_potential_map)[n];
1046 1046
    }
1047 1047

	
1048 1048
    /// \brief Return a const reference to the potential map
1049 1049
    /// (the dual solution).
1050 1050
    ///
1051 1051
    /// This function returns a const reference to a node map storing
1052 1052
    /// the found potentials, which form the dual solution of the
1053 1053
    /// \ref min_cost_flow "minimum cost flow" problem.
1054 1054
    ///
1055 1055
    /// \pre \ref run() must be called before using this function.
1056 1056
    const PotentialMap& potentialMap() const {
1057 1057
      return *_potential_map;
1058 1058
    }
1059 1059

	
1060 1060
    /// @}
1061 1061

	
1062 1062
  private:
1063 1063

	
1064 1064
    // Initialize internal data structures
1065 1065
    bool init() {
1066 1066
      // Initialize result maps
1067 1067
      if (!_flow_map) {
1068 1068
        _flow_map = new FlowMap(_graph);
1069 1069
        _local_flow = true;
1070 1070
      }
1071 1071
      if (!_potential_map) {
1072 1072
        _potential_map = new PotentialMap(_graph);
1073 1073
        _local_potential = true;
1074 1074
      }
1075 1075

	
1076 1076
      // Initialize vectors
1077 1077
      _node_num = countNodes(_graph);
1078 1078
      _arc_num = countArcs(_graph);
1079 1079
      int all_node_num = _node_num + 1;
1080 1080
      int all_arc_num = _arc_num + _node_num;
1081 1081
      if (_node_num == 0) return false;
1082 1082

	
1083 1083
      _arc_ref.resize(_arc_num);
1084 1084
      _source.resize(all_arc_num);
1085 1085
      _target.resize(all_arc_num);
1086 1086

	
1087 1087
      _cap.resize(all_arc_num);
1088 1088
      _cost.resize(all_arc_num);
1089 1089
      _supply.resize(all_node_num);
1090 1090
      _flow.resize(all_arc_num);
1091 1091
      _pi.resize(all_node_num);
1092 1092

	
1093 1093
      _parent.resize(all_node_num);
1094 1094
      _pred.resize(all_node_num);
1095 1095
      _forward.resize(all_node_num);
1096 1096
      _thread.resize(all_node_num);
1097 1097
      _rev_thread.resize(all_node_num);
1098 1098
      _succ_num.resize(all_node_num);
1099 1099
      _last_succ.resize(all_node_num);
1100 1100
      _state.resize(all_arc_num);
1101 1101

	
1102 1102
      // Initialize node related data
1103 1103
      bool valid_supply = true;
1104 1104
      Flow sum_supply = 0;
1105 1105
      if (!_pstsup && !_psupply) {
1106 1106
        _pstsup = true;
1107 1107
        _psource = _ptarget = NodeIt(_graph);
1108 1108
        _pstflow = 0;
1109 1109
      }
1110 1110
      if (_psupply) {
1111 1111
        int i = 0;
1112 1112
        for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
1113 1113
          _node_id[n] = i;
1114 1114
          _supply[i] = (*_psupply)[n];
1115 1115
          sum_supply += _supply[i];
1116 1116
        }
1117 1117
        valid_supply = (_ptype == GEQ && sum_supply <= 0) ||
1118 1118
                       (_ptype == LEQ && sum_supply >= 0);
1119 1119
      } else {
1120 1120
        int i = 0;
1121 1121
        for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
1122 1122
          _node_id[n] = i;
1123 1123
          _supply[i] = 0;
1124 1124
        }
1125 1125
        _supply[_node_id[_psource]] =  _pstflow;
1126 1126
        _supply[_node_id[_ptarget]] = -_pstflow;
1127 1127
      }
1128 1128
      if (!valid_supply) return false;
1129 1129

	
1130 1130
      // Infinite capacity value
1131 1131
      Flow inf_cap =
1132 1132
        std::numeric_limits<Flow>::has_infinity ?
1133 1133
        std::numeric_limits<Flow>::infinity() :
1134 1134
        std::numeric_limits<Flow>::max();
1135 1135

	
1136 1136
      // Initialize artifical cost
1137 1137
      Cost art_cost;
1138 1138
      if (std::numeric_limits<Cost>::is_exact) {
1139 1139
        art_cost = std::numeric_limits<Cost>::max() / 4 + 1;
1140 1140
      } else {
1141 1141
        art_cost = std::numeric_limits<Cost>::min();
1142 1142
        for (int i = 0; i != _arc_num; ++i) {
1143 1143
          if (_cost[i] > art_cost) art_cost = _cost[i];
1144 1144
        }
1145 1145
        art_cost = (art_cost + 1) * _node_num;
1146 1146
      }
1147 1147

	
1148 1148
      // Run Circulation to check if a feasible solution exists
1149 1149
      typedef ConstMap<Arc, Flow> ConstArcMap;
1150
      ConstArcMap zero_arc_map(0), inf_arc_map(inf_cap);
1150 1151
      FlowNodeMap *csup = NULL;
1151 1152
      bool local_csup = false;
1152 1153
      if (_psupply) {
1153 1154
        csup = _psupply;
1154 1155
      } else {
1155 1156
        csup = new FlowNodeMap(_graph, 0);
1156 1157
        (*csup)[_psource] =  _pstflow;
1157 1158
        (*csup)[_ptarget] = -_pstflow;
1158 1159
        local_csup = true;
1159 1160
      }
1160 1161
      bool circ_result = false;
1161 1162
      if (_ptype == GEQ || (_ptype == LEQ && sum_supply == 0)) {
1162 1163
        // GEQ problem type
1163 1164
        if (_plower) {
1164 1165
          if (_pupper) {
1165 1166
            Circulation<GR, FlowArcMap, FlowArcMap, FlowNodeMap>
1166 1167
              circ(_graph, *_plower, *_pupper, *csup);
1167 1168
            circ_result = circ.run();
1168 1169
          } else {
1169 1170
            Circulation<GR, FlowArcMap, ConstArcMap, FlowNodeMap>
1170
              circ(_graph, *_plower, ConstArcMap(inf_cap), *csup);
1171
              circ(_graph, *_plower, inf_arc_map, *csup);
1171 1172
            circ_result = circ.run();
1172 1173
          }
1173 1174
        } else {
1174 1175
          if (_pupper) {
1175 1176
            Circulation<GR, ConstArcMap, FlowArcMap, FlowNodeMap>
1176
              circ(_graph, ConstArcMap(0), *_pupper, *csup);
1177
              circ(_graph, zero_arc_map, *_pupper, *csup);
1177 1178
            circ_result = circ.run();
1178 1179
          } else {
1179 1180
            Circulation<GR, ConstArcMap, ConstArcMap, FlowNodeMap>
1180
              circ(_graph, ConstArcMap(0), ConstArcMap(inf_cap), *csup);
1181
              circ(_graph, zero_arc_map, inf_arc_map, *csup);
1181 1182
            circ_result = circ.run();
1182 1183
          }
1183 1184
        }
1184 1185
      } else {
1185 1186
        // LEQ problem type
1186 1187
        typedef ReverseDigraph<const GR> RevGraph;
1187 1188
        typedef NegMap<FlowNodeMap> NegNodeMap;
1188 1189
        RevGraph rgraph(_graph);
1189 1190
        NegNodeMap neg_csup(*csup);
1190 1191
        if (_plower) {
1191 1192
          if (_pupper) {
1192 1193
            Circulation<RevGraph, FlowArcMap, FlowArcMap, NegNodeMap>
1193 1194
              circ(rgraph, *_plower, *_pupper, neg_csup);
1194 1195
            circ_result = circ.run();
1195 1196
          } else {
1196 1197
            Circulation<RevGraph, FlowArcMap, ConstArcMap, NegNodeMap>
1197
              circ(rgraph, *_plower, ConstArcMap(inf_cap), neg_csup);
1198
              circ(rgraph, *_plower, inf_arc_map, neg_csup);
1198 1199
            circ_result = circ.run();
1199 1200
          }
1200 1201
        } else {
1201 1202
          if (_pupper) {
1202 1203
            Circulation<RevGraph, ConstArcMap, FlowArcMap, NegNodeMap>
1203
              circ(rgraph, ConstArcMap(0), *_pupper, neg_csup);
1204
              circ(rgraph, zero_arc_map, *_pupper, neg_csup);
1204 1205
            circ_result = circ.run();
1205 1206
          } else {
1206 1207
            Circulation<RevGraph, ConstArcMap, ConstArcMap, NegNodeMap>
1207
              circ(rgraph, ConstArcMap(0), ConstArcMap(inf_cap), neg_csup);
1208
              circ(rgraph, zero_arc_map, inf_arc_map, neg_csup);
1208 1209
            circ_result = circ.run();
1209 1210
          }
1210 1211
        }
1211 1212
      }
1212 1213
      if (local_csup) delete csup;
1213 1214
      if (!circ_result) return false;
1214 1215

	
1215 1216
      // Set data for the artificial root node
1216 1217
      _root = _node_num;
1217 1218
      _parent[_root] = -1;
1218 1219
      _pred[_root] = -1;
1219 1220
      _thread[_root] = 0;
1220 1221
      _rev_thread[0] = _root;
1221 1222
      _succ_num[_root] = all_node_num;
1222 1223
      _last_succ[_root] = _root - 1;
1223 1224
      _supply[_root] = -sum_supply;
1224 1225
      if (sum_supply < 0) {
1225 1226
        _pi[_root] = -art_cost;
1226 1227
      } else {
1227 1228
        _pi[_root] = art_cost;
1228 1229
      }
1229 1230

	
1230 1231
      // Store the arcs in a mixed order
1231 1232
      int k = std::max(int(std::sqrt(double(_arc_num))), 10);
1232 1233
      int i = 0;
1233 1234
      for (ArcIt e(_graph); e != INVALID; ++e) {
1234 1235
        _arc_ref[i] = e;
1235 1236
        if ((i += k) >= _arc_num) i = (i % k) + 1;
1236 1237
      }
1237 1238

	
1238 1239
      // Initialize arc maps
1239 1240
      if (_pupper && _pcost) {
1240 1241
        for (int i = 0; i != _arc_num; ++i) {
1241 1242
          Arc e = _arc_ref[i];
1242 1243
          _source[i] = _node_id[_graph.source(e)];
1243 1244
          _target[i] = _node_id[_graph.target(e)];
1244 1245
          _cap[i] = (*_pupper)[e];
1245 1246
          _cost[i] = (*_pcost)[e];
1246 1247
          _flow[i] = 0;
1247 1248
          _state[i] = STATE_LOWER;
1248 1249
        }
1249 1250
      } else {
1250 1251
        for (int i = 0; i != _arc_num; ++i) {
1251 1252
          Arc e = _arc_ref[i];
1252 1253
          _source[i] = _node_id[_graph.source(e)];
1253 1254
          _target[i] = _node_id[_graph.target(e)];
1254 1255
          _flow[i] = 0;
1255 1256
          _state[i] = STATE_LOWER;
1256 1257
        }
1257 1258
        if (_pupper) {
1258 1259
          for (int i = 0; i != _arc_num; ++i)
1259 1260
            _cap[i] = (*_pupper)[_arc_ref[i]];
1260 1261
        } else {
1261 1262
          for (int i = 0; i != _arc_num; ++i)
1262 1263
            _cap[i] = inf_cap;
1263 1264
        }
1264 1265
        if (_pcost) {
1265 1266
          for (int i = 0; i != _arc_num; ++i)
1266 1267
            _cost[i] = (*_pcost)[_arc_ref[i]];
1267 1268
        } else {
1268 1269
          for (int i = 0; i != _arc_num; ++i)
1269 1270
            _cost[i] = 1;
1270 1271
        }
1271 1272
      }
1272 1273
      
1273 1274
      // Remove non-zero lower bounds
1274 1275
      if (_plower) {
1275 1276
        for (int i = 0; i != _arc_num; ++i) {
1276 1277
          Flow c = (*_plower)[_arc_ref[i]];
1277 1278
          if (c != 0) {
1278 1279
            _cap[i] -= c;
1279 1280
            _supply[_source[i]] -= c;
1280 1281
            _supply[_target[i]] += c;
1281 1282
          }
1282 1283
        }
1283 1284
      }
1284 1285

	
1285 1286
      // Add artificial arcs and initialize the spanning tree data structure
1286 1287
      for (int u = 0, e = _arc_num; u != _node_num; ++u, ++e) {
1287 1288
        _thread[u] = u + 1;
1288 1289
        _rev_thread[u + 1] = u;
1289 1290
        _succ_num[u] = 1;
1290 1291
        _last_succ[u] = u;
1291 1292
        _parent[u] = _root;
1292 1293
        _pred[u] = e;
1293 1294
        _cost[e] = art_cost;
1294 1295
        _cap[e] = inf_cap;
1295 1296
        _state[e] = STATE_TREE;
1296 1297
        if (_supply[u] > 0 || (_supply[u] == 0 && sum_supply <= 0)) {
1297 1298
          _flow[e] = _supply[u];
1298 1299
          _forward[u] = true;
1299 1300
          _pi[u] = -art_cost + _pi[_root];
1300 1301
        } else {
1301 1302
          _flow[e] = -_supply[u];
1302 1303
          _forward[u] = false;
1303 1304
          _pi[u] = art_cost + _pi[_root];
1304 1305
        }
1305 1306
      }
1306 1307

	
1307 1308
      return true;
1308 1309
    }
1309 1310

	
1310 1311
    // Find the join node
1311 1312
    void findJoinNode() {
1312 1313
      int u = _source[in_arc];
1313 1314
      int v = _target[in_arc];
1314 1315
      while (u != v) {
1315 1316
        if (_succ_num[u] < _succ_num[v]) {
1316 1317
          u = _parent[u];
1317 1318
        } else {
1318 1319
          v = _parent[v];
1319 1320
        }
1320 1321
      }
1321 1322
      join = u;
1322 1323
    }
1323 1324

	
1324 1325
    // Find the leaving arc of the cycle and returns true if the
1325 1326
    // leaving arc is not the same as the entering arc
1326 1327
    bool findLeavingArc() {
1327 1328
      // Initialize first and second nodes according to the direction
1328 1329
      // of the cycle
1329 1330
      if (_state[in_arc] == STATE_LOWER) {
1330 1331
        first  = _source[in_arc];
1331 1332
        second = _target[in_arc];
1332 1333
      } else {
1333 1334
        first  = _target[in_arc];
1334 1335
        second = _source[in_arc];
1335 1336
      }
Ignore white space 6 line context
... ...
@@ -108,232 +108,227 @@
108 108
             .run();
109 109
      
110 110
      const MCF& const_mcf = mcf;
111 111

	
112 112
      const typename MCF::FlowMap &fm = const_mcf.flowMap();
113 113
      const typename MCF::PotentialMap &pm = const_mcf.potentialMap();
114 114

	
115 115
      v = const_mcf.totalCost();
116 116
      double x = const_mcf.template totalCost<double>();
117 117
      v = const_mcf.flow(a);
118 118
      v = const_mcf.potential(n);
119 119

	
120 120
      ignore_unused_variable_warning(fm);
121 121
      ignore_unused_variable_warning(pm);
122 122
      ignore_unused_variable_warning(x);
123 123
    }
124 124

	
125 125
    typedef typename GR::Node Node;
126 126
    typedef typename GR::Arc Arc;
127 127
    typedef concepts::ReadMap<Node, Flow> NM;
128 128
    typedef concepts::ReadMap<Arc, Flow> FAM;
129 129
    typedef concepts::ReadMap<Arc, Cost> CAM;
130 130

	
131 131
    const GR &g;
132 132
    const FAM &lower;
133 133
    const FAM &upper;
134 134
    const CAM &cost;
135 135
    const NM &sup;
136 136
    const Node &n;
137 137
    const Arc &a;
138 138
    const Flow &k;
139 139
    Flow v;
140 140
    bool b;
141 141

	
142 142
    typename MCF::FlowMap &flow;
143 143
    typename MCF::PotentialMap &pot;
144 144
  };
145 145

	
146 146
};
147 147

	
148 148

	
149 149
// Check the feasibility of the given flow (primal soluiton)
150 150
template < typename GR, typename LM, typename UM,
151 151
           typename SM, typename FM >
152 152
bool checkFlow( const GR& gr, const LM& lower, const UM& upper,
153 153
                const SM& supply, const FM& flow,
154 154
                ProblemType type = EQ )
155 155
{
156 156
  TEMPLATE_DIGRAPH_TYPEDEFS(GR);
157 157

	
158 158
  for (ArcIt e(gr); e != INVALID; ++e) {
159 159
    if (flow[e] < lower[e] || flow[e] > upper[e]) return false;
160 160
  }
161 161

	
162 162
  for (NodeIt n(gr); n != INVALID; ++n) {
163 163
    typename SM::Value sum = 0;
164 164
    for (OutArcIt e(gr, n); e != INVALID; ++e)
165 165
      sum += flow[e];
166 166
    for (InArcIt e(gr, n); e != INVALID; ++e)
167 167
      sum -= flow[e];
168 168
    bool b = (type ==  EQ && sum == supply[n]) ||
169 169
             (type == GEQ && sum >= supply[n]) ||
170 170
             (type == LEQ && sum <= supply[n]);
171 171
    if (!b) return false;
172 172
  }
173 173

	
174 174
  return true;
175 175
}
176 176

	
177 177
// Check the feasibility of the given potentials (dual soluiton)
178 178
// using the "Complementary Slackness" optimality condition
179 179
template < typename GR, typename LM, typename UM,
180 180
           typename CM, typename SM, typename FM, typename PM >
181 181
bool checkPotential( const GR& gr, const LM& lower, const UM& upper,
182 182
                     const CM& cost, const SM& supply, const FM& flow, 
183 183
                     const PM& pi )
184 184
{
185 185
  TEMPLATE_DIGRAPH_TYPEDEFS(GR);
186 186

	
187 187
  bool opt = true;
188 188
  for (ArcIt e(gr); opt && e != INVALID; ++e) {
189 189
    typename CM::Value red_cost =
190 190
      cost[e] + pi[gr.source(e)] - pi[gr.target(e)];
191 191
    opt = red_cost == 0 ||
192 192
          (red_cost > 0 && flow[e] == lower[e]) ||
193 193
          (red_cost < 0 && flow[e] == upper[e]);
194 194
  }
195 195
  
196 196
  for (NodeIt n(gr); opt && n != INVALID; ++n) {
197 197
    typename SM::Value sum = 0;
198 198
    for (OutArcIt e(gr, n); e != INVALID; ++e)
199 199
      sum += flow[e];
200 200
    for (InArcIt e(gr, n); e != INVALID; ++e)
201 201
      sum -= flow[e];
202 202
    opt = (sum == supply[n]) || (pi[n] == 0);
203 203
  }
204 204
  
205 205
  return opt;
206 206
}
207 207

	
208 208
// Run a minimum cost flow algorithm and check the results
209 209
template < typename MCF, typename GR,
210 210
           typename LM, typename UM,
211 211
           typename CM, typename SM >
212 212
void checkMcf( const MCF& mcf, bool mcf_result,
213 213
               const GR& gr, const LM& lower, const UM& upper,
214 214
               const CM& cost, const SM& supply,
215 215
               bool result, typename CM::Value total,
216 216
               const std::string &test_id = "",
217 217
               ProblemType type = EQ )
218 218
{
219 219
  check(mcf_result == result, "Wrong result " + test_id);
220 220
  if (result) {
221 221
    check(checkFlow(gr, lower, upper, supply, mcf.flowMap(), type),
222 222
          "The flow is not feasible " + test_id);
223 223
    check(mcf.totalCost() == total, "The flow is not optimal " + test_id);
224 224
    check(checkPotential(gr, lower, upper, cost, supply, mcf.flowMap(),
225 225
                         mcf.potentialMap()),
226 226
          "Wrong potentials " + test_id);
227 227
  }
228 228
}
229 229

	
230 230
int main()
231 231
{
232 232
  // Check the interfaces
233 233
  {
234 234
    typedef int Flow;
235 235
    typedef int Cost;
236
    // TODO: This typedef should be enabled if the standard maps are
237
    // reference maps in the graph concepts (See #190).
238
/**/
239
    //typedef concepts::Digraph GR;
240
    typedef ListDigraph GR;
241
/**/
236
    typedef concepts::Digraph GR;
242 237
    checkConcept< McfClassConcept<GR, Flow, Cost>,
243 238
                  NetworkSimplex<GR, Flow, Cost> >();
244 239
  }
245 240

	
246 241
  // Run various MCF tests
247 242
  typedef ListDigraph Digraph;
248 243
  DIGRAPH_TYPEDEFS(ListDigraph);
249 244

	
250 245
  // Read the test digraph
251 246
  Digraph gr;
252 247
  Digraph::ArcMap<int> c(gr), l1(gr), l2(gr), u(gr);
253 248
  Digraph::NodeMap<int> s1(gr), s2(gr), s3(gr), s4(gr), s5(gr);
254 249
  ConstMap<Arc, int> cc(1), cu(std::numeric_limits<int>::max());
255 250
  Node v, w;
256 251

	
257 252
  std::istringstream input(test_lgf);
258 253
  DigraphReader<Digraph>(gr, input)
259 254
    .arcMap("cost", c)
260 255
    .arcMap("cap", u)
261 256
    .arcMap("low1", l1)
262 257
    .arcMap("low2", l2)
263 258
    .nodeMap("sup1", s1)
264 259
    .nodeMap("sup2", s2)
265 260
    .nodeMap("sup3", s3)
266 261
    .nodeMap("sup4", s4)
267 262
    .nodeMap("sup5", s5)
268 263
    .node("source", v)
269 264
    .node("target", w)
270 265
    .run();
271 266

	
272 267
  // A. Test NetworkSimplex with the default pivot rule
273 268
  {
274 269
    NetworkSimplex<Digraph> mcf(gr);
275 270

	
276 271
    // Check the equality form
277 272
    mcf.upperMap(u).costMap(c);
278 273
    checkMcf(mcf, mcf.supplyMap(s1).run(),
279 274
             gr, l1, u, c, s1, true,  5240, "#A1");
280 275
    checkMcf(mcf, mcf.stSupply(v, w, 27).run(),
281 276
             gr, l1, u, c, s2, true,  7620, "#A2");
282 277
    mcf.lowerMap(l2);
283 278
    checkMcf(mcf, mcf.supplyMap(s1).run(),
284 279
             gr, l2, u, c, s1, true,  5970, "#A3");
285 280
    checkMcf(mcf, mcf.stSupply(v, w, 27).run(),
286 281
             gr, l2, u, c, s2, true,  8010, "#A4");
287 282
    mcf.reset();
288 283
    checkMcf(mcf, mcf.supplyMap(s1).run(),
289 284
             gr, l1, cu, cc, s1, true,  74, "#A5");
290 285
    checkMcf(mcf, mcf.lowerMap(l2).stSupply(v, w, 27).run(),
291 286
             gr, l2, cu, cc, s2, true,  94, "#A6");
292 287
    mcf.reset();
293 288
    checkMcf(mcf, mcf.run(),
294 289
             gr, l1, cu, cc, s3, true,   0, "#A7");
295 290
    checkMcf(mcf, mcf.boundMaps(l2, u).run(),
296 291
             gr, l2, u, cc, s3, false,   0, "#A8");
297 292

	
298 293
    // Check the GEQ form
299 294
    mcf.reset().upperMap(u).costMap(c).supplyMap(s4);
300 295
    checkMcf(mcf, mcf.run(),
301 296
             gr, l1, u, c, s4, true,  3530, "#A9", GEQ);
302 297
    mcf.problemType(mcf.GEQ);
303 298
    checkMcf(mcf, mcf.lowerMap(l2).run(),
304 299
             gr, l2, u, c, s4, true,  4540, "#A10", GEQ);
305 300
    mcf.problemType(mcf.CARRY_SUPPLIES).supplyMap(s5);
306 301
    checkMcf(mcf, mcf.run(),
307 302
             gr, l2, u, c, s5, false,    0, "#A11", GEQ);
308 303

	
309 304
    // Check the LEQ form
310 305
    mcf.reset().problemType(mcf.LEQ);
311 306
    mcf.upperMap(u).costMap(c).supplyMap(s5);
312 307
    checkMcf(mcf, mcf.run(),
313 308
             gr, l1, u, c, s5, true,  5080, "#A12", LEQ);
314 309
    checkMcf(mcf, mcf.lowerMap(l2).run(),
315 310
             gr, l2, u, c, s5, true,  5930, "#A13", LEQ);
316 311
    mcf.problemType(mcf.SATISFY_DEMANDS).supplyMap(s4);
317 312
    checkMcf(mcf, mcf.run(),
318 313
             gr, l2, u, c, s4, false,    0, "#A14", LEQ);
319 314
  }
320 315

	
321 316
  // B. Test NetworkSimplex with each pivot rule
322 317
  {
323 318
    NetworkSimplex<Digraph> mcf(gr);
324 319
    mcf.supplyMap(s1).costMap(c).capacityMap(u).lowerMap(l2);
325 320

	
326 321
    checkMcf(mcf, mcf.run(NetworkSimplex<Digraph>::FIRST_ELIGIBLE),
327 322
             gr, l2, u, c, s1, true,  5970, "#B1");
328 323
    checkMcf(mcf, mcf.run(NetworkSimplex<Digraph>::BEST_ELIGIBLE),
329 324
             gr, l2, u, c, s1, true,  5970, "#B2");
330 325
    checkMcf(mcf, mcf.run(NetworkSimplex<Digraph>::BLOCK_SEARCH),
331 326
             gr, l2, u, c, s1, true,  5970, "#B3");
332 327
    checkMcf(mcf, mcf.run(NetworkSimplex<Digraph>::CANDIDATE_LIST),
333 328
             gr, l2, u, c, s1, true,  5970, "#B4");
334 329
    checkMcf(mcf, mcf.run(NetworkSimplex<Digraph>::ALTERING_LIST),
335 330
             gr, l2, u, c, s1, true,  5970, "#B5");
336 331
  }
337 332

	
338 333
  return 0;
339 334
}
Ignore white space 6 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2009
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
///\ingroup tools
20 20
///\file
21 21
///\brief DIMACS problem solver.
22 22
///
23 23
/// This program solves various problems given in DIMACS format.
24 24
///
25 25
/// See
26 26
/// \code
27 27
///   dimacs-solver --help
28 28
/// \endcode
29 29
/// for more info on usage.
30 30

	
31 31
#include <iostream>
32 32
#include <fstream>
33 33
#include <cstring>
34 34

	
35 35
#include <lemon/smart_graph.h>
36 36
#include <lemon/dimacs.h>
37 37
#include <lemon/lgf_writer.h>
38 38
#include <lemon/time_measure.h>
39 39

	
40 40
#include <lemon/arg_parser.h>
41 41
#include <lemon/error.h>
42 42

	
43 43
#include <lemon/dijkstra.h>
44 44
#include <lemon/preflow.h>
45 45
#include <lemon/matching.h>
46 46
#include <lemon/network_simplex.h>
47 47

	
48 48
using namespace lemon;
49 49
typedef SmartDigraph Digraph;
50 50
DIGRAPH_TYPEDEFS(Digraph);
51 51
typedef SmartGraph Graph;
52 52

	
53 53
template<class Value>
54 54
void solve_sp(ArgParser &ap, std::istream &is, std::ostream &,
55 55
              DimacsDescriptor &desc)
56 56
{
57 57
  bool report = !ap.given("q");
58 58
  Digraph g;
59 59
  Node s;
60 60
  Digraph::ArcMap<Value> len(g);
61 61
  Timer t;
62 62
  t.restart();
63 63
  readDimacsSp(is, g, len, s, desc);
64 64
  if(report) std::cerr << "Read the file: " << t << '\n';
65 65
  t.restart();
66 66
  Dijkstra<Digraph, Digraph::ArcMap<Value> > dij(g,len);
67 67
  if(report) std::cerr << "Setup Dijkstra class: " << t << '\n';
68 68
  t.restart();
69 69
  dij.run(s);
70 70
  if(report) std::cerr << "Run Dijkstra: " << t << '\n';
71 71
}
72 72

	
73 73
template<class Value>
74 74
void solve_max(ArgParser &ap, std::istream &is, std::ostream &,
75 75
               Value infty, DimacsDescriptor &desc)
76 76
{
77 77
  bool report = !ap.given("q");
78 78
  Digraph g;
79 79
  Node s,t;
80 80
  Digraph::ArcMap<Value> cap(g);
81 81
  Timer ti;
82 82
  ti.restart();
83 83
  readDimacsMax(is, g, cap, s, t, infty, desc);
84 84
  if(report) std::cerr << "Read the file: " << ti << '\n';
85 85
  ti.restart();
86 86
  Preflow<Digraph, Digraph::ArcMap<Value> > pre(g,cap,s,t);
87 87
  if(report) std::cerr << "Setup Preflow class: " << ti << '\n';
88 88
  ti.restart();
89 89
  pre.run();
90 90
  if(report) std::cerr << "Run Preflow: " << ti << '\n';
91 91
  if(report) std::cerr << "\nMax flow value: " << pre.flowValue() << '\n';  
92 92
}
93 93

	
94 94
template<class Value>
95 95
void solve_min(ArgParser &ap, std::istream &is, std::ostream &,
96
               DimacsDescriptor &desc)
96
               Value infty, DimacsDescriptor &desc)
97 97
{
98 98
  bool report = !ap.given("q");
99 99
  Digraph g;
100 100
  Digraph::ArcMap<Value> lower(g), cap(g), cost(g);
101 101
  Digraph::NodeMap<Value> sup(g);
102 102
  Timer ti;
103

	
103 104
  ti.restart();
104
  readDimacsMin(is, g, lower, cap, cost, sup, 0, desc);
105
  readDimacsMin(is, g, lower, cap, cost, sup, infty, desc);
106
  ti.stop();
107
  Value sum_sup = 0;
108
  for (Digraph::NodeIt n(g); n != INVALID; ++n) {
109
    sum_sup += sup[n];
110
  }
111
  if (report) {
112
    std::cerr << "Sum of supply values: " << sum_sup << "\n";
113
    if (sum_sup <= 0)
114
      std::cerr << "GEQ supply contraints are used for NetworkSimplex\n\n";
115
    else
116
      std::cerr << "LEQ supply contraints are used for NetworkSimplex\n\n";
117
  }
105 118
  if (report) std::cerr << "Read the file: " << ti << '\n';
119

	
106 120
  ti.restart();
107 121
  NetworkSimplex<Digraph, Value> ns(g);
108 122
  ns.lowerMap(lower).capacityMap(cap).costMap(cost).supplyMap(sup);
123
  if (sum_sup > 0) ns.problemType(ns.LEQ);
109 124
  if (report) std::cerr << "Setup NetworkSimplex class: " << ti << '\n';
110 125
  ti.restart();
111
  ns.run();
112
  if (report) std::cerr << "Run NetworkSimplex: " << ti << '\n';
113
  if (report) std::cerr << "\nMin flow cost: " << ns.totalCost() << '\n';
126
  bool res = ns.run();
127
  if (report) {
128
    std::cerr << "Run NetworkSimplex: " << ti << "\n\n";
129
    std::cerr << "Feasible flow: " << (res ? "found" : "not found") << '\n';
130
    if (res) std::cerr << "Min flow cost: " << ns.totalCost() << '\n';
131
  }
114 132
}
115 133

	
116 134
void solve_mat(ArgParser &ap, std::istream &is, std::ostream &,
117 135
              DimacsDescriptor &desc)
118 136
{
119 137
  bool report = !ap.given("q");
120 138
  Graph g;
121 139
  Timer ti;
122 140
  ti.restart();
123 141
  readDimacsMat(is, g, desc);
124 142
  if(report) std::cerr << "Read the file: " << ti << '\n';
125 143
  ti.restart();
126 144
  MaxMatching<Graph> mat(g);
127 145
  if(report) std::cerr << "Setup MaxMatching class: " << ti << '\n';
128 146
  ti.restart();
129 147
  mat.run();
130 148
  if(report) std::cerr << "Run MaxMatching: " << ti << '\n';
131 149
  if(report) std::cerr << "\nCardinality of max matching: "
132 150
                       << mat.matchingSize() << '\n';  
133 151
}
134 152

	
135 153

	
136 154
template<class Value>
137 155
void solve(ArgParser &ap, std::istream &is, std::ostream &os,
138 156
           DimacsDescriptor &desc)
139 157
{
140 158
  std::stringstream iss(static_cast<std::string>(ap["infcap"]));
141 159
  Value infty;
142 160
  iss >> infty;
143 161
  if(iss.fail())
144 162
    {
145 163
      std::cerr << "Cannot interpret '"
146 164
                << static_cast<std::string>(ap["infcap"]) << "' as infinite"
147 165
                << std::endl;
148 166
      exit(1);
149 167
    }
150 168
  
151 169
  switch(desc.type)
152 170
    {
153 171
    case DimacsDescriptor::MIN:
154
      solve_min<Value>(ap,is,os,desc);
172
      solve_min<Value>(ap,is,os,infty,desc);
155 173
      break;
156 174
    case DimacsDescriptor::MAX:
157 175
      solve_max<Value>(ap,is,os,infty,desc);
158 176
      break;
159 177
    case DimacsDescriptor::SP:
160 178
      solve_sp<Value>(ap,is,os,desc);
161 179
      break;
162 180
    case DimacsDescriptor::MAT:
163 181
      solve_mat(ap,is,os,desc);
164 182
      break;
165 183
    default:
166 184
      break;
167 185
    }
168 186
}
169 187

	
170 188
int main(int argc, const char *argv[]) {
171 189
  typedef SmartDigraph Digraph;
172 190

	
173 191
  typedef Digraph::Arc Arc;
174 192

	
175 193
  std::string inputName;
176 194
  std::string outputName;
177 195

	
178 196
  ArgParser ap(argc, argv);
179 197
  ap.other("[INFILE [OUTFILE]]",
180 198
           "If either the INFILE or OUTFILE file is missing the standard\n"
181 199
           "     input/output will be used instead.")
182 200
    .boolOption("q", "Do not print any report")
183 201
    .boolOption("int","Use 'int' for capacities, costs etc. (default)")
184 202
    .optionGroup("datatype","int")
185 203
#ifdef HAVE_LONG_LONG
186 204
    .boolOption("long","Use 'long long' for capacities, costs etc.")
187 205
    .optionGroup("datatype","long")
188 206
#endif
189 207
    .boolOption("double","Use 'double' for capacities, costs etc.")
190 208
    .optionGroup("datatype","double")
191 209
    .boolOption("ldouble","Use 'long double' for capacities, costs etc.")
192 210
    .optionGroup("datatype","ldouble")
193 211
    .onlyOneGroup("datatype")
194 212
    .stringOption("infcap","Value used for 'very high' capacities","0")
195 213
    .run();
196 214

	
197 215
  std::ifstream input;
198 216
  std::ofstream output;
199 217

	
200 218
  switch(ap.files().size())
201 219
    {
202 220
    case 2:
203 221
      output.open(ap.files()[1].c_str());
204 222
      if (!output) {
205 223
        throw IoError("Cannot open the file for writing", ap.files()[1]);
206 224
      }
207 225
    case 1:
208 226
      input.open(ap.files()[0].c_str());
209 227
      if (!input) {
210 228
        throw IoError("File cannot be found", ap.files()[0]);
211 229
      }
212 230
    case 0:
213 231
      break;
214 232
    default:
215 233
      std::cerr << ap.commandName() << ": too many arguments\n";
216 234
      return 1;
217 235
    }
218 236
  std::istream& is = (ap.files().size()<1 ? std::cin : input);
219 237
  std::ostream& os = (ap.files().size()<2 ? std::cout : output);
220 238

	
221 239
  DimacsDescriptor desc = dimacsType(is);
222 240
  
223 241
  if(!ap.given("q"))
224 242
    {
225 243
      std::cout << "Problem type: ";
226 244
      switch(desc.type)
227 245
        {
228 246
        case DimacsDescriptor::MIN:
229 247
          std::cout << "min";
230 248
          break;
231 249
        case DimacsDescriptor::MAX:
232 250
          std::cout << "max";
233 251
          break;
234 252
        case DimacsDescriptor::SP:
235 253
          std::cout << "sp";
236 254
        case DimacsDescriptor::MAT:
237 255
          std::cout << "mat";
238 256
          break;
239 257
        default:
240 258
          exit(1);
241 259
          break;
242 260
        }
243 261
      std::cout << "\nNum of nodes: " << desc.nodeNum;
244 262
      std::cout << "\nNum of arcs:  " << desc.edgeNum;
245 263
      std::cout << "\n\n";
246 264
    }
247 265
    
248 266
  if(ap.given("double"))
249 267
    solve<double>(ap,is,os,desc);
250 268
  else if(ap.given("ldouble"))
251 269
    solve<long double>(ap,is,os,desc);
252 270
#ifdef HAVE_LONG_LONG
253 271
  else if(ap.given("long"))
254 272
    solve<long long>(ap,is,os,desc);
255 273
#endif
256 274
  else solve<int>(ap,is,os,desc);
257 275

	
258 276
  return 0;
259 277
}
0 comments (0 inline)