Changeset 408


Ignore:
Timestamp:
Aug 19, 2004 1:55:55 PM (16 years ago)
Author:
ddelanu
Message:

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

Location:
trunk/Docs
Files:
3 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Docs/authors.xml

    r405 r408  
    88    Forrest
    99    </surname>
    10     <affiliation>
    11       <orgname>
    12       IBM Research
    13       </orgname>
    14     </affiliation>
    15   </author>
    16   <author>
    17     <firstname>
    18     Robin
    19     </firstname>
    20     <surname>
    21     Lougee-Heimer
    22     </surname>
     10    <email>jjforre@us.ibm.com</email>
    2311    <affiliation>
    2412      <orgname>
     
    3422    de la Nuez
    3523    </surname>
     24    <email>ddelanu@us.ibm.com</email>
    3625    <affiliation>
    3726      <orgname>
    38       Columbia University
     27      Columbia University &amp; IBM Research
     28      </orgname>
     29    </affiliation>
     30  </author>
     31  <author>
     32    <firstname>
     33    Robin
     34    </firstname>
     35    <surname>
     36    Lougee-Heimer
     37    </surname>
     38    <email>robinlh@us.ibm.com</email>
     39    <affiliation>
     40      <orgname>
     41      IBM Research
    3942      </orgname>
    4043    </affiliation>
  • trunk/Docs/basicmodelclasses.xml

    r405 r408  
    11<?xml version="1.0" encoding="ISO-8859-1"?>
    2   <chapter>
     2  <chapter id="basicmodelclasses">
    33  <title>
    44  Basic Model Classes
     
    1414  model (aka, a problem instance). The third level is less model and more
    1515  algorithmic.  There is a fourth level (for models with more general
    16   objectives than linear ones), but beyond the current scope of this document. 
     16  objectives than linear ones), but it is beyond the current scope of this
     17  document. 
    1718  </para>
    1819  <mediaobject>
     20    <!-- Caption doesn't line-up nicely in HTML, leave out for now
     21    <caption align="top">
     22      <para>
     23        CLP Basic Classes
     24      </para>
     25    </caption>
     26    -->
    1927    <imageobject>
    2028      <imagedata fileref="figures/clpbasicmodelhier.gif" format="GIF"/>
    2129    </imageobject>
    22     <caption>
    23       <para>
    24         CLP Basic Classes
    25       </para>
    26     </caption>
    2730  </mediaobject>
    2831  <para>
    29   ClpModel has all problem data.  There may be a few pieces of data which could
    30   be elsewhere but which are permanent and so they are here.  The main example
    31   of this is a status array which makes most sense for Simplex but has use for
    32   crossing over from any solution.
     32  The class ClpModel contains all problem data.  There may be a few pieces of
     33  data which could be elsewhere but which are permanent and so they are here.
     34  The main example of this is a status array: it makes the most sense for
     35  Simplex but has use for crossing over from any solution.
    3336  </para>
    3437  <para>
    3538  ClpSimplex inherits from ClpModel, as does ClpInterior.  Extra data is specific
    36   to the simplex algorithm and can be transient  e.g., scaling arrays.  Normally
     39  to the Simplex Algorithm and can be transient  e.g., scaling arrays.  Normally
    3740  a user will just be dealing with the ClpSimplex class and not with the ClpModel
    3841  class.
     
    4043  <para>
    4144  From the point of view of most Simplex users, the ClpModel and ClpSimplex
    42   classes are all you need to know about.  There are algorithm-specific classes
     45  classes are all one needs to know about.  There are algorithm-specific classes
    4346  which inherit from ClpSimplex (e.g., ClpSimplexDual and ClpSimplexPrimal), but
    44   they have no member data and very rarely need be visible to user.  Normally,
    45   after instantiating an object of type ClpSimplex, the user would type
    46   model.dual() to invoke dual algorithm.
    47   </para>
    48   </section>
    49   <section>
    50   <title>
    51   First example
    52   </title>
    53   <para>
    54   Okay, first sample.  It is short enough to present in full (and to not be too
    55   frightening!):
    56   </para>
     47  they have no member data and very rarely need be visible to user.  So, for
     48  example, after instantiating an object <userinput>model</userinput> of type ClpSimplex,
     49  the user would type <userinput>model.dual()</userinput> to invoke dual algorithm.
     50  </para>
     51  </section>
     52  <section>
     53  <title>
     54  First Example
     55  </title>
     56  <para>
     57  Below is our first CLP example code.  It is short enough to present in full.
     58  Most of the remaining examples in this Guide will take the form of small code
     59  fragments.
     60  </para>
     61  <example>
     62  <title>minimum.cpp</title>
    5763  <programlisting>
     64  <![CDATA[ 
    5865// Copyright (C) 2002, International Business Machines
    5966// Corporation and others.  All Rights Reserved.
    6067
    61 #include &quot;ClpSimplex.hpp&quot;
     68#include "ClpSimplex.hpp"
    6269int main (int argc, const char *argv[])
    6370{
    6471  ClpSimplex  model;
    6572  int status;
    66   if (argc&lt;2)
    67     status=model.readMps(&quot;../../Mps/Sample/p0033.mps&quot;);
     73  if (argc<2)
     74    status=model.readMps("../../Mps/Sample/p0033.mps");
    6875  else
    6976    status=model.readMps(argv[1]);
     
    7279  }
    7380  return 0;
    74 }   
     81}
     82  ]]>   
    7583  </programlisting>
    76   <para>
    77   This sample program creates a default ClpSimplex model, reads an mps file,
    78   and if there are no errors, solves it using the primal algorithm.  Simple, but
    79   not terribly useful: there is no way to see the result of the solve.  There are
    80   two main results -- a status saying what happened, and then arrays filled with
    81   the solution values.
    82   </para>
    83   </section>
    84   <section>
    85   <title>
    86   Getting at the solution
     84  </example>
     85  <para>
     86  This sample program creates a default <classname>ClpSimplex</classname> model,
     87  reads an mps file, and if there are no errors, solves it using the primal
     88  algorithm.  Simple, but not terribly useful: there is no way to see the results
     89  of the solve.  There are two main kinds of results -- a status saying what
     90  happened to the model, and arrays filled with the solution values.
     91  </para>
     92  </section>
     93  <section>
     94  <title>
     95  Getting at the Solution
    8796  </title>
    8897  <para>
    8998  It is often the case with CLP that there is more than one way to do something.
    9099  This is a consequence of CLP's mixed heritage as a child of OSL and a cousin of
    91   OSI.  Finding the status exemplifies this situation.
     100  OSI.  Finding the status of a model exemplifies this situation.
    92101  </para>
    93102  <para>
    94103  The OSI way to check for optimality is to call model.isProvenOptimal().  Also
    95   available are isProvenPrimalInfeasible(), isProvenDualInfeasible(),
    96   isPrimalObjectiveLimitReached(), isDualObjectiveLimitReached(),
    97   isIterationLimitReached() or the feared isAbandoned().  Should one prefer the
    98   OSL way of doing things, model.status() returns as it would in OSL-land, so 0
    99   means optimal, 1 means  primal infeasible etc.
    100   </para>
    101   <para>
    102   Similarly, to pick up the solution values, we can inhabit the virtuous Osi-land or the
    103   not-quite-so-virtuous Clp-land.  By this it is meant that there are const and
    104   non-const forms of arrays.  It is easier to deal with the non-const versions,
    105   so most of the later elaborate algorithms use them.
    106   </para>
     104  available are <function>isProvenPrimalInfeasible()</function>,
     105  <function>isProvenDualInfeasible()</function>,
     106  <function>isPrimalObjectiveLimitReached()</function>,
     107  <function>isDualObjectiveLimitReached()</function>,
     108  <function>isIterationLimitReached()</function> or the feared
     109  <function>isAbandoned()</function>.  Should one prefer the OSL way of doing
     110  things, model.status() returns as it would in OSL-land, so 0 means optimal,
     111  1 means  primal infeasible etc.
     112  </para>
     113  <para>
     114  Similarly, to pick up the solution values, we can inhabit the virtuous OSI-land
     115  or the not-quite-so-virtuous CLP-land.  By this it is meant that there are
     116  const and non-const forms of arrays.  It is easier to deal with the non-const
     117  versions, so most of the later elaborate algorithms use them.
     118  </para>
     119
     120  <table frame="none">
     121  <title>
     122  Methods for getting solution information
     123  </title>
     124  <tgroup cols="3">
     125  <thead>
     126    <row>
     127      <entry>
     128      Purpose
     129      </entry>
     130      <entry>
     131      OSI-style (virtuous)
     132      </entry>
     133      <entry>
     134      CLP style (less virtuous)
     135      </entry>
     136    </row>
     137  </thead>
     138  <tbody>
     139    <row>
     140      <entry align="left" valign="top">
     141      Primal column solution
     142      </entry>
     143      <entry align="left" valign="top">
     144      <function>const double * getColSolution()</function>
     145      </entry>
     146      <entry align="left" valign="top">
     147      <function>double * primalColumnSolution()</function>
     148      </entry>
     149    </row>
     150    <row>
     151      <entry align="left" valign="top">
     152      Dual row solution
     153      </entry>
     154      <entry align="left" valign="top">
     155      <function>const double * getRowPrice()</function>
     156      </entry>
     157      <entry align="left" valign="top">
     158      <function>double * dualColumnSolution()</function>
     159      </entry>
     160    </row>
     161    <row>
     162      <entry align="left" valign="top">
     163      Primal row solution
     164      </entry>
     165      <entry align="left" valign="top">
     166      <function>const double * getRowActivity()</function>
     167      </entry>
     168      <entry align="left" valign="top">
     169      <function>double * primalRowSolution()</function>
     170      </entry>
     171    </row>
     172    <row>
     173      <entry align="left" valign="top">
     174      Dual row solution
     175      </entry>
     176      <entry align="left" valign="top">
     177      <function>const double * getReducedCost()</function>
     178      </entry>
     179      <entry align="left" valign="top">
     180      <function>double * dualColumnSolution()</function>
     181      </entry>
     182    </row>
     183    <row>
     184      <entry align="left" valign="top">
     185      Number of rows in model
     186      </entry>
     187      <entry align="left" valign="top">
     188      <function>int getNumRows()</function>
     189      </entry>
     190      <entry align="left" valign="top">
     191      <function>int numberRows()</function>
     192      </entry>
     193    </row>
     194    <row>
     195      <entry align="left" valign="top">
     196      Number of columns in model
     197      </entry>
     198      <entry align="left" valign="top">
     199      <function>int getNumCols()</function>
     200      </entry>
     201      <entry align="left" valign="top">
     202      <function>int numberColumns()</function>
     203      </entry>
     204    </row>
     205  </tbody>
     206  </tgroup>
     207  </table>
     208
     209  <para>
     210  The reader  may have noted a preference for &quot;number&quot; over
     211  &quot;num&quot; and &quot;column&quot; over &quot;col&quot;.  This may be a
     212  reaction to when one of the authors was young and 5 or 6 letters was the
     213  maximum in FORTRAN for any name or to early days with Osl when seven characters
     214  were allowed but the first three had to be &quot;EKK&quot;! 
     215  </para>
     216  <para>
     217  Using the above-listed functions, our initial example might be continued as follows:
     218  </para>
     219  <example>
     220  <title>
     221  Possible extension of minimum.cpp
     222  </title>
     223  <programlisting>
     224  <![CDATA[ 
     225  int numberRows = model.numberRows();
     226  double * rowPrimal = model.primalRowSolution();
     227  double * rowDual = model.dualRowSolution();
     228
     229  int iRow;
     230
     231  for (iRow=0;iRow<numberRows;iRow++)   
     232    printf("Row %d, primal %g, dual %g\n",iRow,
     233        rowPrimal[iRow],rowDual[iRow]);
     234       
     235  int numberColumns = model.numberColumns();
     236  double * columnPrimal = model.primalColumnSolution();
     237  double * columnDual = model.dualColumnSolution();
     238
     239  int iColumn;
     240
     241  for (iColumn=0;iColumn<numberColumns;iColumn++)       
     242    printf("Column %d, primal %g, dual %g\n",iColumn,
     243        columnPrimal[iColumn],columnDual[iColumn]);
     244  ]]>
     245  </programlisting>
     246  </example>
     247  <para>
     248  This code sample would pretty-print information about the model's primal and
     249  dual solutions.  How to additionally print row and column names is
     250  illustrated in the <filename>defaults.cpp</filename> file in the
     251  &quot;Samples&quot; directory (the &quot;Samples&quot; are properly addressed
     252  in <xref linkend="moreexamples" />).  This sample is also useful as it
     253  explicitly performs default actions (e.g. it sets the primal feasiblility
     254  tolerance value to the default value).
     255  </para>
     256  <para>
     257  The remainder of this chapter will show some more of the basic tasks a user
     258  might want to perform.  Apart from presolve we will only be looking at actions
     259  which can be performed when including the single header file
     260  <filename>COIN/Clp/include/ClpSimplex.hpp</filename>.
     261  </para>
     262  </section>
     263  <section>
     264  <title>
     265  Building and Modifying a Model
     266  </title>
     267  <para>
     268  Rather than reading a model from an MPS file we can load a model from arrays
     269  in memory.  There are various <function>loadProblem</function> methods which
     270  are similar to those in OSI.  It is easy to add more such methods to CLP if the need arises.
     271  </para>
     272  <para>We can copy in integer information by
     273  <function>copyInIntegerInformation(const&nbsp;char&nbsp;*&nbsp;array)</function> where array
     274  is 0 or 1 to say integer and we can drop existing information by
     275  <function>deleteIntegerInformation()</function>.  There are various ways of
     276  changing the size of a model.  The simplest is
     277  <function>resize(newNumberRows,newNumberColumns)</function> - this will either
     278  truncate model or add default rows or columns - a default row has lower bound
     279  of -infinity and upper bound of +infinity, while a default column has zero cost,
     280  zero lower bound and an upper bound of +infinity.
     281  </para>
     282  <para>
     283  Normally we would use <function>deleteRows</function>,
     284  <function>addRows</function>, <function>deleteColumns</function> and
     285  <function>addColumns</function>, where the add ones will also add in the
     286  elements.  A potentially very useful way of modifying a model is strictly a
     287  constructor.  Given a large model and a list of rows and a list of columns it
     288  constructs the model as a subset of the large model.  It is possible to change
     289  the order of the columns/rows and to duplicate columns/rows.  So a list of
     290  columns 4,4,1,0 will create a new model where the first two columns are copies
     291  of column 4 in original model and the next two are the first two of original
     292  model in reverse order.  This can be useful to form a model with piecewise
     293  linear costs by duplicating columns and then modifying bounds and costs.
     294  </para>
     295  </section>
     296  <section>
     297  <title>Tolerances</title>
     298  <para>
     299  There are set and get methods for tolerances, for example,
     300  <function>double&nbsp;primalTolerance()</function> and
     301  <function>setPrimalTolerance(double)</function>.  An individual variable is
     302  deemed primal feasible if it is less than the tolerance referred to by these
     303  methods below its lower bound and less than it above its upper bound.
     304  Similarly for dual tolerances, a variable is deemed to be dual feasible if its
     305  reduced cost is greater than minus the tolerance or its distance to the upper
     306  bound is less than primal tolerance and the reduced cost is less than plus the
     307  tolerance or the distance to lower bound is less than primal tolerance.  This
     308  is just complementarity conditions adadpted for tolerances and simple lower and
     309  upper bounds.(Note that the above was stated as for minimization - signs are
     310  reversed for maximization.)
     311  </para>
     312  </section>
     313  <section>
     314  <title>Some Useful Sets and Gets</title>
     315  <table frame="none">
     316  <title>Some Useful Sets and Gets</title>
     317    <tgroup cols="2">
     318    <thead>
     319    <row>
     320    <entry>
     321    Method(s)
     322    </entry>
     323    <entry>
     324    Description
     325    </entry>
     326    </row>
     327    </thead>
     328    <tbody>
     329    <row>
     330      <entry align="left" valign="top">
     331      <function>setMaximumIterations(int value)</function><sbr/>
     332      <function>setMaximumSeconds(double value)</function>
     333      </entry>
     334      <entry align="left" valign="top">
     335      These methods tell CLP to stop after a given number of iterations or
     336      seconds.
     337      </entry>
     338    </row>
     339    <row>
     340      <entry align="left" valign="top">
     341      <function>double&nbsp;objectiveValue()</function>
     342      </entry>
     343      <entry align="left" valign="top">
     344      This method returns the objective value.
     345      </entry>
     346    </row>
     347    <row>
     348      <entry align="left" valign="top">
     349      <function>const&nbsp;double&nbsp;*&nbsp;getObjCoefficients()</function><sbr/>
     350      <function>double&nbsp;*&nbsp;objective()</function>
     351      </entry>
     352      <entry align="left" valign="top">
     353      These methods return the objective coefficients.
     354      </entry>
     355    </row>
     356    <row>
     357      <entry align="left" valign="top">
     358      <function>const&nbsp;double&nbsp;*&nbsp;getRowLower()</function><sbr/>
     359      <function>double&nbsp;*&nbsp;rowLower()</function><sbr/>
     360      <function>const&nbsp;double&nbsp;*&nbsp;getRowUpper()</function><sbr/>
     361      <function>double&nbsp;*&nbsp;rowUpper()</function><sbr/>
     362      <function>const&nbsp;double&nbsp;*&nbsp;getColLower()</function><sbr/>
     363      <function>double&nbsp;*&nbsp;columnLower()</function><sbr/>
     364      <function>const&nbsp;double&nbsp;*&nbsp;getColUpper()</function><sbr/>
     365      <function>double&nbsp;*&nbsp;columnUpper()</function>
     366      </entry>
     367      <entry align="left" valign="top">
     368      These methods give lower and upper bounds on row and column activities.
     369      </entry>
     370    </row>
     371    <row>
     372      <entry align="left" valign="top">
     373      <function>infeasibilityRay()</function><sbr/>
     374      <function>unboundedRay()</function>
     375      </entry>
     376      <entry align="left" valign="top">
     377      If the problem was primal or dual infeasible, these methods will give a
     378      pointer to a ray proving infeasibility.
     379      </entry>
     380    </row>
     381    <row>
     382      <entry align="left" valign="top">
     383      <function>matrix()</function>
     384      </entry>
     385      <entry align="left" valign="top">
     386      There are more options as the user has great flexibility in how the problem
     387      matrix is stored, but the default is as a
     388      <classname>CoinPackedMatrix</classname> and so we have that this method
     389      returns a pointer to a <classname>CoinPackedMatrix</classname> which can
     390      be further manipulated.
     391      </entry>
     392    </row>
     393    <row>
     394      <entry align="left" valign="top">
     395      <function>getNumElements()</function>
     396      </entry>
     397      <entry align="left" valign="top">
     398      Returns the number of elements in the problem matrix.
     399      </entry>
     400    </row>
     401    <row>
     402      <entry align="left" valign="top">
     403      <function>setOptimizationDirection(int&nbsp;direction)</function><sbr/>
     404      <function>optimizationDirection()</function>
     405      </entry>
     406      <entry align="left" valign="top">
     407      These methods set and get the objective sense.  The parameter
     408      <parameter>direction</parameter> should be +1 to minimize, -1 to maximize,
     409      and 0 to ignore.
     410      </entry>
     411    </row>
     412    </tbody>
     413  </tgroup>
     414  </table>
     415  </section>
     416  <section>
     417  <title>
     418  Simplex-specific Methods
     419  </title>
     420  <para>
     421  Some of the most commonly-used methods when working with Simplex are listed in
     422  the table below.
     423  </para>
     424  <table frame="none">
     425  <title>Common Simplex-specific methods</title>
     426    <tgroup cols="2">
     427    <thead>
     428    <row>
     429    <entry>
     430    Method(s)
     431    </entry>
     432    <entry>
     433    Description
     434    </entry>
     435    </row>
     436    </thead>
     437    <tbody>
     438    <row>
     439      <entry align="left" valign="top">
     440      <function>primal(int&nbsp;mode=0)</function>
     441      </entry>
     442      <entry align="left" valign="top">
     443      This applies the primal algorithm. If <parameter>mode</parameter> is
     444      set to the default of 0, then the method uses the status variables to
     445      determine basis and solution. If <parameter>mode</parameter> is 1 then
     446      the method does a values pass so variables not in basis are given their
     447      current values and one pass of variables is done to clean up the basis
     448      with an equal or better objective value.
     449      </entry>
     450    </row>
     451    <row>
     452      <entry align="left" valign="top">
     453      <function>dual(int&nbsp;mode=0)</function>
     454      </entry>
     455      <entry align="left" valign="top">
     456      This applies the dual algorithm. if <parameter>mode</parameter> is set
     457      to the default of 0, then the method uses the status variables to
     458      determine basis and solution.  If <parameter>mode</parameter> is 1 then
     459      the method uses input duals and does a values pass so one pass of basic
     460      variables is done to clean up the duals with an equal or better objective
     461      value.
     462      </entry>
     463    </row>
     464    <row>
     465      <entry align="left" valign="top">
     466      <function>scaling(int&nbsp;mode=1)</function>
     467      </entry>
     468      <entry align="left" valign="top">
     469      This method toggles scaling on (<parameter>mode</parameter> set to 1)
     470      and off (<parameter>mode</parameter> set to 0).
     471      </entry>
     472    </row>
     473    <row>
     474      <entry align="left" valign="top">
     475      <function>int&nbsp;crash(double&nbsp;gap,int&nbsp;mode)</function>
     476      </entry>
     477      <entry align="left" valign="top">
     478      This method attemps to improve on an all slack basis and remains a work
     479      in progress.  For dual this will move variables to the dual feasible bound
     480      if the gap between bounds is less than <parameter>gap</parameter>.  Setting
     481      <parameter>mode</parameter> to 0 guesses which algorithm is better, while
     482      a value of 1 or 2 will result in more work being done.  The return code is
     483      0 if the basis was not slacks in first case, it is negative if dual is
     484      preferred or positive if primal.  &plusmn;1 means an all slack basis seemed
     485      best, while &plusmn;2 means some work was done.
     486      </entry>
     487    </row>
     488    <row>
     489      <entry align="left" valign="top">
     490      <function>perturb(int&nbsp;mode)</function>
     491      </entry>
     492      <entry align="left" valign="top">
     493      This method toggles perturbation on (<parameter>mode</parameter> set to 1)
     494      and off (<parameter>mode</parameter> set to 0).  It should be considered
     495      a work in progress, although on some problems it gives very good results.
     496      </entry>
     497    </row>
     498    <row>
     499      <entry align="left" valign="top">
     500      <function>factorizationFrequency()</function><sbr/>
     501      <function>setFactorizationFrequency(int&nbsp;value)</function>
     502      </entry>
     503      <entry align="left" valign="top">
     504      These are &quot;get&quot; and &quot;set&quot; methods for the basis matrix
     505      factorization frequency.  The default is to refactor every 200 iterations,
     506      but it may make more sense to use something such as 100 + the number of
     507      rows divided by 50.
     508      </entry>
     509    </row>
     510    <row>
     511      <entry align="left" valign="top">
     512      <function>dualBound()</function><sbr/>
     513      <function>setDualBound(double&nbsp;value)</function>
     514      </entry>
     515      <entry align="left" valign="top">
     516      These are &quot;get&quot; and &quot;set&quot; methods for the
     517      &quot;dual&nbsp;bound&quot;.  The CLP dual algorithm declares all problems
     518      to be dual feasible by putting non-basic variables to correct bounds for
     519      the reduced cost.  If the gap between the bounds is too big then it
     520      pretends the gap is only the value specified by this set method.
     521      In essence, this gives a composite dual rather than a pure
     522      Phase&nbsp;I- Phase&nbsp;II method.
     523      </entry>
     524    </row>
     525    <row>
     526      <entry align="left" valign="top">
     527      <function>infeasibilityCost()</function><sbr/>
     528      <function>setInfeasibilityCost(double&nbsp;value)</function>
     529      </entry>
     530      <entry align="left" valign="top">
     531      These are the primal analogs to the &quot;dual&nbsp;bound&quot; methods.
     532      </entry>
     533    </row>
     534    <row>
     535      <entry align="left" valign="top">
     536      <function>numberPrimalInfeasibilities()</function><sbr/>
     537      <function>sumPrimalInfeasibilities()</function>
     538      </entry>
     539      <entry align="left" valign="top">
     540      After a solve, there may be infeasibilities.  These methods serve to
     541      check for said infeasibilities.  One could check the solution explicitly
     542      as well.  For a code fragement illustrating this, see
     543      <xref linkend="presolveexample"/>.
     544      </entry>
     545    </row>
     546    </tbody>
     547  </tgroup>
     548  </table>
     549  </section>
     550  <section>
     551  <title>
     552  Presolve
     553  </title>
     554  <para>
     555  The header file for the use of CLP's presolve functionality is
     556  <filename>COIN/Clp/include/Presolve.hpp</filename>.  The code fragment below
     557  illustrates some of the possibilities offered by CLP's presolve:
     558  </para>
     559  <example id="presolveexample">
     560  <title>Presolve code fragment</title>
     561  <programlisting>
     562    #include "Presolve.hpp"
     563   
     564    ...
     565
     566    ClpSimplex model; // initialized by readMps or some other method
     567   
     568    ...
     569
     570    Presolve presolveInfo;
     571    ClpSimplex * presolvedModel = presolveInfo(model);
     572    // at this point we have original model and a new model.  The information
     573    // on the operations done is in presolveInfo
     574    if (presolvedModel) {
     575      // was not found to be infeasible - so lets solve
     576      // if presolvedModel was NULL then it was primal infeasible and ...
     577      presolvedModel->dual(); // or whatever else we wish to do
     578      presolveInfo.postsolve(true);  // the true updates status arrays in original
     579      /* If the presolved model was optimal then so should the original be.
     580         We can use checkSolution and test feasibility */
     581    model.checkSolution();     
     582    if (model.numberDualInfeasibilities()||
     583      model.numberPrimalInfeasibilities()) {
     584      printf("%g dual %g(%d) Primal %g(%d)\n",
     585         model.objectiveValue(),
     586          model.sumDualInfeasibilities(),
     587          model.numberDualInfeasibilities(),
     588          model.sumPrimalInfeasibilities(),
     589          model.numberPrimalInfeasibilities());
     590      // Due to tolerances we can not guarantee that so you may wish to throw in
     591      model.primal(1);
     592    }
     593  </programlisting>
     594  </example>
     595  <para>
     596  Presolve has a few more options which can be found in the header file, for
     597  example whether to treat as an integer problem or whether to keep row and
     598  column names.
     599  </para>
     600  </section>
     601  <section>
     602  <title>Status Array</title>
     603  <para>
     604  The astute reader may have noticed that the status array has been mentioned
     605  once or twice.  The beginning user will not need to look at it   Nevertheless,
     606  for completeness the status of a variable can be found and set as shown below.
     607  The possible state of a variable are listed in the following table (each may
     608  have to be preceded by ClpSimplex::):
     609  </para>
     610  <table frame="none">
     611  <title>Possible states of a variable</title>
     612    <tgroup cols="2">
     613      <thead>
     614        <row>
     615          <entry>
     616          State
     617          </entry>
     618          <entry>
     619          Description
     620          </entry>
     621        </row>
     622      </thead>
     623      <tbody>
     624        <row>
     625          <entry align="left" valign="top">
     626          <constant>isFree</constant>
     627          </entry>
     628          <entry align="left" valign="top">
     629          Not in basis, has infinite bounds
     630          </entry>
     631        </row>
     632        <row>
     633          <entry align="left" valign="top">
     634          <constant>basic</constant>
     635          </entry>
     636          <entry align="left" valign="top">
     637          In basis
     638          </entry>
     639        </row>
     640        <row>
     641          <entry align="left" valign="top">
     642          <constant>atUpperBound</constant>
     643          </entry>
     644          <entry align="left" valign="top">
     645          At upper bound
     646          </entry>
     647        </row>
     648        <row>
     649          <entry align="left" valign="top">
     650          <constant>atLowerBound</constant>
     651          </entry>
     652          <entry align="left" valign="top">
     653          At lower bound
     654          </entry>
     655        </row>
     656        <row>
     657          <entry align="left" valign="top">
     658          <constant>superBasic</constant>
     659          </entry>
     660          <entry align="left" valign="top">
     661          Between bounds, but not basic or free
     662          </entry>
     663        </row>
     664        <row>
     665          <entry align="left" valign="top">
     666          <constant>isFixed</constant>
     667          </entry>
     668          <entry align="left" valign="top">
     669          Not in basis, bounds are equal
     670          </entry>
     671        </row>
     672      </tbody>
     673    </tgroup>
     674  </table>
     675  <para>
     676  To get or set the status of a variable is a simple task:
     677  </para>
     678  <programlisting>
     679  // Get row status...
     680  Status status=model.getRowStatus(sequenceNumber)
     681  // ... or get column status.
     682  Status status=model.getColumnStatus(sequenceNumber)
     683  // Set row status to basic (for example)...
     684  model.setRowStatus(sequenceNumber,ClpSimplex::basic)
     685  // ... or column status to basic.
     686  model.setColumnStatus(sequenceNumber,ClpSimplex::basic)
     687  </programlisting>
    107688  </section>
    108689  </chapter>
  • trunk/Docs/clpexe.xml

    r405 r408  
    11<?xml version="1.0" encoding="ISO-8859-1"?>
    2 <chapter>
     2<chapter id="clpexe">
    33  <title>
    44  The CLP Executable
    55  </title>
    66  <para>
    7   Coming Soon
     7  The result of <userinput>make unitTest</userinput> is an executable
     8  <filename>clp</filename> as well as the CLP and COIN libraries.
     9  This can be used to do various unit tests, but can also be used as a standalone
     10  solver.  As it only has a very simple solution file format you may wish to
     11  modify that part of <filename>Test/ClpMain.cpp</filename> and even offer it to
     12  Clp.
     13  </para>
     14  <para>
     15  The <filename>clp</filename> executable operates in command line mode or
     16  prompted mode.  Entering <userinput>clp</userinput> will bring you to prompt
     17  mode,while <userinput>clp &lt;filename&gt;</userinput> will import an MPS file
     18  from filename and solve it using the dual simplex method and exit.  Again
     19  <userinput>clp &lt;filename&gt; -primalsimplex</userinput> will import a file
     20  and solve using the primal simplex method.  A dash
     21  (&quot;<userinput>-</userinput>&quot;) by itself changes to prompt mode.  In
     22  command line mode &quot;<userinput>-</userinput>&quot; is needed (apart from
     23  first parameter which is taken as file name).  So the following are equivalent
     24  and maximize a problem using dual and write a solution to file
     25  <filename>solfile</filename>:
     26  <blockquote>
     27    <literallayout>
     28    <prompt>$</prompt> <userinput>clp <replaceable>filename</replaceable> -maximize -dualsimplex -solution solfile</userinput>
     29    </literallayout>
     30  </blockquote>
     31  <blockquote>
     32    <literallayout>
     33    <prompt>$</prompt> <userinput>clp <replaceable>filename</replaceable> -maximize -</userinput>
     34    <prompt>Clp:</prompt><userinput>duals</userinput>
     35    <prompt>Clp:</prompt><userinput>solution solfile</userinput>
     36    <prompt>Clp:</prompt><userinput>quit</userinput>
     37    </literallayout>
     38  </blockquote>
     39  </para>
     40  <para>
     41  The executable has some command-completion functionality as well as some inline
     42  help.  Below is a table with some examples which summarize these capabilities.
     43  </para>
     44  <table frame="none">
     45  <title>Command examples for the clp executable</title>
     46  <tgroup cols="2">
     47    <thead>
     48      <row>
     49        <entry align="left">
     50        Command&nbsp;&nbsp;&nbsp;&nbsp;
     51        </entry>
     52        <entry align="left">
     53        Result
     54        </entry>
     55      </row>
     56    </thead>
     57    <tbody>
     58      <row>
     59        <entry>
     60        <command>?</command>
     61        </entry>
     62        <entry>
     63        Gives a list of all  commands
     64        </entry>
     65      </row>
     66      <row>
     67        <entry>
     68        <command>p?</command>
     69        </entry>
     70        <entry>
     71        Gives a list of all commands which begin with &lt;p&gt;.
     72        </entry>
     73      </row>
     74      <row>
     75        <entry>
     76        <command>p??</command>
     77        </entry>
     78        <entry>
     79        Gives a list of all commands which begin with &lt;p&gt;., with a short
     80        explanation for each.
     81        </entry>
     82      </row>
     83      <row>
     84        <entry>
     85        <command>primals??</command>
     86        </entry>
     87        <entry>
     88        If is this is enough to uniquely determine a command (in this example,
     89        <command>primalS</command>, for primal simplex), a long explanation
     90        is given.
     91        </entry>
     92      </row>
     93    </tbody>
     94  </tgroup>
     95  </table>
     96  <para>
     97  In addition, matching a name without a ? will either execute the command or give
     98  the value of the corresponding parameter.  So,
     99  <command>primalweight</command> will give the current value of  the
     100  primalWeight parameter while <command>primalw 1.0e7</command> will change
     101  it to 1.0e7.
     102  </para>
     103  <para>
     104  The executable is at a very early stage and comments will graciously
     105  welcomed.
    8106  </para>
    9107</chapter>
  • trunk/Docs/clpuserguide.xml

    r405 r408  
    22<!DOCTYPE book SYSTEM "/home/delanuez/docbook/dtd/docbookx.dtd" [
    33  <!ENTITY authors SYSTEM "authors.xml">
     4  <!ENTITY legal SYSTEM "legal.xml">
    45  <!ENTITY intro SYSTEM "intro.xml">
    56  <!ENTITY basicmodelclasses SYSTEM "basicmodelclasses.xml">
     
    89  <!ENTITY clpexe SYSTEM "clpexe.xml">
    910  <!ENTITY messages SYSTEM "messages.xml">
     11  <!ENTITY revhist SYSTEM "revhist.xml">
     12  <!ENTITY doxygen SYSTEM "doxygen.xml">
    1013]>
    1114<book id="clpuserguide" lang="en">
     
    1316<title>CLP User Manual</title>
    1417  &authors;
     18  &legal;
    1519</bookinfo>
    1620  &intro;
     
    2024  &clpexe;
    2125  &messages;
     26  &doxygen;
     27  &revhist;
    2228</book>
    2329
  • trunk/Docs/intro.xml

    r405 r408  
    11<?xml version="1.0" encoding="ISO-8859-1"?>
    2   <chapter>
     2  <chapter id="intro">
    33  <title>
    44    Introduction
     
    66  <para>
    77  The COIN  Linear Program code or CLP is an open-source simplex solver.  This
    8   is a not-so-pathetic attempt to create a User Guide.
     8  is the first edition of the User Guide, and is to be considered a work in
     9  progress.
    910  </para>
    1011  <para>
    1112  This document is designed to be used in conjunction with the Samples
    12   subdirectory of the Clp directory.  In the rare event that this document
    13   conflicts with the observed behavior of the source code, the comments in the
    14   header files are the ultimate reference.
     13  subdirectory of the Clp directory (i.e. <filename>COIN/Clp/Samples</filename>).
     14  In the rare event that this document conflicts with the observed behavior of
     15  the source code, the comments in the header files (found in
     16  <filename>COIN/Clp/include</filename>) are the ultimate reference.
    1517  </para>
    1618  </chapter>
  • trunk/Docs/messages.xml

    r405 r408  
    11<?xml version="1.0" encoding="ISO-8859-1"?>
    2 <chapter>
     2<chapter id="messages">
    33  <title>
    44  Messages
    55  </title>
    66  <para>
    7   Coming Soon
     7  The messages and codes passed by CLP are listed in the tables below.  The
     8  notation is as for printf from &quot;C&quot;:
     9  </para>
     10  <itemizedlist>
     11    <listitem>
     12    <simpara>
     13    <computeroutput>%s</computeroutput> is a string
     14    </simpara>
     15    </listitem>
     16    <listitem>
     17    <simpara>
     18    <computeroutput>%d</computeroutput> is an integer
     19    </simpara>
     20    </listitem>
     21    <listitem>
     22    <simpara>
     23    <computeroutput>%g</computeroutput> or <computeroutput>%f</computeroutput>
     24    is a floating point value
     25    </simpara>
     26    </listitem>
     27  </itemizedlist>
     28
     29  <table frame="none" align="left">
     30  <title>
     31  COIN Messages passed at or above logging level 1
     32  </title>
     33  <tgroup cols="4" colsep="1" rowsep="1">
     34  <colspec colname="c1"/>
     35  <colspec colname="c2"/>
     36  <colspec colname="c3"/>
     37  <colspec colname="c4"/>
     38  <thead>
     39    <row>
     40      <entry align="center">
     41      Code
     42      </entry>
     43      <entry align="center">
     44      Area
     45      </entry>
     46      <entry>
     47      </entry>
     48      <entry align="left">
     49      Text and notes
     50      </entry>
     51    </row>
     52  </thead>
     53  <tbody>
     54    <row>
     55      <entry align="left">
     56      1
     57      </entry>
     58      <entry align="center">
     59      MPSREAD
     60      </entry>
     61      <entry>
     62      </entry>
     63      <entry align="left">
     64      <computeroutput>At line %d %s</computeroutput>
     65      </entry>
     66    </row>
     67    <row>
     68      <entry namest="c1" nameend="c3">
     69      </entry>
     70      <entry align="left">
     71      <simpara>
     72      This just prints out NAME line, ROW line, etc
     73      </simpara>
     74      </entry>
     75    </row>
     76    <row>
     77      <entry align="left">
     78      2
     79      </entry>
     80      <entry align="center">
     81      MPSREAD
     82      </entry>
     83      <entry>
     84      </entry>
     85      <entry align="left">
     86      <computeroutput>Problem %s has %d rows, %d columns and %d elements
     87      </computeroutput>
     88      </entry>
     89    </row>
     90    <row>
     91      <entry namest="c1" nameend="c3">
     92      </entry>
     93      <entry align="left">
     94      <simpara>
     95      This gives statistics after reading an MPS file
     96      </simpara>
     97      </entry>
     98    </row>
     99    <row>
     100      <entry align="left">
     101      8
     102      </entry>
     103      <entry align="center">
     104      MPSREAD
     105      </entry>
     106      <entry>
     107      </entry>
     108      <entry align="left">
     109      <computeroutput>%s read with %d errors
     110      </computeroutput>
     111      </entry>
     112    </row>
     113    <row>
     114      <entry namest="c1" nameend="c3">
     115      </entry>
     116      <entry align="left">
     117      <simpara>
     118      This gives error statistics for file
     119      </simpara>
     120      </entry>
     121    </row>
     122    <row>
     123      <entry align="left">
     124      505
     125      </entry>
     126      <entry align="center">
     127      PRESOLVE
     128      </entry>
     129      <entry>
     130      </entry>
     131      <entry align="left">
     132      <computeroutput>
     133      Presolved poblem not optimal, resolve after postsolve
     134      </computeroutput>
     135      </entry>
     136    </row>
     137    <row>
     138      <entry namest="c1" nameend="c3">
     139      </entry>
     140      <entry align="left">
     141      <simpara>
     142      This could be because it was not feasible or because of maximum
     143      iterations.  If this message occurs then consider using primal clean up
     144      </simpara>
     145      </entry>
     146    </row>
     147    <row>
     148      <entry align="left">
     149      506
     150      </entry>
     151      <entry align="center">
     152      PRESOLVE
     153      </entry>
     154      <entry>
     155      </entry>
     156      <entry align="left">
     157      <computeroutput>
     158      Presolve %d (%d) rows, %d (%d) columns and %d (%d) elements
     159      </computeroutput>
     160      </entry>
     161    </row>
     162    <row>
     163      <entry namest="c1" nameend="c3">
     164      </entry>
     165      <entry align="left">
     166      <simpara>
     167      The first number is the number after presolve and the number
     168      in parentheses is amount of reduction
     169      </simpara>
     170      </entry>
     171    </row>
     172    <row>
     173      <entry align="left">
     174      510
     175      </entry>
     176      <entry align="center">
     177      PRESOLVE
     178      </entry>
     179      <entry>
     180      </entry>
     181      <entry align="left">
     182      <computeroutput>
     183      Presolve is modifying %d integer bounds and re-presolving
     184      </computeroutput>
     185      </entry>
     186    </row>
     187    <row>
     188      <entry namest="c1" nameend="c3">
     189      </entry>
     190      <entry align="left">
     191      <simpara>
     192      If presolve determines at the end that an integer variable have its bounds
     193      changed then it will repeat the entrire presolve
     194      </simpara>
     195      </entry>
     196    </row>
     197    <row>
     198      <entry align="left">
     199      511
     200      </entry>
     201      <entry align="center">
     202      PRESOLVE
     203      </entry>
     204      <entry>
     205      </entry>
     206      <entry align="left">
     207      <computeroutput>
     208      After Postsolve, objective %g, infeasibilities - dual %g (%d),
     209      primal %g (%d)
     210      </computeroutput>
     211      </entry>
     212    </row>
     213    <row>
     214      <entry namest="c1" nameend="c3">
     215      </entry>
     216      <entry align="left">
     217      <simpara>
     218      This gives the state after postsolve - this gives the objective value
     219      and the sum of dual and primal infeasibilities with the number of
     220      infeasibilities in parentheses.  Hopefully these should be zero
     221      </simpara>
     222      </entry>
     223    </row>
     224    <row>
     225      <entry align="left">
     226      512
     227      </entry>
     228      <entry align="center">
     229      PRESOLVE
     230      </entry>
     231      <entry>
     232      </entry>
     233      <entry align="left">
     234      <computeroutput>
     235      Presolved model was optimal, full model needs cleaning up
     236      </computeroutput>
     237      </entry>
     238    </row>
     239    <row>
     240      <entry namest="c1" nameend="c3">
     241      </entry>
     242      <entry align="left">
     243      <simpara>
     244      If the numbers in previous message (511) were large then maybe we need to
     245      know, if small then that's life
     246      </simpara>
     247      </entry>
     248    </row>
     249  </tbody>
     250  </tgroup>
     251  </table>
     252
     253  <table frame="none" align="left">
     254  <title>
     255  CLP Messages passed at or above logging level 1
     256  </title>
     257  <tgroup cols="4" colsep="1" rowsep="1">
     258  <colspec colname="c1"/>
     259  <colspec colname="c2"/>
     260  <colspec colname="c3"/>
     261  <colspec colname="c4"/>
     262  <thead>
     263    <row>
     264      <entry align="center">
     265      Code
     266      </entry>
     267      <entry align="center">
     268      Area
     269      </entry>
     270      <entry>
     271      </entry>
     272      <entry align="left">
     273      Text and notes
     274      </entry>
     275    </row>
     276  </thead>
     277  <tbody>
     278    <row>
     279    <row>
     280      <entry align="left">
     281      0
     282      </entry>
     283      <entry align="center">
     284      SIMPLEX
     285      </entry>
     286      <entry>
     287      </entry>
     288      <entry align="left">
     289      <computeroutput>
     290      Optimal - objective value %g
     291      </computeroutput>
     292      </entry>
     293    </row>
     294    <row>
     295      <entry namest="c1" nameend="c3">
     296      </entry>
     297      <entry align="left">
     298      <simpara>
     299      The only message you want to see
     300      </simpara>
     301      </entry>
     302    </row>
     303      <entry align="left">
     304      1
     305      </entry>
     306      <entry align="center">
     307      SIMPLEX
     308      </entry>
     309      <entry>
     310      </entry>
     311      <entry align="left">
     312      <computeroutput>
     313      Primal infeasible - objective value %g
     314      </computeroutput>
     315      </entry>
     316    </row>
     317    <row>
     318      <entry namest="c1" nameend="c3">
     319      </entry>
     320      <entry align="left">
     321      <simpara>
     322      You may need to look at previous messages or use methods.  Such as
     323      sumPrimalInfeasibilities() to find cause
     324      </simpara>
     325      </entry>
     326    </row>
     327    <row>
     328      <entry align="left">
     329      2
     330      </entry>
     331      <entry align="center">
     332      SIMPLEX
     333      </entry>
     334      <entry>
     335      </entry>
     336      <entry align="left">
     337      <computeroutput>
     338      Dual infeasible - objective value %g
     339      </computeroutput>
     340      </entry>
     341    </row>
     342    <row>
     343      <entry namest="c1" nameend="c3">
     344      </entry>
     345      <entry align="left">
     346      <simpara>
     347      You may need to look at previous messages or use methods.  Such as
     348      sumDualInfeasibilities() to find cause
     349      </simpara>
     350      </entry>
     351    </row>
     352    <row>
     353      <entry align="left">
     354      3
     355      </entry>
     356      <entry align="center">
     357      SIMPLEX
     358      </entry>
     359      <entry>
     360      </entry>
     361      <entry align="left">
     362      <computeroutput>
     363      Stopped - objective value %g
     364      </computeroutput>
     365      </entry>
     366    </row>
     367    <row>
     368      <entry namest="c1" nameend="c3">
     369      </entry>
     370      <entry align="left">
     371      <simpara>
     372      The algorithm stopped as requested by the user.
     373      </simpara>
     374      </entry>
     375    </row>
     376    <row>
     377      <entry align="left">
     378      4
     379      </entry>
     380      <entry align="center">
     381      SIMPLEX
     382      </entry>
     383      <entry>
     384      </entry>
     385      <entry align="left">
     386      <computeroutput>
     387      Stopped due to errors - objective value %g
     388      </computeroutput>
     389      </entry>
     390    </row>
     391    <row>
     392      <entry namest="c1" nameend="c3">
     393      </entry>
     394      <entry align="left">
     395      <simpara>
     396      Switch on log level 2 to see information on size of elements etc.  If they
     397      look reasonable then maybe we need to know.
     398      </simpara>
     399      </entry>
     400    </row>
     401    <row>
     402      <entry align="left">
     403      5
     404      </entry>
     405      <entry align="center">
     406      SIMPLEX
     407      </entry>
     408      <entry>
     409      </entry>
     410      <entry align="left">
     411      <computeroutput>
     412      %d Obj %g Primal inf %g (%d) Dual inf %g (%d)
     413      </computeroutput>
     414      </entry>
     415    </row>
     416    <row>
     417      <entry namest="c1" nameend="c3">
     418      </entry>
     419      <entry align="left">
     420      <simpara>
     421      At each re-factorization this gives the number of iterations and the value
     422      of the objective function.  If there are primal infeasibilities then the
     423      sum and number are given and similarly for dual infeasibilities.
     424      (This is a simplified form of message.)
     425      </simpara>
     426      </entry>
     427    </row>
     428    <row>
     429      <entry align="left">
     430      14
     431      </entry>
     432      <entry align="center">
     433      SIMPLEX
     434      </entry>
     435      <entry>
     436      </entry>
     437      <entry align="left">
     438      <computeroutput>
     439      Perturbing problem by %g % of %g
     440      </computeroutput>
     441      </entry>
     442    </row>
     443    <row>
     444      <entry namest="c1" nameend="c3">
     445      </entry>
     446      <entry align="left">
     447      <simpara>
     448      There is more to this message but if the user sees this then s/he has
     449      chosen to perturb the problem or the algorithm has decided to do so.
     450      If the numbers look too large the user may wish to think again.
     451      </simpara>
     452      </entry>
     453    </row>
     454    <row>
     455      <entry align="left">
     456      19
     457      </entry>
     458      <entry align="center">
     459      SIMPLEX
     460      </entry>
     461      <entry>
     462      </entry>
     463      <entry align="left">
     464      <computeroutput>
     465      %d variables/rows fixed as scaled bounds too close
     466      </computeroutput>
     467      </entry>
     468    </row>
     469    <row>
     470      <entry namest="c1" nameend="c3">
     471      </entry>
     472      <entry align="left">
     473      <simpara>
     474      If this occurs look carefully at your input data
     475      </simpara>
     476      </entry>
     477    </row>
     478    <row>
     479      <entry align="left">
     480      24
     481      </entry>
     482      <entry align="center">
     483      SIMPLEX
     484      </entry>
     485      <entry>
     486      </entry>
     487      <entry align="left">
     488      <computeroutput>
     489      Matrix will be packed to eliminate small elements
     490      </computeroutput>
     491      </entry>
     492    </row>
     493    <row>
     494      <entry namest="c1" nameend="c3">
     495      </entry>
     496      <entry align="left">
     497      <simpara>
     498      If this occurs the user should look carefully at data.
     499      </simpara>
     500      </entry>
     501    </row>
     502    <row>
     503      <entry align="left">
     504      26
     505      </entry>
     506      <entry align="center">
     507      SIMPLEX
     508      </entry>
     509      <entry>
     510      </entry>
     511      <entry align="left">
     512      <computeroutput>
     513      Matrix will be packed to eliminate %d duplicate elements
     514      </computeroutput>
     515      </entry>
     516    </row>
     517    <row>
     518      <entry namest="c1" nameend="c3">
     519      </entry>
     520      <entry align="left">
     521      <simpara>
     522      If this occurs the user should look carefully at data.
     523      </simpara>
     524      </entry>
     525    </row>
     526    <row>
     527      <entry align="left">
     528      28
     529      </entry>
     530      <entry align="center">
     531      SIMPLEX
     532      </entry>
     533      <entry>
     534      </entry>
     535      <entry align="left">
     536      <computeroutput>
     537      Crash put %d variables in basis, %d dual infeasibilities
     538      </computeroutput>
     539      </entry>
     540    </row>
     541    <row>
     542      <entry namest="c1" nameend="c3">
     543      </entry>
     544      <entry align="left">
     545      <simpara>
     546     
     547      </simpara>
     548      </entry>
     549    </row>
     550    <row>
     551      <entry align="left">
     552      29
     553      </entry>
     554      <entry align="center">
     555      SIMPLEX
     556      </entry>
     557      <entry>
     558      </entry>
     559      <entry align="left">
     560      <computeroutput>
     561      End of values pass after %d iterations
     562      </computeroutput>
     563      </entry>
     564    </row>
     565    <row>
     566      <entry namest="c1" nameend="c3">
     567      </entry>
     568      <entry align="left">
     569      <simpara>
     570      ??? If primal(1) or dual(1) the a sweep through model is made and this
     571      signals end of pass.
     572      </simpara>
     573      </entry>
     574    </row>
     575
     576  </tbody>
     577  </tgroup>
     578  </table>
     579
     580  <table frame="none" align="left">
     581  <title>
     582  COIN Messages passed at or above logging level 0
     583  </title>
     584  <tgroup cols="4" colsep="1" rowsep="1">
     585  <colspec colname="c1"/>
     586  <colspec colname="c2"/>
     587  <colspec colname="c3"/>
     588  <colspec colname="c4"/>
     589  <thead>
     590    <row>
     591      <entry align="center">
     592      Code
     593      </entry>
     594      <entry align="center">
     595      Area
     596      </entry>
     597      <entry>
     598      </entry>
     599      <entry align="left">
     600      Text and notes
     601      </entry>
     602    </row>
     603  </thead>
     604  <tbody>
     605    <row>
     606      <entry align="left">
     607      3001
     608      </entry>
     609      <entry align="center">
     610      MPSREAD
     611      </entry>
     612      <entry>
     613      </entry>
     614      <entry align="left">
     615      <computeroutput>
     616      Illegal value for %s of %g
     617      </computeroutput>
     618      </entry>
     619    </row>
     620    <row>
     621      <entry namest="c1" nameend="c3">
     622      </entry>
     623      <entry align="left">
     624      <simpara>
     625      String will be &quot;infinity&quot; if setInfinity passed bad value,
     626      or &quot;default integer bound&quot; if setDefaultBound passed bad value.
     627      </simpara>
     628      </entry>
     629    </row>
     630    <row>
     631      <entry align="left">
     632      3002
     633      </entry>
     634      <entry align="center">
     635      MPSREAD
     636      </entry>
     637      <entry>
     638      </entry>
     639      <entry align="left">
     640      <computeroutput>
     641      Bad image at line %d &lt; %s &gt;
     642      </computeroutput>
     643      </entry>
     644    </row>
     645    <row>
     646      <entry namest="c1" nameend="c3">
     647      </entry>
     648      <entry align="left">
     649      <simpara>
     650      This gives line number and the offending line
     651      </simpara>
     652      </entry>
     653    </row>
     654    <row>
     655      <entry align="left">
     656      3003
     657      </entry>
     658      <entry align="center">
     659      MPSREAD
     660      </entry>
     661      <entry>
     662      </entry>
     663      <entry align="left">
     664      <computeroutput>
     665      Duplicate objective at line %d &lt; %s &gt;
     666      </computeroutput>
     667      </entry>
     668    </row>
     669    <row>
     670      <entry namest="c1" nameend="c3">
     671      </entry>
     672      <entry align="left">
     673      <simpara>
     674      An objective row appears twice in one column
     675      </simpara>
     676      </entry>
     677    </row>
     678    <row>
     679      <entry align="left">
     680      3004
     681      </entry>
     682      <entry align="center">
     683      MPSREAD
     684      </entry>
     685      <entry>
     686      </entry>
     687      <entry align="left">
     688      <computeroutput>
     689      Duplicate row %s at line %d %s
     690      </computeroutput>
     691      </entry>
     692    </row>
     693    <row>
     694      <entry namest="c1" nameend="c3">
     695      </entry>
     696      <entry align="left">
     697      <simpara>
     698      The named row appears twice in one column.
     699      </simpara>
     700      </entry>
     701    </row>
     702    <row>
     703      <entry align="left">
     704      3005
     705      </entry>
     706      <entry align="center">
     707      MPSREAD
     708      </entry>
     709      <entry>
     710      </entry>
     711      <entry align="left">
     712      <computeroutput>
     713      No match for row %s at line %d &lt; %s &gt;
     714      </computeroutput>
     715      </entry>
     716    </row>
     717    <row>
     718      <entry namest="c1" nameend="c3">
     719      </entry>
     720      <entry align="left">
     721      <simpara>
     722      The named row did not appear in ROWS section.
     723      </simpara>
     724      </entry>
     725    </row>
     726    <row>
     727      <entry align="left">
     728      3006
     729      </entry>
     730      <entry align="center">
     731      MPSREAD
     732      </entry>
     733      <entry>
     734      </entry>
     735      <entry align="left">
     736      <computeroutput>
     737      No match for column at line %d &lt; %s &gt;
     738      </computeroutput>
     739      </entry>
     740    </row>
     741    <row>
     742      <entry namest="c1" nameend="c3">
     743      </entry>
     744      <entry align="left">
     745      <simpara>
     746      The named column (in BOUNDS section) did not appear in COLUMNS section.
     747      </simpara>
     748      </entry>
     749    </row>
     750    <row>
     751      <entry align="left">
     752      6001
     753      </entry>
     754      <entry align="center">
     755      MPSREAD
     756      </entry>
     757      <entry>
     758      </entry>
     759      <entry align="left">
     760      <computeroutput>
     761      Unable to open mps input file %s
     762      </computeroutput>
     763      </entry>
     764    </row>
     765    <row>
     766      <entry namest="c1" nameend="c3">
     767      </entry>
     768      <entry align="left">
     769      <simpara>
     770     
     771      </simpara>
     772      </entry>
     773    </row>
     774    <row>
     775      <entry align="left">
     776      6002
     777      </entry>
     778      <entry align="center">
     779      MPSREAD
     780      </entry>
     781      <entry>
     782      </entry>
     783      <entry align="left">
     784      <computeroutput>
     785      Unknown image %s at line %d of file %s
     786      </computeroutput>
     787      </entry>
     788    </row>
     789    <row>
     790      <entry namest="c1" nameend="c3">
     791      </entry>
     792      <entry align="left">
     793      <simpara>
     794      The Mps reader could not make sense of the image file specified.
     795      </simpara>
     796      </entry>
     797    </row>
     798    <row>
     799      <entry align="left">
     800      6003
     801      </entry>
     802      <entry align="center">
     803      MPSREAD
     804      </entry>
     805      <entry>
     806      </entry>
     807      <entry align="left">
     808      <computeroutput>
     809      Consider the possibility of a compressed file which zlib is unable to read.
     810      </computeroutput>
     811      </entry>
     812    </row>
     813    <row>
     814      <entry namest="c1" nameend="c3">
     815      </entry>
     816      <entry align="left">
     817      <simpara>
     818      Some .gz files can not be read by zlib.  Using gunzip and then gzip
     819      normally cures problem.
     820      </simpara>
     821      </entry>
     822    </row>
     823    <row>
     824      <entry align="left">
     825      6004
     826      </entry>
     827      <entry align="center">
     828      MPSREAD
     829      </entry>
     830      <entry>
     831      </entry>
     832      <entry align="left">
     833      <computeroutput>
     834      EOF on file %s
     835      </computeroutput>
     836      </entry>
     837    </row>
     838    <row>
     839      <entry namest="c1" nameend="c3">
     840      </entry>
     841      <entry align="left">
     842      <simpara>
     843      The Mps reader did not find expected section marker.     
     844      </simpara>
     845      </entry>
     846    </row>
     847    <row>
     848      <entry align="left">
     849      6005
     850      </entry>
     851      <entry align="center">
     852      MPSREAD
     853      </entry>
     854      <entry>
     855      </entry>
     856      <entry align="left">
     857      <computeroutput>
     858      Returning as too many errors
     859      </computeroutput>
     860      </entry>
     861    </row>
     862    <row>
     863      <entry namest="c1" nameend="c3">
     864      </entry>
     865      <entry align="left">
     866      <simpara>
     867      The reader has put out 100 messages and is giving up.
     868      </simpara>
     869      </entry>
     870    </row>
     871    <row>
     872      <entry align="left">
     873      507
     874      </entry>
     875      <entry align="center">
     876      PRESOLVE
     877      </entry>
     878      <entry>
     879      </entry>
     880      <entry align="left">
     881      <computeroutput>
     882      Presolve determined that the problem is infeasible with tolerance of %g
     883      </computeroutput>
     884      </entry>
     885    </row>
     886    <row>
     887      <entry namest="c1" nameend="c3">
     888      </entry>
     889      <entry align="left">
     890      <simpara>
     891      If you want you can try with a larger tolerance
     892      </simpara>
     893      </entry>
     894    </row>
     895    <row>
     896      <entry align="left">
     897      508
     898      </entry>
     899      <entry align="center">
     900      PRESOLVE
     901      </entry>
     902      <entry>
     903      </entry>
     904      <entry align="left">
     905      <computeroutput>
     906      Presolve thinks problem is unbounded
     907      </computeroutput>
     908      </entry>
     909    </row>
     910    <row>
     911      <entry namest="c1" nameend="c3">
     912      </entry>
     913      <entry align="left">
     914      <simpara>
     915      Perhaps the user should maximize if initially minimizing or vice versa.
     916      </simpara>
     917      </entry>
     918    </row>
     919    <row>
     920      <entry align="left">
     921      509
     922      </entry>
     923      <entry align="center">
     924      PRESOLVE
     925      </entry>
     926      <entry>
     927      </entry>
     928      <entry align="left">
     929      <computeroutput>
     930      Presolve thinks problem is infeasible AND unbounded???
     931      </computeroutput>
     932      </entry>
     933    </row>
     934    <row>
     935      <entry namest="c1" nameend="c3">
     936      </entry>
     937      <entry align="left">
     938      <simpara>
     939      If you get this message we want to know
     940      </simpara>
     941      </entry>
     942    </row>
     943  </tbody>
     944  </tgroup>
     945  </table>
     946
     947  <table frame="none" align="left">
     948  <title>
     949  CLP Messages passed at or above logging level 0
     950  </title>
     951  <tgroup cols="4" colsep="1" rowsep="1">
     952  <colspec colname="c1"/>
     953  <colspec colname="c2"/>
     954  <colspec colname="c3"/>
     955  <colspec colname="c4"/>
     956  <thead>
     957    <row>
     958      <entry align="center">
     959      Code
     960      </entry>
     961      <entry align="center">
     962      Area
     963      </entry>
     964      <entry>
     965      </entry>
     966      <entry align="left">
     967      Text and notes
     968      </entry>
     969    </row>
     970  </thead>
     971  <tbody>
     972    <row>
     973      <entry align="left">
     974      3002
     975      </entry>
     976      <entry align="center">
     977      SIMPLEX
     978      </entry>
     979      <entry>
     980      </entry>
     981      <entry align="left">
     982      <computeroutput>
     983      Not solving empty problem - %d rows, %d columns and %d elements
     984      </computeroutput>
     985      </entry>
     986    </row>
     987    <row>
     988      <entry namest="c1" nameend="c3">
     989      </entry>
     990      <entry align="left">
     991      <simpara>
     992      Test problem size before solving.
     993      </simpara>
     994      </entry>
     995    </row>
     996    <row>
     997      <entry align="left">
     998      6002
     999      </entry>
     1000      <entry align="center">
     1001      SIMPLEX
     1002      </entry>
     1003      <entry>
     1004      </entry>
     1005      <entry align="left">
     1006      <computeroutput>
     1007      %d bad bound pairs or bad objectives were found
     1008      </computeroutput>
     1009      </entry>
     1010    </row>
     1011    <row>
     1012      <entry namest="c1" nameend="c3">
     1013      </entry>
     1014      <entry align="left">
     1015      <simpara>
     1016      Either the value in the objective was too large or a lower bound was
     1017      greater than an upper bound.
     1018      </simpara>
     1019      </entry>
     1020    </row>
     1021    <row>
     1022      <entry align="left">
     1023      6003
     1024      </entry>
     1025      <entry align="center">
     1026      SIMPLEX
     1027      </entry>
     1028      <entry>
     1029      </entry>
     1030      <entry align="left">
     1031      <computeroutput>
     1032      Matrix has %d large values, first at column %d, row %d is %g
     1033      </computeroutput>
     1034      </entry>
     1035    </row>
     1036    <row>
     1037      <entry namest="c1" nameend="c3">
     1038      </entry>
     1039      <entry align="left">
     1040      <simpara>
     1041      Some of the values in matrix are ridiculous.
     1042      </simpara>
     1043      </entry>
     1044    </row>
     1045    <row>
     1046      <entry align="left">
     1047      6004
     1048      </entry>
     1049      <entry align="center">
     1050      SIMPLEX
     1051      </entry>
     1052      <entry>
     1053      </entry>
     1054      <entry align="left">
     1055      <computeroutput>
     1056      Can't get out of loop ...
     1057      </computeroutput>
     1058      </entry>
     1059    </row>
     1060    <row>
     1061      <entry namest="c1" nameend="c3">
     1062      </entry>
     1063      <entry align="left">
     1064      <simpara>
     1065     
     1066      </simpara>
     1067      </entry>
     1068    </row>
     1069  </tbody>
     1070  </tgroup>
     1071  </table>
     1072  <para>
     1073  There are also messages available at log level 2 (the most likely useful relate
     1074  to scaling), and will be addressed in a future version of this User Guide.
    81075  </para>
    91076</chapter>
  • trunk/Docs/moresamples.xml

    r405 r408  
    11<?xml version="1.0" encoding="ISO-8859-1"?>
    2 <chapter>
     2<chapter id="moreexamples">
    33<title>
    44More Samples
    55</title>
    66<para>
    7 Coming Soon
     7CLP includes a number of <filename>.cpp</filename> sample files.  They can be
     8found in the <filename>COIN/Clp/Samples</filename> directory.  Below is a table
     9listing some of the sample files with a short description for each.
    810</para>
     11<table frame="none">
     12  <title>Contents of the Samples directory</title>
     13  <tgroup cols="2">
     14    <thead>
     15      <row>
     16        <entry align="left" valign="bottom">
     17        Filename&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
     18        </entry>
     19        <entry align="left" valign="bottom">
     20        Description
     21        </entry>
     22      </row>
     23    </thead>
     24    <tbody>
     25      <row>
     26        <entry align="left" valign="top">
     27        <filename>minimum.cpp</filename>
     28        </entry>
     29        <entry align="left" valign="top">
     30        This is a CLP &lt;Hello, world&gt; program.  It reads an MPS file, and
     31        solves the problem.
     32        </entry>
     33      </row>
     34      <row>
     35        <entry align="left" valign="top">
     36        <filename>defaults.cpp</filename>
     37        </entry>
     38        <entry align="left" valign="top">
     39        This is one of the simpler drivers.  It sets tolerances to defaults and
     40        is a useful place to find simple use of &lt;sets&gt; and &lt;gets&gt;.
     41        It also prints out a full MPS-like solutions.
     42        </entry>
     43      </row>
     44      <row>
     45        <entry align="left" valign="top">
     46        <filename>driver.cpp</filename>
     47        </entry>
     48        <entry align="left" valign="top">
     49        This is designed to be the file that people modify to get a useful
     50        driver.  It does presolve.
     51        </entry>
     52      </row>
     53      <row>
     54        <entry align="left" valign="top">
     55        <filename>network.cpp</filename>
     56        </entry>
     57        <entry align="left" valign="top">
     58        This shows the use of non-standard matrices and how to load a problem
     59        without going throu MPS files.
     60        </entry>
     61      </row>
     62      <row>
     63        <entry align="left" valign="top">
     64        <filename>decompose.cpp</filename>
     65        </entry>
     66        <entry align="left" valign="top">
     67        This does full Dantzig-Wolfe decomposition.  It illustrates
     68        the use of many models, adding columns, et cetera.
     69        </entry>
     70      </row>
     71      <row>
     72        <entry align="left" valign="top">
     73        <filename>sprint.cpp</filename>
     74        </entry>
     75        <entry align="left" valign="top">
     76        This solves a long, thin problem by solving smaller subsets.  It is a
     77        simplified version of work done by one of the authors on aircrew
     78        scheduling problems.  It shows the use of two models and their
     79        synchronization.  A more general version can be found in
     80        <filename>COIN/Clp/ClpSolve.cpp</filename>
     81        </entry>
     82      </row>
     83      <row>
     84        <entry align="left" valign="top">
     85        <filename>sprint2.cpp</filename>
     86        </entry>
     87        <entry align="left" valign="top">
     88        This is similar to <filename>sprint.cpp</filename> but is designed for
     89        solving large problems with little choice.  The idea is that if
     90        relatively few variables are fixed, presolve can greatly reduce the
     91        problem size so that a series of solves can get close to the optimal
     92        solution much faster than would a na&iuml;ve solve of the full problem.
     93        </entry>
     94      </row>
     95    </tbody>
     96  </tgroup>
     97</table>
    998</chapter>
  • trunk/Docs/notsobasic.xml

    r405 r408  
    11<?xml version="1.0" encoding="ISO-8859-1"?>
    2   <chapter>
     2  <chapter id="notsobasic">
    33  <title>
    4   Not-Quite-So-Basic Model Class
     4  Not-Quite-So-Basic Model Classes
    55  </title>
     6  <section>
     7  <title>Pivot Choices</title>
    68  <para>
    7   Coming Soon
     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.
    816  </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   };
     157
     158
     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>
    9173  </chapter>
Note: See TracChangeset for help on using the changeset viewer.