source: trunk/Docs/notsobasic.xml @ 411

Last change on this file since 411 was 408, checked in by ddelanu, 16 years ago

Candidate for User Guide revision 0.3, which is to be the first world-wide release

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.6 KB
1<?xml version="1.0" encoding="ISO-8859-1"?>
2  <chapter id="notsobasic">
3  <title>
4  Not-Quite-So-Basic Model Classes
5  </title>
6  <section>
7  <title>Pivot Choices</title>
8  <para>
9  In the dual algorithm, any infeasible basic variable may be chosen to leave the
10  basis.  Similarly in the primal algorithm, any non-basic variable with a
11  &quot;bad&quot; reduced cost may be chosen to enter the basis.  This choice is
12  probably the most important factor in determining the number of iterations it
13  will take to solve a problem.  Clp provides a abstract base class for each case
14  and then instances of each.  It is relatively simple for an advanced user to
15  create new instances.
16  </para>
17  <para>
18  For the dual method the base class is <function>ClpDualRowPivot</function>.
19  The two existing instances are <function>ClpDualRowDantzig</function> and
20  <function>ClpDualRowSteepest</function>.  The Dantzig version implements the
21  &quot;standard&quot; pivot rule: choose the  most violated basic variable.  It
22  is easily dominated by the Steepest instance which should normally be used.  The
23  default is to use un-initialized weights where the initial weight for each basic
24  variable is 1.0.  If an all-slack basis is being used then these are the correct
25  weights.  To use a version which calculates the weights, create an instance and
26  pass it to ClpSimplex model as in the following code fragment:
27  </para>
28  <programlisting>
29  ClpDualRowSteepest steep(1); // 0 uninitialized, 1 compute weights
30  model.setDualRowPivotAlgorithm(steep);
31  </programlisting>
32  <para>Similarly for the primal method the base class is
33  <function>ClpPrimalColumnPivot</function>.  The two existing instances are
34  <function>ClpPrimalColumnDantzig</function> and
35  <function>ClpPrimalColumnSteepest</function>.  The Dantzig version implements
36  &quot;standard&quot; pivot rule: choose the most &quot;violated&quot; non-basic
37  variable.  It is dominated by the Steepest instance which should normally be
38  used.  The default is to use exact Devex where the initial weight for each
39  non-basic variable is 1.0.  Unlike for the dual, this is never the same as
40  normal steepest edge.  To use a version which does steepest edge create an
41  instance and pass it to ClpSimplex model as in the following code fragment:
42  </para>
43  <programlisting>
44  ClpPrimalColumnSteepest steep(1); // 0 devex, 1 steepest
45  model.setPrimalColumnPivotAlgorithm(steep);
46  </programlisting>
47  <para>
48  The partial pricing scheme (for long, thin problems) currently does not
49  exist.  This could be implemented by anyone who is interested.
50  </para>
51  </section>
52  <section>
53  <title>Matrix Classes</title>
54  <para>
55  The next abstract class of interest is <function>ClpMatrixBase</function>.
56  CLP encapsulates its knowledge of how a matrix is stored in this class.  The
57  default instance of this is the <function>ClpPackedMatrix</function> class.
58  This is identical in format to <function>CoinPackedMatrix</function>.  The
59  important new methods implemented are for filling a basis, checking validity
60  of elements and faster &quot;times&quot; and &quot;transposeTimes&quot; when
61  the input array is sparse and/or we have a row copy of the matrix.  Advanced
62  users should note that not all methods have to be implemented.  In particular,
63  <function>scaling</function> need not be implemented and
64  <function>reverseOrderedCopy</function> can return <parameter>NULL</parameter>
65  if a row copy does not make sense.
66  </para>
67  <para>
68  In addition to the default class, there are two others at present:
69  <function>ClpPlusMinusOneMatrix</function> and
70  <function>ClpNetworkMatrix</function>.  As the name implies, the first one is
71  useful when all elements are &plusmn;1.  In this case multiplies are not needed
72  and more importantly less memory is used and there are fewer cache misses.  A
73  class for a matrix where all elements are +1 would be trivial to create. If
74  there were fewer than 64000 rows one could even store row indices as shorts
75  etc.
76  </para>
77  <para>
78  The use <function>ClpPlusMinusOneMatrix</function> involves some work as one
79  cannot simply read-in an MPS file.  The keyt is to use
80  <function>loadProblem</function> to pass in a matrix.  So if
81  <varname>matrix</varname> was a <function>CoinPackedMatrix</function> one
82  could do the following:
83  </para>
84  <programlisting>
85  ClpPlusMinusOneMatrix plusMinus(matrix);
86  assert (plusMinus.getIndices()); // would be zero if not +- one
87  model.loadProblem(plusMinus,
88    lowerColumn,upperColumn,objective,
89    lower,upper);
90  </programlisting>
91  <para>
92  <function>ClpNetworkMatrix</function> is similar, but represents a network,
93  thus may only have one element per column.  Fortunately, using is is very
94  easy.  Given <varname>head</varname> and <varname>tail</varname>, one could
95  do the following:
96  </para>
97  <programlisting>
98  ClpNetworkMatrix network(numberColumns,head,tail);
99  model.loadProblem(network,
100    lowerColumn,upperColumn,objective,
101    lower,upper);
102  </programlisting>
103  <para>
104  Actual code is in <filename>COIN/Clp/Test/unitTest.cpp</filename>.  A quick
105  glance at the output of this program shows that use of
106  <function>ClpNetworkMatrix</function> gives much faster run times.  This is
107  not because of storage issues, but because CLP recognizes the network and uses
108  a network basis factorization which is much faster.  However, in this mode CLP
109  is not a genuine network code as it does not take full advantage of the
110  structure by combining operations but it does have the advantage of
111  flexibility.
112  </para>
113  <para>
114  Other instances are possible.  In particular, it should be possible to use the
115  abstract class for column generation or for dynamic matrices which change over
116  time.  Minor modifications may be needed but it should work quite smoothly
117  (there is already a dummy &quot;refresh&quot; method which would be used).
118  </para>
119  </section>
120  <section>
121  <title>Message Handling</title>
122  <para>
123  Strictly speaking, message handling is a general COIN topic, but it won't hurt
124  to repeat a few important things here.
125  </para>
126  <para>
127  A simple user you may wish to turn off some output.  This is done with
128  <function>model.setLogLevel(int&nbsp;value)</function>
129  where 0 gives nothing and each increase in value switches on more
130  messages. See <filename>ClpMessage.cpp</filename>,
131  <filename>CoinMessage.cpp</filename> and <xref linkend="messages"/> to see
132  which messages are at which level.  A more sophisticated user may wish to
133  handle messages in a different way.  This is done using
134  <function>passInMessageHandler</function> with a pointer to a handler of the
135  user's own design.  The simplest case would be to use the default handler but
136  use a constructor which writes to file.  The code would be:
137  </para>
138  <programlisting>
139  FILE * fp; // assumed open
140  CoinMessageHandler handler(fp);
141  model.passInMessageHandler(&amp;handler);
142  </programlisting>
143  <para>
144  A still more sophisticated use would be to write a class derived from
145  <function>CoinMessageHandler</function> and then override the
146  <function>print</function> method.  Below follows an example which would
147  print only a message for optimality (or infeasibility):
148  </para>
149  <example>
150  <title>Sophisticated message handling</title>
151  <programlisting>
152  class DerivedHandler :
153   public CoinMessageHandler {
154   public:
155     virtual int print() ;
156   };
159   int DerivedHandler::print()
160   {
161     if (currentSource()=="Clp") {
162       if (currentMessage().externalNumber()&gt;=0
163       &amp;&amp; currentMessage().externalNumber()&lt;4) {
164         // finished
165         return CoinMessageHandler::print(); // print
166       }
167     }
168     return 0;
169   }
170  </programlisting>
171  </example>
172  </section>
173  </chapter>
Note: See TracBrowser for help on using the repository browser.