Scippy

SoPlex

Sequential object-oriented simPlex

spxpricer.h
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the class library */
4 /* SoPlex --- the Sequential object-oriented simPlex. */
5 /* */
6 /* Copyright (C) 1996-2015 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SoPlex is distributed under the terms of the ZIB Academic Licence. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SoPlex; see the file COPYING. If not email to soplex@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 
17 /**@file spxpricer.h
18  * @brief Abstract pricer base class.
19  */
20 #ifndef _SPXPRICE_H_
21 #define _SPXPRICE_H_
22 
23 #include <assert.h>
24 
25 #include "spxdefines.h"
26 #include "spxsolver.h"
27 #include "sorter.h"
28 
29 namespace soplex
30 {
31 
32 /**@brief Abstract pricer base class.
33  @ingroup Algo
34 
35  Class SPxPricer is a pure virtual class defining the interface for pricer
36  classes to be used by SoPlex. The pricer's task is to select a vector to
37  enter or leave the simplex basis, depending on the chosen simplex type.
38 
39  An SPxPricer first #load%s the SoPlex object for which pricing is to
40  be performed. Then, depending of the SPxSolver::Type, methods
41  #selectEnter() and #entered4() (for entering Simplex) or #selectLeave()
42  and #left4() (for leaving Simplex) are called by SoPlex. The SPxPricer
43  object is informed of a change of the SPxSolver::Type by calling method
44  #setType().
45 */
46 class SPxPricer
47 {
48 protected:
49 
50  //-------------------------------------
51  /**@name Data */
52  //@{
53  /// name of the pricer
54  const char* m_name;
55  /// the solver
57  /// violation bound
59  /// vector to store pricing weights or norms
62  /// are the weights already set up?
64  //@}
65 
66 
67  struct IdxElement
68  {
69  int idx;
71  };
72 
73  /// Compare class to sort idx/val pairs, used for hypersparse pricing leaving
74  struct IdxCompare
75  {
76  public:
77  /// constructor
79  : elements(0)
80  {}
81 
83 
85  IdxElement a,
86  IdxElement b
87  ) const
88  {
89  return b.val - a.val;
90  }
91  };
92 
94 
95 public:
96 
97  // violation types used for (hyper) sparse pricing
99  {
101  VIOLATED = 1,
103  };
104 
105  //-------------------------------------
106  /**@name Initialization */
107  //@{
108  /// get name of pricer.
109  virtual const char* getName() const
110  {
111  return m_name;
112  }
113 
114  /// loads LP.
115  /** Loads the solver and LP for which pricing steps are to be performed.
116  */
117  virtual void load(SPxSolver* p_solver)
118  {
119  thesolver = p_solver;
120  }
121 
122  /// unloads LP.
123  virtual void clear()
124  {
125  thesolver = 0;
126  }
127 
128  /// returns loaded SPxSolver object.
129  virtual SPxSolver* solver() const
130  {
131  return thesolver;
132  }
133 
134  /// returns violation bound \ref soplex::SPxPricer::theeps "theeps".
135  virtual Real epsilon() const
136  {
137  return theeps;
138  }
139 
140  /// sets violation bound.
141  /** Inequality violations are accepted, if their size is less than \p eps.
142  */
143  virtual void setEpsilon(Real eps)
144  {
145  assert(eps >= 0.0);
146 
147  theeps = eps;
148  }
149 
150  /// sets pricing type.
151  /** Informs pricer about (a change of) the loaded SoPlex's Type. In
152  the sequel, only the corresponding select methods may be called.
153  */
154  virtual void setType(SPxSolver::Type)
155  {}
156 
157  /// sets basis representation.
158  /** Informs pricer about (a change of) the loaded SoPlex's
159  Representation.
160  */
162  {}
163  //@}
164 
165  //-------------------------------------
166  /**@name Pivoting */
167  //@{
168  /// returns selected index to leave basis.
169  /** Selects the index of a vector to leave the basis. The selected index
170  i, say, must be in the range 0 <= i < solver()->dim() and its
171  tested value must fullfill solver()->test()[i] < -#epsilon().
172  */
173  virtual int selectLeave() = 0;
174 
175  /// performs leaving pivot.
176  /** Method #left4() is called after each simplex iteration in LEAVE
177  mode. It informs the SPxPricer that the \p n 'th variable has left
178  the basis for \p id to come in at this position. When being called,
179  all vectors of SoPlex involved in such an entering update are
180  setup correctly and may be accessed via the corresponding methods
181  (\ref SPxSolver::fVec() "fVec()", \ref SPxSolver::pVec() "pVec()",
182  etc.). In general, argument \p n will be the one returned by the
183  SPxPricer at the previous call to #selectLeave(). However, one can not
184  rely on this.
185  */
186  virtual void left4(int /*n*/, SPxId /*id*/) {}
187 
188  /// selects Id to enter basis.
189  /** Selects the SPxId of a vector to enter the basis. The selected
190  id, must not represent a basic index (i.e. solver()->isBasic(id) must
191  be false). However, the corresponding test value needs not to be less
192  than -#epsilon(). If not, SoPlex will discard the pivot.
193 
194  Note:
195  When method #selectEnter() is called by the loaded SoPlex
196  object, all values from \ref SPxSolver::coTest() "coTest()" are
197  up to date. However, whether the elements of
198  \ref SPxSolver::test() "test()" are up to date depends on the
199  SPxSolver::Pricing type.
200  */
201  virtual SPxId selectEnter() = 0;
202 
203  /// performs entering pivot.
204  /** Method #entered4() is called after each simplex iteration in ENTER
205  mode. It informs the SPxPricer that variable \p id has entered
206  at the \p n 'th position. When being called, all vectors of SoPlex
207  involved in such an entering update are setup correctly and may be
208  accessed via the corresponding methods
209  (\ref SPxSolver::fVec() "fVec()", \ref SPxSolver::pVec() "pVec()",
210  etc.). In general, argument \p id will be the one returned by the
211  SPxPricer at the previous call to #selectEnter(). However, one can not
212  rely on this.
213  */
214  virtual void entered4(SPxId /*id*/, int /*n*/)
215  {}
216  //@}
217 
218 
219  //-------------------------------------
220  /**@name Extension */
221  //@{
222  /// \p n vectors have been added to loaded LP.
223  virtual void addedVecs (int /*n*/)
224  {}
225  /// \p n covectors have been added to loaded LP.
226  virtual void addedCoVecs(int /*n*/)
227  {}
228  //@}
229 
230  //-------------------------------------
231  /**@name Shrinking */
232  //@{
233  /// vector \p i was removed from loaded LP.
234  virtual void removedVec(int /*i*/)
235  {}
236  /// vectors given by \p perm have been removed from loaded LP.
237  virtual void removedVecs(const int* /*perm*/)
238  {}
239  /// covector \p i was removed from loaded LP.
240  virtual void removedCoVec(int /*i*/)
241  {}
242  /// covectors given by \p perm have been removed from loaded LP.
243  virtual void removedCoVecs(const int* /*perm*/)
244  {}
245  //@}
246 
247  /**@name Import/Export norms */
248  //@{
249  /// get number of available norms
250  virtual void getNdualNorms(int& nrows, int& ncols) const
251  {
252  nrows = 0;
253  ncols = 0;
254 
255  if( weightsAreSetup )
256  {
258  {
259  ncols = 0;
260  nrows = coWeights.dim();
261 
262  assert(nrows == thesolver->dim());
263  }
264  else if( thesolver->type() == SPxSolver::ENTER && thesolver->rep() == SPxSolver::ROW )
265  {
266  nrows = weights.dim();
267  ncols = coWeights.dim();
268 
269  assert(ncols == thesolver->dim());
270  assert(nrows == thesolver->coDim());
271  }
272  }
273  }
274 
275  /// export norms from pricer
276  virtual bool getDualNorms(int& nrows, int& ncols, Real* norms) const
277  {
278  nrows = 0;
279  ncols = 0;
280 
281  if( !weightsAreSetup )
282  return false;
283 
285  {
286  ncols = 0;
287  nrows = coWeights.dim();
288 
289  assert(nrows == thesolver->dim());
290 
291  for( int i = 0; i < nrows; ++i)
292  norms[i] = coWeights[i];
293  }
294  else if( thesolver->type() == SPxSolver::ENTER && thesolver->rep() == SPxSolver::ROW )
295  {
296  nrows = weights.dim();
297  ncols = coWeights.dim();
298 
299  assert(ncols == thesolver->dim());
300  assert(nrows == thesolver->coDim());
301 
302  for( int i = 0; i < nrows; ++i )
303  norms[i] = weights[i];
304 
305  for( int i = 0; i < ncols; ++i )
306  norms[nrows + i] = coWeights[i];
307  }
308  else
309  return false;
310 
311  return true;
312  }
313  /// import norms into pricer
314  virtual bool setDualNorms(int nrows, int ncols, Real* norms)
315  {
317  {
318  assert(coWeights.dim() >= nrows);
319  for( int i = 0; i < nrows; ++i )
320  coWeights[i] = norms[i];
321  weightsAreSetup = true;
322  }
323  else if( thesolver->type() == SPxSolver::ENTER && thesolver->rep() == SPxSolver::ROW)
324  {
325  assert(weights.dim() >= nrows);
326  assert(coWeights.dim() >= ncols);
327  for( int i = 0; i < nrows; ++i )
328  weights[i] = norms[i];
329  for( int i = 0; i < ncols; ++i )
330  coWeights[i] = norms[nrows + i];
331  weightsAreSetup = true;
332  }
333  else
334  {
335  weightsAreSetup = false;
336  return false;
337  }
338 
339  return true;
340  }
341  //@}
342 
343  //-------------------------------------
344  /**@name Debugging */
345  //@{
346  virtual bool isConsistent() const
347  {
348 #ifdef ENABLE_CONSISTENCY_CHECKS
349  return thesolver != 0;
350 #else
351  return true;
352 #endif
353  }
354  //@}
355 
356  //-------------------------------------
357  /**@name Constructors / Destructors */
358  //@{
359  /// constructor
360  explicit SPxPricer(const char* p_name)
361  : m_name(p_name)
362  , thesolver(0)
363  , theeps(0.0)
364  , weights(0)
365  , coWeights(0)
366  , weightsAreSetup(false)
367  {}
368 
369  /// copy constructor
370  SPxPricer(const SPxPricer& old)
371  : m_name(old.m_name)
372  , thesolver(old.thesolver)
373  , theeps(old.theeps)
374  , weights(old.weights)
375  , coWeights(old.coWeights)
377  {}
378 
379  /// assignment operator
381  {
382  if(this != &rhs)
383  {
384  m_name = rhs.m_name;
385  thesolver = rhs.thesolver;
386  theeps = rhs.theeps;
387  weights = rhs.weights;
388  coWeights = rhs.coWeights;
390 
391  assert(isConsistent());
392  }
393 
394  return *this;
395  }
396 
397  /// destructor.
398  virtual ~SPxPricer()
399  {
400  m_name = 0;
401  thesolver = 0;
402  }
403 
404  /// clone function for polymorphism
405  virtual SPxPricer* clone() const = 0;
406  //@}
407 
408 };
409 
410 
411 } // namespace soplex
412 #endif // _SPXPRICER_H_