gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Unify sources
0 3 0
r1.2.3 1.2
3 files changed with 3 insertions and 3 deletions:
↑ Collapse diff ↑
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
 * Copyright (C) 2003-2010
5
 * Copyright (C) 2003-2011
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
#ifndef LEMON_LP_BASE_H
20 20
#define LEMON_LP_BASE_H
21 21

	
22 22
#include<iostream>
23 23
#include<vector>
24 24
#include<map>
25 25
#include<limits>
26 26
#include<lemon/math.h>
27 27

	
28 28
#include<lemon/error.h>
29 29
#include<lemon/assert.h>
30 30

	
31 31
#include<lemon/core.h>
32 32
#include<lemon/bits/solver_bits.h>
33 33

	
34 34
///\file
35 35
///\brief The interface of the LP solver interface.
36 36
///\ingroup lp_group
37 37
namespace lemon {
38 38

	
39 39
  ///Common base class for LP and MIP solvers
40 40

	
41 41
  ///Usually this class is not used directly, please use one of the concrete
42 42
  ///implementations of the solver interface.
43 43
  ///\ingroup lp_group
44 44
  class LpBase {
45 45

	
46 46
  protected:
47 47

	
48 48
    _solver_bits::VarIndex rows;
49 49
    _solver_bits::VarIndex cols;
50 50

	
51 51
  public:
52 52

	
53 53
    ///Possible outcomes of an LP solving procedure
54 54
    enum SolveExitStatus {
55 55
      /// = 0. It means that the problem has been successfully solved: either
56 56
      ///an optimal solution has been found or infeasibility/unboundedness
57 57
      ///has been proved.
58 58
      SOLVED = 0,
59 59
      /// = 1. Any other case (including the case when some user specified
60 60
      ///limit has been exceeded).
61 61
      UNSOLVED = 1
62 62
    };
63 63

	
64 64
    ///Direction of the optimization
65 65
    enum Sense {
66 66
      /// Minimization
67 67
      MIN,
68 68
      /// Maximization
69 69
      MAX
70 70
    };
71 71

	
72 72
    ///Enum for \c messageLevel() parameter
73 73
    enum MessageLevel {
74 74
      /// No output (default value).
75 75
      MESSAGE_NOTHING,
76 76
      /// Error messages only.
77 77
      MESSAGE_ERROR,
78 78
      /// Warnings.
79 79
      MESSAGE_WARNING,
80 80
      /// Normal output.
81 81
      MESSAGE_NORMAL,
82 82
      /// Verbose output.
83 83
      MESSAGE_VERBOSE
84 84
    };
85 85

	
86 86

	
87 87
    ///The floating point type used by the solver
88 88
    typedef double Value;
89 89
    ///The infinity constant
90 90
    static const Value INF;
91 91
    ///The not a number constant
92 92
    static const Value NaN;
93 93

	
94 94
    friend class Col;
95 95
    friend class ColIt;
96 96
    friend class Row;
97 97
    friend class RowIt;
98 98

	
99 99
    ///Refer to a column of the LP.
100 100

	
101 101
    ///This type is used to refer to a column of the LP.
102 102
    ///
103 103
    ///Its value remains valid and correct even after the addition or erase of
104 104
    ///other columns.
105 105
    ///
106 106
    ///\note This class is similar to other Item types in LEMON, like
107 107
    ///Node and Arc types in digraph.
108 108
    class Col {
109 109
      friend class LpBase;
110 110
    protected:
111 111
      int _id;
112 112
      explicit Col(int id) : _id(id) {}
113 113
    public:
114 114
      typedef Value ExprValue;
115 115
      typedef True LpCol;
116 116
      /// Default constructor
117 117

	
118 118
      /// \warning The default constructor sets the Col to an
119 119
      /// undefined value.
120 120
      Col() {}
121 121
      /// Invalid constructor \& conversion.
122 122

	
123 123
      /// This constructor initializes the Col to be invalid.
124 124
      /// \sa Invalid for more details.
125 125
      Col(const Invalid&) : _id(-1) {}
126 126
      /// Equality operator
127 127

	
128 128
      /// Two \ref Col "Col"s are equal if and only if they point to
129 129
      /// the same LP column or both are invalid.
130 130
      bool operator==(Col c) const  {return _id == c._id;}
131 131
      /// Inequality operator
132 132

	
133 133
      /// \sa operator==(Col c)
134 134
      ///
135 135
      bool operator!=(Col c) const  {return _id != c._id;}
136 136
      /// Artificial ordering operator.
137 137

	
138 138
      /// To allow the use of this object in std::map or similar
139 139
      /// associative container we require this.
140 140
      ///
141 141
      /// \note This operator only have to define some strict ordering of
142 142
      /// the items; this order has nothing to do with the iteration
143 143
      /// ordering of the items.
144 144
      bool operator<(Col c) const  {return _id < c._id;}
145 145
    };
146 146

	
147 147
    ///Iterator for iterate over the columns of an LP problem
148 148

	
149 149
    /// Its usage is quite simple, for example, you can count the number
150 150
    /// of columns in an LP \c lp:
151 151
    ///\code
152 152
    /// int count=0;
153 153
    /// for (LpBase::ColIt c(lp); c!=INVALID; ++c) ++count;
154 154
    ///\endcode
155 155
    class ColIt : public Col {
156 156
      const LpBase *_solver;
157 157
    public:
158 158
      /// Default constructor
159 159

	
160 160
      /// \warning The default constructor sets the iterator
161 161
      /// to an undefined value.
162 162
      ColIt() {}
163 163
      /// Sets the iterator to the first Col
164 164

	
165 165
      /// Sets the iterator to the first Col.
166 166
      ///
167 167
      ColIt(const LpBase &solver) : _solver(&solver)
168 168
      {
169 169
        _solver->cols.firstItem(_id);
170 170
      }
171 171
      /// Invalid constructor \& conversion
172 172

	
173 173
      /// Initialize the iterator to be invalid.
174 174
      /// \sa Invalid for more details.
175 175
      ColIt(const Invalid&) : Col(INVALID) {}
176 176
      /// Next column
177 177

	
178 178
      /// Assign the iterator to the next column.
179 179
      ///
180 180
      ColIt &operator++()
181 181
      {
182 182
        _solver->cols.nextItem(_id);
183 183
        return *this;
184 184
      }
185 185
    };
186 186

	
187 187
    /// \brief Returns the ID of the column.
188 188
    static int id(const Col& col) { return col._id; }
189 189
    /// \brief Returns the column with the given ID.
190 190
    ///
191 191
    /// \pre The argument should be a valid column ID in the LP problem.
192 192
    static Col colFromId(int id) { return Col(id); }
193 193

	
194 194
    ///Refer to a row of the LP.
195 195

	
196 196
    ///This type is used to refer to a row of the LP.
197 197
    ///
198 198
    ///Its value remains valid and correct even after the addition or erase of
199 199
    ///other rows.
200 200
    ///
201 201
    ///\note This class is similar to other Item types in LEMON, like
202 202
    ///Node and Arc types in digraph.
203 203
    class Row {
204 204
      friend class LpBase;
205 205
    protected:
206 206
      int _id;
207 207
      explicit Row(int id) : _id(id) {}
208 208
    public:
209 209
      typedef Value ExprValue;
210 210
      typedef True LpRow;
211 211
      /// Default constructor
212 212

	
213 213
      /// \warning The default constructor sets the Row to an
214 214
      /// undefined value.
215 215
      Row() {}
216 216
      /// Invalid constructor \& conversion.
217 217

	
218 218
      /// This constructor initializes the Row to be invalid.
219 219
      /// \sa Invalid for more details.
220 220
      Row(const Invalid&) : _id(-1) {}
221 221
      /// Equality operator
222 222

	
223 223
      /// Two \ref Row "Row"s are equal if and only if they point to
224 224
      /// the same LP row or both are invalid.
225 225
      bool operator==(Row r) const  {return _id == r._id;}
226 226
      /// Inequality operator
227 227

	
228 228
      /// \sa operator==(Row r)
229 229
      ///
230 230
      bool operator!=(Row r) const  {return _id != r._id;}
231 231
      /// Artificial ordering operator.
232 232

	
233 233
      /// To allow the use of this object in std::map or similar
234 234
      /// associative container we require this.
235 235
      ///
236 236
      /// \note This operator only have to define some strict ordering of
237 237
      /// the items; this order has nothing to do with the iteration
238 238
      /// ordering of the items.
239 239
      bool operator<(Row r) const  {return _id < r._id;}
240 240
    };
241 241

	
242 242
    ///Iterator for iterate over the rows of an LP problem
243 243

	
244 244
    /// Its usage is quite simple, for example, you can count the number
245 245
    /// of rows in an LP \c lp:
246 246
    ///\code
247 247
    /// int count=0;
248 248
    /// for (LpBase::RowIt c(lp); c!=INVALID; ++c) ++count;
249 249
    ///\endcode
250 250
    class RowIt : public Row {
251 251
      const LpBase *_solver;
252 252
    public:
253 253
      /// Default constructor
254 254

	
255 255
      /// \warning The default constructor sets the iterator
256 256
      /// to an undefined value.
257 257
      RowIt() {}
258 258
      /// Sets the iterator to the first Row
259 259

	
260 260
      /// Sets the iterator to the first Row.
261 261
      ///
262 262
      RowIt(const LpBase &solver) : _solver(&solver)
263 263
      {
264 264
        _solver->rows.firstItem(_id);
265 265
      }
266 266
      /// Invalid constructor \& conversion
267 267

	
268 268
      /// Initialize the iterator to be invalid.
269 269
      /// \sa Invalid for more details.
270 270
      RowIt(const Invalid&) : Row(INVALID) {}
271 271
      /// Next row
272 272

	
273 273
      /// Assign the iterator to the next row.
274 274
      ///
275 275
      RowIt &operator++()
276 276
      {
277 277
        _solver->rows.nextItem(_id);
278 278
        return *this;
279 279
      }
280 280
    };
281 281

	
282 282
    /// \brief Returns the ID of the row.
283 283
    static int id(const Row& row) { return row._id; }
284 284
    /// \brief Returns the row with the given ID.
285 285
    ///
286 286
    /// \pre The argument should be a valid row ID in the LP problem.
287 287
    static Row rowFromId(int id) { return Row(id); }
288 288

	
289 289
  public:
290 290

	
291 291
    ///Linear expression of variables and a constant component
292 292

	
293 293
    ///This data structure stores a linear expression of the variables
294 294
    ///(\ref Col "Col"s) and also has a constant component.
295 295
    ///
296 296
    ///There are several ways to access and modify the contents of this
297 297
    ///container.
298 298
    ///\code
299 299
    ///e[v]=5;
300 300
    ///e[v]+=12;
301 301
    ///e.erase(v);
302 302
    ///\endcode
303 303
    ///or you can also iterate through its elements.
304 304
    ///\code
305 305
    ///double s=0;
306 306
    ///for(LpBase::Expr::ConstCoeffIt i(e);i!=INVALID;++i)
307 307
    ///  s+=*i * primal(i);
308 308
    ///\endcode
309 309
    ///(This code computes the primal value of the expression).
310 310
    ///- Numbers (<tt>double</tt>'s)
311 311
    ///and variables (\ref Col "Col"s) directly convert to an
312 312
    ///\ref Expr and the usual linear operations are defined, so
313 313
    ///\code
314 314
    ///v+w
315 315
    ///2*v-3.12*(v-w/2)+2
316 316
    ///v*2.1+(3*v+(v*12+w+6)*3)/2
317 317
    ///\endcode
318 318
    ///are valid expressions.
319 319
    ///The usual assignment operations are also defined.
320 320
    ///\code
321 321
    ///e=v+w;
322 322
    ///e+=2*v-3.12*(v-w/2)+2;
323 323
    ///e*=3.4;
324 324
    ///e/=5;
325 325
    ///\endcode
326 326
    ///- The constant member can be set and read by dereference
327 327
    ///  operator (unary *)
328 328
    ///
329 329
    ///\code
330 330
    ///*e=12;
331 331
    ///double c=*e;
332 332
    ///\endcode
333 333
    ///
334 334
    ///\sa Constr
335 335
    class Expr {
336 336
      friend class LpBase;
337 337
    public:
338 338
      /// The key type of the expression
339 339
      typedef LpBase::Col Key;
340 340
      /// The value type of the expression
341 341
      typedef LpBase::Value Value;
342 342

	
343 343
    protected:
344 344
      Value const_comp;
345 345
      std::map<int, Value> comps;
346 346

	
347 347
    public:
348 348
      typedef True SolverExpr;
349 349
      /// Default constructor
350 350

	
351 351
      /// Construct an empty expression, the coefficients and
352 352
      /// the constant component are initialized to zero.
353 353
      Expr() : const_comp(0) {}
354 354
      /// Construct an expression from a column
355 355

	
356 356
      /// Construct an expression, which has a term with \c c variable
357 357
      /// and 1.0 coefficient.
358 358
      Expr(const Col &c) : const_comp(0) {
359 359
        typedef std::map<int, Value>::value_type pair_type;
360 360
        comps.insert(pair_type(id(c), 1));
361 361
      }
362 362
      /// Construct an expression from a constant
363 363

	
364 364
      /// Construct an expression, which's constant component is \c v.
365 365
      ///
366 366
      Expr(const Value &v) : const_comp(v) {}
367 367
      /// Returns the coefficient of the column
368 368
      Value operator[](const Col& c) const {
369 369
        std::map<int, Value>::const_iterator it=comps.find(id(c));
370 370
        if (it != comps.end()) {
371 371
          return it->second;
372 372
        } else {
373 373
          return 0;
374 374
        }
375 375
      }
376 376
      /// Returns the coefficient of the column
377 377
      Value& operator[](const Col& c) {
378 378
        return comps[id(c)];
379 379
      }
380 380
      /// Sets the coefficient of the column
381 381
      void set(const Col &c, const Value &v) {
382 382
        if (v != 0.0) {
383 383
          typedef std::map<int, Value>::value_type pair_type;
384 384
          comps.insert(pair_type(id(c), v));
385 385
        } else {
386 386
          comps.erase(id(c));
387 387
        }
388 388
      }
389 389
      /// Returns the constant component of the expression
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-2011
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
#include <lemon/list_graph.h>
20 20
#include <lemon/lgf_reader.h>
21 21
#include "test_tools.h"
22 22

	
23 23
using namespace lemon;
24 24

	
25 25
char test_lgf[] =
26 26
  "@nodes\n"
27 27
  "label\n"
28 28
  "0\n"
29 29
  "1\n"
30 30
  "@arcs\n"
31 31
  "     label\n"
32 32
  "0 1  0\n"
33 33
  "1 0  1\n"
34 34
  "@attributes\n"
35 35
  "source 0\n"
36 36
  "target 1\n";
37 37

	
38 38
char test_lgf_nomap[] =
39 39
  "@nodes\n"
40 40
  "label\n"
41 41
  "0\n"
42 42
  "1\n"
43 43
  "@arcs\n"
44 44
  "     -\n"
45 45
  "0 1\n";
46 46

	
47 47
char test_lgf_bad1[] =
48 48
  "@nodes\n"
49 49
  "label\n"
50 50
  "0\n"
51 51
  "1\n"
52 52
  "@arcs\n"
53 53
  "     - another\n"
54 54
  "0 1\n";
55 55

	
56 56
char test_lgf_bad2[] =
57 57
  "@nodes\n"
58 58
  "label\n"
59 59
  "0\n"
60 60
  "1\n"
61 61
  "@arcs\n"
62 62
  "     label -\n"
63 63
  "0 1\n";
64 64

	
65 65

	
66 66
int main()
67 67
{
68 68
  {
69 69
    ListDigraph d;
70 70
    ListDigraph::Node s,t;
71 71
    ListDigraph::ArcMap<int> label(d);
72 72
    std::istringstream input(test_lgf);
73 73
    digraphReader(d, input).
74 74
      node("source", s).
75 75
      node("target", t).
76 76
      arcMap("label", label).
77 77
      run();
78 78
    check(countNodes(d) == 2,"There should be 2 nodes");
79 79
    check(countArcs(d) == 2,"There should be 2 arcs");
80 80
  }
81 81
  {
82 82
    ListGraph g;
83 83
    ListGraph::Node s,t;
84 84
    ListGraph::EdgeMap<int> label(g);
85 85
    std::istringstream input(test_lgf);
86 86
    graphReader(g, input).
87 87
      node("source", s).
88 88
      node("target", t).
89 89
      edgeMap("label", label).
90 90
      run();
91 91
    check(countNodes(g) == 2,"There should be 2 nodes");
92 92
    check(countEdges(g) == 2,"There should be 2 arcs");
93 93
  }
94 94

	
95 95
  {
96 96
    ListDigraph d;
97 97
    std::istringstream input(test_lgf_nomap);
98 98
    digraphReader(d, input).
99 99
      run();
100 100
    check(countNodes(d) == 2,"There should be 2 nodes");
101 101
    check(countArcs(d) == 1,"There should be 1 arc");
102 102
  }
103 103
  {
104 104
    ListGraph g;
105 105
    std::istringstream input(test_lgf_nomap);
106 106
    graphReader(g, input).
107 107
      run();
108 108
    check(countNodes(g) == 2,"There should be 2 nodes");
109 109
    check(countEdges(g) == 1,"There should be 1 edge");
110 110
  }
111 111

	
112 112
  {
113 113
    ListDigraph d;
114 114
    std::istringstream input(test_lgf_bad1);
115 115
    bool ok=false;
116 116
    try {
117 117
      digraphReader(d, input).
118 118
        run();
119 119
    }
120
    catch (FormatError&) 
120
    catch (FormatError&)
121 121
      {
122 122
        ok = true;
123 123
      }
124 124
    check(ok,"FormatError exception should have occured");
125 125
  }
126 126
  {
127 127
    ListGraph g;
128 128
    std::istringstream input(test_lgf_bad1);
129 129
    bool ok=false;
130 130
    try {
131 131
      graphReader(g, input).
132 132
        run();
133 133
    }
134 134
    catch (FormatError&)
135 135
      {
136 136
        ok = true;
137 137
      }
138 138
    check(ok,"FormatError exception should have occured");
139 139
  }
140 140

	
141 141
  {
142 142
    ListDigraph d;
143 143
    std::istringstream input(test_lgf_bad2);
144 144
    bool ok=false;
145 145
    try {
146 146
      digraphReader(d, input).
147 147
        run();
148 148
    }
149 149
    catch (FormatError&)
150 150
      {
151 151
        ok = true;
152 152
      }
153 153
    check(ok,"FormatError exception should have occured");
154 154
  }
155 155
  {
156 156
    ListGraph g;
157 157
    std::istringstream input(test_lgf_bad2);
158 158
    bool ok=false;
159 159
    try {
160 160
      graphReader(g, input).
161 161
        run();
162 162
    }
163 163
    catch (FormatError&)
164 164
      {
165 165
        ok = true;
166 166
      }
167 167
    check(ok,"FormatError exception should have occured");
168 168
  }
169 169
}
Ignore white space 768 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
 * Copyright (C) 2003-2009
5
 * Copyright (C) 2003-2011
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
#include <sstream>
20 20
#include <lemon/lp_skeleton.h>
21 21
#include "test_tools.h"
22 22
#include <lemon/tolerance.h>
23 23

	
24 24
#include <lemon/config.h>
25 25

	
26 26
#ifdef LEMON_HAVE_GLPK
27 27
#include <lemon/glpk.h>
28 28
#endif
29 29

	
30 30
#ifdef LEMON_HAVE_CPLEX
31 31
#include <lemon/cplex.h>
32 32
#endif
33 33

	
34 34
#ifdef LEMON_HAVE_SOPLEX
35 35
#include <lemon/soplex.h>
36 36
#endif
37 37

	
38 38
#ifdef LEMON_HAVE_CLP
39 39
#include <lemon/clp.h>
40 40
#endif
41 41

	
42 42
using namespace lemon;
43 43

	
44 44
void lpTest(LpSolver& lp)
45 45
{
46 46

	
47 47
  typedef LpSolver LP;
48 48

	
49 49
  std::vector<LP::Col> x(10);
50 50
  //  for(int i=0;i<10;i++) x.push_back(lp.addCol());
51 51
  lp.addColSet(x);
52 52
  lp.colLowerBound(x,1);
53 53
  lp.colUpperBound(x,1);
54 54
  lp.colBounds(x,1,2);
55 55

	
56 56
  std::vector<LP::Col> y(10);
57 57
  lp.addColSet(y);
58 58

	
59 59
  lp.colLowerBound(y,1);
60 60
  lp.colUpperBound(y,1);
61 61
  lp.colBounds(y,1,2);
62 62

	
63 63
  std::map<int,LP::Col> z;
64 64

	
65 65
  z.insert(std::make_pair(12,INVALID));
66 66
  z.insert(std::make_pair(2,INVALID));
67 67
  z.insert(std::make_pair(7,INVALID));
68 68
  z.insert(std::make_pair(5,INVALID));
69 69

	
70 70
  lp.addColSet(z);
71 71

	
72 72
  lp.colLowerBound(z,1);
73 73
  lp.colUpperBound(z,1);
74 74
  lp.colBounds(z,1,2);
75 75

	
76 76
  {
77 77
    LP::Expr e,f,g;
78 78
    LP::Col p1,p2,p3,p4,p5;
79 79
    LP::Constr c;
80 80

	
81 81
    p1=lp.addCol();
82 82
    p2=lp.addCol();
83 83
    p3=lp.addCol();
84 84
    p4=lp.addCol();
85 85
    p5=lp.addCol();
86 86

	
87 87
    e[p1]=2;
88 88
    *e=12;
89 89
    e[p1]+=2;
90 90
    *e+=12;
91 91
    e[p1]-=2;
92 92
    *e-=12;
93 93

	
94 94
    e=2;
95 95
    e=2.2;
96 96
    e=p1;
97 97
    e=f;
98 98

	
99 99
    e+=2;
100 100
    e+=2.2;
101 101
    e+=p1;
102 102
    e+=f;
103 103

	
104 104
    e-=2;
105 105
    e-=2.2;
106 106
    e-=p1;
107 107
    e-=f;
108 108

	
109 109
    e*=2;
110 110
    e*=2.2;
111 111
    e/=2;
112 112
    e/=2.2;
113 113

	
114 114
    e=((p1+p2)+(p1-p2)+(p1+12)+(12+p1)+(p1-12)+(12-p1)+
115 115
       (f+12)+(12+f)+(p1+f)+(f+p1)+(f+g)+
116 116
       (f-12)+(12-f)+(p1-f)+(f-p1)+(f-g)+
117 117
       2.2*f+f*2.2+f/2.2+
118 118
       2*f+f*2+f/2+
119 119
       2.2*p1+p1*2.2+p1/2.2+
120 120
       2*p1+p1*2+p1/2
121 121
       );
122 122

	
123 123

	
124 124
    c = (e  <= f  );
125 125
    c = (e  <= 2.2);
126 126
    c = (e  <= 2  );
127 127
    c = (e  <= p1 );
128 128
    c = (2.2<= f  );
129 129
    c = (2  <= f  );
130 130
    c = (p1 <= f  );
131 131
    c = (p1 <= p2 );
132 132
    c = (p1 <= 2.2);
133 133
    c = (p1 <= 2  );
134 134
    c = (2.2<= p2 );
135 135
    c = (2  <= p2 );
136 136

	
137 137
    c = (e  >= f  );
138 138
    c = (e  >= 2.2);
139 139
    c = (e  >= 2  );
140 140
    c = (e  >= p1 );
141 141
    c = (2.2>= f  );
142 142
    c = (2  >= f  );
143 143
    c = (p1 >= f  );
144 144
    c = (p1 >= p2 );
145 145
    c = (p1 >= 2.2);
146 146
    c = (p1 >= 2  );
147 147
    c = (2.2>= p2 );
148 148
    c = (2  >= p2 );
149 149

	
150 150
    c = (e  == f  );
151 151
    c = (e  == 2.2);
152 152
    c = (e  == 2  );
153 153
    c = (e  == p1 );
154 154
    c = (2.2== f  );
155 155
    c = (2  == f  );
156 156
    c = (p1 == f  );
157 157
    //c = (p1 == p2 );
158 158
    c = (p1 == 2.2);
159 159
    c = (p1 == 2  );
160 160
    c = (2.2== p2 );
161 161
    c = (2  == p2 );
162 162

	
163 163
    c = ((2 <= e) <= 3);
164 164
    c = ((2 <= p1) <= 3);
165 165

	
166 166
    c = ((2 >= e) >= 3);
167 167
    c = ((2 >= p1) >= 3);
168 168

	
169 169
    { //Tests for #430
170 170
      LP::Col v=lp.addCol();
171 171
      LP::Constr c = v >= -3;
172 172
      c = c <= 4;
173 173
      LP::Constr c2;
174 174
      c2 = -3 <= v <= 4;
175 175
    }
176 176

	
177 177
    e[x[3]]=2;
178 178
    e[x[3]]=4;
179 179
    e[x[3]]=1;
180 180
    *e=12;
181 181

	
182 182
    lp.addRow(-LP::INF,e,23);
183 183
    lp.addRow(-LP::INF,3.0*(x[1]+x[2]/2)-x[3],23);
184 184
    lp.addRow(-LP::INF,3.0*(x[1]+x[2]*2-5*x[3]+12-x[4]/3)+2*x[4]-4,23);
185 185

	
186 186
    lp.addRow(x[1]+x[3]<=x[5]-3);
187 187
    lp.addRow((-7<=x[1]+x[3]-12)<=3);
188 188
    lp.addRow(x[1]<=x[5]);
189 189

	
190 190
    std::ostringstream buf;
191 191

	
192 192

	
193 193
    e=((p1+p2)+(p1-0.99*p2));
194 194
    //e.prettyPrint(std::cout);
195 195
    //(e<=2).prettyPrint(std::cout);
196 196
    double tolerance=0.001;
197 197
    e.simplify(tolerance);
198 198
    buf << "Coeff. of p2 should be 0.01";
199 199
    check(e[p2]>0, buf.str());
200 200

	
201 201
    tolerance=0.02;
202 202
    e.simplify(tolerance);
203 203
    buf << "Coeff. of p2 should be 0";
204 204
    check(const_cast<const LpSolver::Expr&>(e)[p2]==0, buf.str());
205 205

	
206 206
    //Test for clone/new
207 207
    LP* lpnew = lp.newSolver();
208 208
    LP* lpclone = lp.cloneSolver();
209 209
    delete lpnew;
210 210
    delete lpclone;
211 211

	
212 212
  }
213 213

	
214 214
  {
215 215
    LP::DualExpr e,f,g;
216 216
    LP::Row p1 = INVALID, p2 = INVALID, p3 = INVALID,
217 217
      p4 = INVALID, p5 = INVALID;
218 218

	
219 219
    e[p1]=2;
220 220
    e[p1]+=2;
221 221
    e[p1]-=2;
222 222

	
223 223
    e=p1;
224 224
    e=f;
225 225

	
226 226
    e+=p1;
227 227
    e+=f;
228 228

	
229 229
    e-=p1;
230 230
    e-=f;
231 231

	
232 232
    e*=2;
233 233
    e*=2.2;
234 234
    e/=2;
235 235
    e/=2.2;
236 236

	
237 237
    e=((p1+p2)+(p1-p2)+
238 238
       (p1+f)+(f+p1)+(f+g)+
239 239
       (p1-f)+(f-p1)+(f-g)+
240 240
       2.2*f+f*2.2+f/2.2+
241 241
       2*f+f*2+f/2+
242 242
       2.2*p1+p1*2.2+p1/2.2+
243 243
       2*p1+p1*2+p1/2
244 244
       );
245 245
  }
246 246

	
247 247
}
248 248

	
249 249
void solveAndCheck(LpSolver& lp, LpSolver::ProblemType stat,
250 250
                   double exp_opt) {
251 251
  using std::string;
252 252
  lp.solve();
253 253

	
254 254
  std::ostringstream buf;
255 255
  buf << "PrimalType should be: " << int(stat) << int(lp.primalType());
256 256

	
257 257
  check(lp.primalType()==stat, buf.str());
258 258

	
259 259
  if (stat ==  LpSolver::OPTIMAL) {
260 260
    std::ostringstream sbuf;
261 261
    sbuf << "Wrong optimal value (" << lp.primal() <<") with "
262 262
         << lp.solverName() <<"\n     the right optimum is " << exp_opt;
263 263
    check(std::abs(lp.primal()-exp_opt) < 1e-3, sbuf.str());
264 264
  }
265 265
}
266 266

	
267 267
void aTest(LpSolver & lp)
268 268
{
269 269
  typedef LpSolver LP;
270 270

	
271 271
 //The following example is very simple
272 272

	
273 273
  typedef LpSolver::Row Row;
274 274
  typedef LpSolver::Col Col;
275 275

	
276 276

	
277 277
  Col x1 = lp.addCol();
278 278
  Col x2 = lp.addCol();
279 279

	
280 280

	
281 281
  //Constraints
282 282
  Row upright=lp.addRow(x1+2*x2 <=1);
283 283
  lp.addRow(x1+x2 >=-1);
284 284
  lp.addRow(x1-x2 <=1);
285 285
  lp.addRow(x1-x2 >=-1);
286 286
  //Nonnegativity of the variables
287 287
  lp.colLowerBound(x1, 0);
288 288
  lp.colLowerBound(x2, 0);
289 289
  //Objective function
290 290
  lp.obj(x1+x2);
291 291

	
292 292
  lp.sense(lp.MAX);
293 293

	
294 294
  //Testing the problem retrieving routines
295 295
  check(lp.objCoeff(x1)==1,"First term should be 1 in the obj function!");
296 296
  check(lp.sense() == lp.MAX,"This is a maximization!");
297 297
  check(lp.coeff(upright,x1)==1,"The coefficient in question is 1!");
298 298
  check(lp.colLowerBound(x1)==0,
299 299
        "The lower bound for variable x1 should be 0.");
300 300
  check(lp.colUpperBound(x1)==LpSolver::INF,
301 301
        "The upper bound for variable x1 should be infty.");
302 302
  check(lp.rowLowerBound(upright) == -LpSolver::INF,
303 303
        "The lower bound for the first row should be -infty.");
304 304
  check(lp.rowUpperBound(upright)==1,
305 305
        "The upper bound for the first row should be 1.");
306 306
  LpSolver::Expr e = lp.row(upright);
307 307
  check(e[x1] == 1, "The first coefficient should 1.");
308 308
  check(e[x2] == 2, "The second coefficient should 1.");
309 309

	
310 310
  lp.row(upright, x1+x2 <=1);
311 311
  e = lp.row(upright);
312 312
  check(e[x1] == 1, "The first coefficient should 1.");
313 313
  check(e[x2] == 1, "The second coefficient should 1.");
314 314

	
315 315
  LpSolver::DualExpr de = lp.col(x1);
316 316
  check(  de[upright] == 1, "The first coefficient should 1.");
317 317

	
318 318
  LpSolver* clp = lp.cloneSolver();
319 319

	
320 320
  //Testing the problem retrieving routines
321 321
  check(clp->objCoeff(x1)==1,"First term should be 1 in the obj function!");
322 322
  check(clp->sense() == clp->MAX,"This is a maximization!");
323 323
  check(clp->coeff(upright,x1)==1,"The coefficient in question is 1!");
324 324
  //  std::cout<<lp.colLowerBound(x1)<<std::endl;
325 325
  check(clp->colLowerBound(x1)==0,
326 326
        "The lower bound for variable x1 should be 0.");
327 327
  check(clp->colUpperBound(x1)==LpSolver::INF,
328 328
        "The upper bound for variable x1 should be infty.");
329 329

	
330 330
  check(lp.rowLowerBound(upright)==-LpSolver::INF,
331 331
        "The lower bound for the first row should be -infty.");
332 332
  check(lp.rowUpperBound(upright)==1,
333 333
        "The upper bound for the first row should be 1.");
334 334
  e = clp->row(upright);
335 335
  check(e[x1] == 1, "The first coefficient should 1.");
336 336
  check(e[x2] == 1, "The second coefficient should 1.");
337 337

	
338 338
  de = clp->col(x1);
339 339
  check(de[upright] == 1, "The first coefficient should 1.");
340 340

	
341 341
  delete clp;
342 342

	
343 343
  //Maximization of x1+x2
344 344
  //over the triangle with vertices (0,0) (0,1) (1,0)
345 345
  double expected_opt=1;
346 346
  solveAndCheck(lp, LpSolver::OPTIMAL, expected_opt);
347 347

	
348 348
  //Minimization
349 349
  lp.sense(lp.MIN);
350 350
  expected_opt=0;
351 351
  solveAndCheck(lp, LpSolver::OPTIMAL, expected_opt);
352 352

	
353 353
  //Vertex (-1,0) instead of (0,0)
354 354
  lp.colLowerBound(x1, -LpSolver::INF);
355 355
  expected_opt=-1;
356 356
  solveAndCheck(lp, LpSolver::OPTIMAL, expected_opt);
357 357

	
358 358
  //Erase one constraint and return to maximization
359 359
  lp.erase(upright);
360 360
  lp.sense(lp.MAX);
361 361
  expected_opt=LpSolver::INF;
362 362
  solveAndCheck(lp, LpSolver::UNBOUNDED, expected_opt);
363 363

	
364 364
  //Infeasibilty
365 365
  lp.addRow(x1+x2 <=-2);
366 366
  solveAndCheck(lp, LpSolver::INFEASIBLE, expected_opt);
367 367

	
368 368
}
369 369

	
370 370
template<class LP>
371 371
void cloneTest()
372 372
{
373 373
  //Test for clone/new
374 374

	
375 375
  LP* lp = new LP();
376 376
  LP* lpnew = lp->newSolver();
377 377
  LP* lpclone = lp->cloneSolver();
378 378
  delete lp;
379 379
  delete lpnew;
380 380
  delete lpclone;
381 381
}
382 382

	
383 383
int main()
384 384
{
385 385
  LpSkeleton lp_skel;
386 386
  lpTest(lp_skel);
387 387

	
388 388
#ifdef LEMON_HAVE_GLPK
389 389
  {
0 comments (0 inline)