athos@1247
|
1 |
/* -*- C++ -*-
|
alpar@1253
|
2 |
* src/lemon/lp_base.h - Part of LEMON, a generic C++ optimization library
|
athos@1247
|
3 |
*
|
athos@1247
|
4 |
* Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
|
athos@1247
|
5 |
* (Egervary Combinatorial Optimization Research Group, EGRES).
|
athos@1247
|
6 |
*
|
athos@1247
|
7 |
* Permission to use, modify and distribute this software is granted
|
athos@1247
|
8 |
* provided that this copyright notice appears in all copies. For
|
athos@1247
|
9 |
* precise terms see the accompanying LICENSE file.
|
athos@1247
|
10 |
*
|
athos@1247
|
11 |
* This software is provided "AS IS" with no warranty of any kind,
|
athos@1247
|
12 |
* express or implied, and with no claim as to its suitability for any
|
athos@1247
|
13 |
* purpose.
|
athos@1247
|
14 |
*
|
athos@1247
|
15 |
*/
|
athos@1247
|
16 |
|
athos@1246
|
17 |
#ifndef LEMON_LP_BASE_H
|
athos@1246
|
18 |
#define LEMON_LP_BASE_H
|
athos@1246
|
19 |
|
alpar@1253
|
20 |
#include<vector>
|
alpar@1253
|
21 |
|
alpar@1253
|
22 |
#include<lemon/error.h>
|
alpar@1253
|
23 |
|
alpar@1253
|
24 |
#include"lin_expr.h"
|
athos@1246
|
25 |
///\file
|
athos@1246
|
26 |
///\brief The interface of the LP solver interface.
|
athos@1246
|
27 |
namespace lemon {
|
alpar@1253
|
28 |
|
alpar@1253
|
29 |
///Internal data structure to convert floating id's to fix one's
|
alpar@1253
|
30 |
|
alpar@1253
|
31 |
///\todo This might by implemented to be usable in other places.
|
alpar@1253
|
32 |
class _FixId
|
alpar@1253
|
33 |
{
|
alpar@1253
|
34 |
std::vector<int> index;
|
alpar@1253
|
35 |
std::vector<int> cross;
|
alpar@1253
|
36 |
int first_free;
|
alpar@1253
|
37 |
public:
|
alpar@1253
|
38 |
_FixId() : first_free(-1) {};
|
alpar@1253
|
39 |
///Convert a floating id to a fix one
|
alpar@1253
|
40 |
|
alpar@1253
|
41 |
///\param n is a floating id
|
alpar@1253
|
42 |
///\return the corresponding fix id
|
alpar@1253
|
43 |
int fixId(int n) {return cross[n];}
|
alpar@1253
|
44 |
///Convert a fix id to a floating one
|
alpar@1253
|
45 |
|
alpar@1253
|
46 |
///\param n is a fix id
|
alpar@1253
|
47 |
///\return the corresponding floating id
|
alpar@1253
|
48 |
int floatingId(int n) { return index[n];}
|
alpar@1253
|
49 |
///Add a new floating id.
|
alpar@1253
|
50 |
|
alpar@1253
|
51 |
///\param n is a floating id
|
alpar@1253
|
52 |
///\return the fix id of the new value
|
alpar@1253
|
53 |
///\todo Multiple additions should also be handled.
|
alpar@1253
|
54 |
int insert(int n)
|
alpar@1253
|
55 |
{
|
alpar@1253
|
56 |
if(n>=int(cross.size())) {
|
alpar@1253
|
57 |
cross.resize(n+1);
|
alpar@1253
|
58 |
if(first_free==-1) {
|
alpar@1253
|
59 |
cross[n]=index.size();
|
alpar@1253
|
60 |
index.push_back(n);
|
alpar@1253
|
61 |
}
|
alpar@1253
|
62 |
else {
|
alpar@1253
|
63 |
cross[n]=first_free;
|
alpar@1253
|
64 |
int next=index[first_free];
|
alpar@1253
|
65 |
index[first_free]=n;
|
alpar@1253
|
66 |
first_free=next;
|
alpar@1253
|
67 |
}
|
alpar@1253
|
68 |
}
|
alpar@1253
|
69 |
else throw LogicError(); //floatingId-s must form a continuous range;
|
alpar@1253
|
70 |
}
|
alpar@1253
|
71 |
///Remove a fix id.
|
alpar@1253
|
72 |
|
alpar@1253
|
73 |
///\param n is a fix id
|
alpar@1253
|
74 |
///
|
alpar@1253
|
75 |
void erase(int n)
|
alpar@1253
|
76 |
{
|
alpar@1253
|
77 |
int fl=index[n];
|
alpar@1253
|
78 |
index[n]=first_free;
|
alpar@1253
|
79 |
first_free=n;
|
alpar@1253
|
80 |
for(int i=fl+1;i<int(cross.size());++i) {
|
alpar@1253
|
81 |
cross[i-1]=cross[i];
|
alpar@1253
|
82 |
index[cross[i]]--;
|
alpar@1253
|
83 |
}
|
alpar@1253
|
84 |
cross.pop_back();
|
alpar@1253
|
85 |
}
|
alpar@1253
|
86 |
///An upper bound on the largest fix id.
|
alpar@1253
|
87 |
|
alpar@1253
|
88 |
///\todo Do we need this?
|
alpar@1253
|
89 |
///
|
alpar@1253
|
90 |
std::size_t maxFixId() { return cross.size()-1; }
|
alpar@1253
|
91 |
|
alpar@1253
|
92 |
};
|
alpar@1253
|
93 |
|
alpar@1253
|
94 |
///Common base class for LP solvers
|
athos@1246
|
95 |
class LpSolverBase {
|
alpar@1253
|
96 |
|
athos@1247
|
97 |
public:
|
athos@1247
|
98 |
|
athos@1247
|
99 |
/// \e
|
athos@1247
|
100 |
typedef double Value;
|
athos@1247
|
101 |
/// \e
|
athos@1247
|
102 |
static const Value INF;
|
alpar@1253
|
103 |
|
alpar@1253
|
104 |
///\e
|
alpar@1253
|
105 |
class Col { protected: int id; friend class LpSolverBase; };
|
alpar@1253
|
106 |
///\e
|
alpar@1253
|
107 |
class Row { protected: int id; friend class LpSolverBase; };
|
alpar@1253
|
108 |
|
alpar@1253
|
109 |
typedef SparseLinExpr<Col, Value> Expr;
|
alpar@1253
|
110 |
|
alpar@1253
|
111 |
protected:
|
alpar@1253
|
112 |
_FixId rows;
|
alpar@1253
|
113 |
_FixId cols;
|
athos@1246
|
114 |
|
athos@1246
|
115 |
//MATRIX MANIPULATING FUNCTIONS
|
athos@1246
|
116 |
|
athos@1246
|
117 |
/// \e
|
athos@1246
|
118 |
virtual int _addCol() = 0;
|
athos@1246
|
119 |
/// \e
|
athos@1246
|
120 |
virtual int _addRow() = 0;
|
athos@1246
|
121 |
/// \e
|
alpar@1253
|
122 |
|
athos@1246
|
123 |
/// \warning Arrays are indexed from 1 (datum at index 0 is ignored)
|
alpar@1253
|
124 |
///
|
athos@1246
|
125 |
virtual void _setRowCoeffs(int i,
|
athos@1251
|
126 |
int length,
|
athos@1247
|
127 |
int const * indices,
|
athos@1247
|
128 |
Value const * values ) = 0;
|
athos@1246
|
129 |
/// \e
|
alpar@1253
|
130 |
|
athos@1246
|
131 |
/// \warning Arrays are indexed from 1 (datum at index 0 is ignored)
|
alpar@1253
|
132 |
///
|
athos@1246
|
133 |
virtual void _setColCoeffs(int i,
|
athos@1251
|
134 |
int length,
|
athos@1247
|
135 |
int const * indices,
|
athos@1247
|
136 |
Value const * values ) = 0;
|
athos@1246
|
137 |
|
athos@1247
|
138 |
/// \e
|
alpar@1253
|
139 |
|
athos@1247
|
140 |
/// The lower bound of a variable (column) have to be given by an
|
athos@1247
|
141 |
/// extended number of type Value, i.e. a finite number of type
|
athos@1247
|
142 |
/// Value or -INF.
|
athos@1247
|
143 |
virtual void _setColLowerBound(int i, Value value) = 0;
|
athos@1247
|
144 |
/// \e
|
alpar@1253
|
145 |
|
athos@1247
|
146 |
/// The upper bound of a variable (column) have to be given by an
|
athos@1247
|
147 |
/// extended number of type Value, i.e. a finite number of type
|
athos@1247
|
148 |
/// Value or INF.
|
athos@1247
|
149 |
virtual void _setColUpperBound(int i, Value value) = 0;
|
athos@1247
|
150 |
/// \e
|
alpar@1253
|
151 |
|
athos@1247
|
152 |
/// The lower bound of a linear expression (row) have to be given by an
|
athos@1247
|
153 |
/// extended number of type Value, i.e. a finite number of type
|
athos@1247
|
154 |
/// Value or -INF.
|
athos@1247
|
155 |
virtual void _setRowLowerBound(int i, Value value) = 0;
|
athos@1247
|
156 |
/// \e
|
alpar@1253
|
157 |
|
athos@1247
|
158 |
/// The upper bound of a linear expression (row) have to be given by an
|
athos@1247
|
159 |
/// extended number of type Value, i.e. a finite number of type
|
athos@1247
|
160 |
/// Value or INF.
|
athos@1247
|
161 |
virtual void _setRowUpperBound(int i, Value value) = 0;
|
athos@1247
|
162 |
|
athos@1247
|
163 |
/// \e
|
athos@1247
|
164 |
virtual void _setObjCoeff(int i, Value obj_coef) = 0;
|
alpar@1253
|
165 |
|
alpar@1253
|
166 |
///\e
|
alpar@1253
|
167 |
|
alpar@1253
|
168 |
///\bug unimplemented!!!!
|
alpar@1253
|
169 |
void clearObj() {}
|
alpar@1253
|
170 |
public:
|
alpar@1253
|
171 |
|
alpar@1253
|
172 |
|
alpar@1253
|
173 |
///\e
|
alpar@1253
|
174 |
virtual ~LpSolverBase() {}
|
alpar@1253
|
175 |
|
alpar@1253
|
176 |
///Add a new empty column (i.e a new variable) to the LP
|
alpar@1253
|
177 |
Col addCol() { Col c; c.id=cols.insert(_addCol()); return c;}
|
alpar@1253
|
178 |
///Add a new empty row (i.e a new constaint) to the LP
|
alpar@1253
|
179 |
Row addRow() { Row r; r.id=rows.insert(_addRow()); return r;}
|
alpar@1253
|
180 |
|
alpar@1253
|
181 |
///Add a new row (i.e a new constaint) to the LP
|
alpar@1253
|
182 |
|
alpar@1253
|
183 |
///\param l lower bound (-INF means no bound)
|
alpar@1253
|
184 |
///\param e a linear expression (see \ref Expr)
|
alpar@1253
|
185 |
///\param u upper bound (INF means no bound)
|
alpar@1253
|
186 |
///\bug This is a temportary function. The interface will change to
|
alpar@1253
|
187 |
///a better one.
|
alpar@1253
|
188 |
Row addRow(Value l,Expr e, Value u) {
|
alpar@1253
|
189 |
Row r=addRow();
|
alpar@1253
|
190 |
std::vector<int> indices;
|
alpar@1253
|
191 |
std::vector<Value> values;
|
alpar@1253
|
192 |
indices.push_back(0);
|
alpar@1253
|
193 |
values.push_back(0);
|
alpar@1253
|
194 |
for(Expr::iterator i=e.begin(); i!=e.end(); ++i) {
|
alpar@1253
|
195 |
indices.push_back(cols.floatingId((*i).first.id));
|
alpar@1253
|
196 |
values.push_back((*i).second);
|
alpar@1253
|
197 |
}
|
alpar@1253
|
198 |
_setRowCoeffs(rows.floatingId(r.id),indices.size()-1,
|
alpar@1253
|
199 |
&indices[0],&values[0]);
|
alpar@1253
|
200 |
_setRowLowerBound(rows.floatingId(r.id),l);
|
alpar@1253
|
201 |
_setRowUpperBound(rows.floatingId(r.id),l);
|
alpar@1253
|
202 |
return r;
|
alpar@1253
|
203 |
}
|
alpar@1253
|
204 |
|
alpar@1253
|
205 |
/// Set the lower bound of a column (i.e a variable)
|
alpar@1253
|
206 |
|
alpar@1253
|
207 |
/// The upper bound of a variable (column) have to be given by an
|
alpar@1253
|
208 |
/// extended number of type Value, i.e. a finite number of type
|
alpar@1253
|
209 |
/// Value or -INF.
|
alpar@1253
|
210 |
virtual void setColLowerBound(Col c, Value value) {
|
alpar@1253
|
211 |
_setColLowerBound(cols.floatingId(c.id),value);
|
alpar@1253
|
212 |
}
|
alpar@1253
|
213 |
/// Set the upper bound of a column (i.e a variable)
|
alpar@1253
|
214 |
|
alpar@1253
|
215 |
/// The upper bound of a variable (column) have to be given by an
|
alpar@1253
|
216 |
/// extended number of type Value, i.e. a finite number of type
|
alpar@1253
|
217 |
/// Value or INF.
|
alpar@1253
|
218 |
virtual void setColUpperBound(Col c, Value value) {
|
alpar@1253
|
219 |
_setColUpperBound(cols.floatingId(c.id),value);
|
alpar@1253
|
220 |
};
|
alpar@1253
|
221 |
/// Set the lower bound of a row (i.e a constraint)
|
alpar@1253
|
222 |
|
alpar@1253
|
223 |
/// The lower bound of a linear expression (row) have to be given by an
|
alpar@1253
|
224 |
/// extended number of type Value, i.e. a finite number of type
|
alpar@1253
|
225 |
/// Value or -INF.
|
alpar@1253
|
226 |
virtual void setRowLowerBound(Row r, Value value) {
|
alpar@1253
|
227 |
_setRowLowerBound(rows.floatingId(r.id),value);
|
alpar@1253
|
228 |
};
|
alpar@1253
|
229 |
/// Set the upper bound of a row (i.e a constraint)
|
alpar@1253
|
230 |
|
alpar@1253
|
231 |
/// The upper bound of a linear expression (row) have to be given by an
|
alpar@1253
|
232 |
/// extended number of type Value, i.e. a finite number of type
|
alpar@1253
|
233 |
/// Value or INF.
|
alpar@1253
|
234 |
virtual void setRowUpperBound(Row r, Value value) {
|
alpar@1253
|
235 |
_setRowUpperBound(rows.floatingId(r.id),value);
|
alpar@1253
|
236 |
};
|
alpar@1253
|
237 |
///Set an element of the objective function
|
alpar@1253
|
238 |
void setObjCoeff(Col c, Value v) {_setObjCoeff(cols.floatingId(c.id),v); };
|
alpar@1253
|
239 |
///Set the objective function
|
alpar@1253
|
240 |
|
alpar@1253
|
241 |
///\param e is a linear expression of type \ref Expr.
|
alpar@1253
|
242 |
///\todo What to do with the constant component?
|
alpar@1253
|
243 |
void setObj(Expr e) {
|
alpar@1253
|
244 |
clearObj();
|
alpar@1253
|
245 |
for (Expr::iterator i=e.begin(); i!=e.end(); ++i)
|
alpar@1253
|
246 |
setObjCoeff((*i).first,(*i).second);
|
alpar@1253
|
247 |
}
|
alpar@1253
|
248 |
|
athos@1248
|
249 |
};
|
athos@1246
|
250 |
|
athos@1246
|
251 |
} //namespace lemon
|
athos@1246
|
252 |
|
athos@1246
|
253 |
#endif //LEMON_LP_BASE_H
|