Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members

OsiDylpSolverInterfaceTest.cpp

00001 
00006 #ifdef COIN_USE_DYLP
00007 
00008 #if defined(_MSC_VER)
00009 
00010 /* Turn off compiler warning about long names */
00011 #  pragma warning(disable:4786)
00012 
00013 #endif
00014 
00015 /* 
00016   Rudimentary tests for the Dylp OSI layer. The assumption is that
00017   OsiSolverInterfaceCommonUnitTest checks basic functionality. The routine
00018   test_starts does a cursory check of cold/warm/hot starts.
00019 
00020   These tests need to be sharpened considerably, if they are to have any
00021   teeth.
00022 */
00023 
00024 #include <iostream>
00025 #include <assert.h>
00026 #include "OsiDylpSolverInterface.hpp"
00027 #include "OsiDylpWarmStartBasis.hpp"
00028 #include "OsiDylpMessages.hpp"
00029 
00030 
00031 static char sccsid[] = "%W%     %G%" ;
00032 static char cvsid[] = "$Id: OsiDylpSolverInterfaceTest.cpp,v 1.8 2003/09/27 18:39:12 lou-oss Exp $" ;
00033 
00034 
00035 void test_starts (const std::string& mpsDir)
00036 /*
00037   This routine makes a number of checks for warm and hot start capabilities.
00038     * Create and attempt to set an empty warm start object.
00039     * Create an ODSI object and solve the exmip1 sample MPS file with
00040       initialSolve.
00041     * Get a warm start object, then destroy the ODSI object. Create a new ODSI
00042       object, clone the saved warm start, install it, and resolve. Check that
00043       the objective is the same and that we did not pivot.
00044     * Change the objective sense and resolve from hot start.
00045 */
00046 { OsiDylpSolverInterface *osi = new OsiDylpSolverInterface ;
00047   OsiHintStrength strength ;
00048   bool sense ;
00049   void *info ;
00050 
00051 /*
00052   Create an empty warm start object and try to set it. The create should
00053   succeed, the set should fail.
00054 */
00055   { std::cout << "Checking behaviour for empty warm start object.\n" ;
00056     CoinWarmStart *ws = osi->getWarmStart() ;
00057     assert(ws) ;
00058     assert(!osi->setWarmStart(ws)) ;
00059     delete ws ; }
00060 /*
00061   Read in exmip1 and solve it.
00062 */
00063   std::cout << "Boosting verbosity.\n" ;
00064   osi->setHintParam(OsiDoReducePrint,false) ;
00065 
00066   std::string exmpsfile = mpsDir+"exmip1" ;
00067   std::string probname ;
00068   std::cout << "Reading mps file \"" << exmpsfile << "\"\n" ;
00069   osi->readMps(exmpsfile.c_str(), "mps") ;
00070   assert(osi->getStrParam(OsiProbName,probname)) ;
00071   std::cout << "Solving " << probname << " ... \n" ;
00072   osi->initialSolve() ;
00073   double val = osi->getObjValue() ;
00074   std::cout << "And the answer is " << val << ".\n" ;
00075   assert(fabs(val - 3.23) < 0.01) ;
00076 /*
00077   Grab a warm start object.
00078 */
00079   std::cout << "Getting a warm start object ... \n" ;
00080   CoinWarmStart *ws = osi->getWarmStart() ;
00081   assert(ws) ;
00082 /*
00083   Brief interruption for an idiot check: are the signs of the reduced costs
00084   correct in the solution, given minimisation? Easy to test with status info
00085   from the warm start object.
00086 */
00087   { const double *cbar = osi->getReducedCost() ;
00088     std::cout << "Performing sanity test on reduced costs.\n" ;
00089     const CoinWarmStartBasis *wsb =
00090         dynamic_cast<CoinWarmStartBasis *>(ws) ;
00091     for (int j = 0 ; j < osi->getNumCols() ; j++)
00092     { switch (wsb->getStructStatus(j))
00093       { case CoinWarmStartBasis::atUpperBound:
00094         { if (cbar[j] > 0)
00095           { std::cout << "Sign error! " ;
00096             std::cout << "Var " << j
00097                       << " at upper bound, cbar = " << cbar[j] << ".\n" ; }
00098           break ; }
00099         case CoinWarmStartBasis::atLowerBound:
00100         { if (cbar[j] < 0)
00101           { std::cout << "Sign error! " ;
00102             std::cout << "Var " << j
00103                       << " at lower bound, cbar = " << cbar[j] << ".\n" ; }
00104           break ; }
00105         case CoinWarmStartBasis::basic:
00106         { if (fabs(cbar[j]) > 1.0e-5)
00107           { std::cout << "Value error! " ;
00108             std::cout << "Var " << j << " is basic, cbar = " << cbar[j] ;
00109             std::cout << ", should be zero" ;
00110             std::cout << ".\n" ; }
00111           break ; }
00112         default:
00113         { break ; } } } }
00114 /*
00115   Back to our regular programming.
00116 */
00117   std::cout << "Discarding current ODSI object ... \n" ;
00118   delete osi ;
00119 /*
00120   We've discarded the first solver. Create a second solver, and read in the
00121   problem. Clone the original warm start object and destroy the original.
00122   Install the clone in the new solver, and resolve. Check that we did not
00123   pivot and that the objective hasn't changed. Set the print level quite high.
00124 */
00125   std::cout << "Creating new ODSI object ... \n" ;
00126   osi = new OsiDylpSolverInterface ;
00127   assert(osi) ;
00128   std::cout << "Testing anonymous clone for warm start ... \n" ;
00129   CoinWarmStart *ws_clone = ws->clone() ;
00130   assert(ws_clone) ;
00131   delete ws ;
00132   ws = ws_clone ;
00133   ws_clone = 0 ;
00134 
00135   int level = 5 ;
00136   osi->setHintParam(OsiDoReducePrint,true,OsiForceDo,&level) ;
00137   osi->getHintParam(OsiDoReducePrint,sense,strength,info) ;
00138   std::cout << "Verbosity now maxed at " << *static_cast<int *>(info) << ".\n" ;
00139 
00140   osi->readMps(exmpsfile.c_str(), "mps") ;
00141 
00142   std::cout << "Installing cloned warm start object ... \n" ;
00143   assert(osi->setWarmStart(ws)) ;
00144   std::cout << "Resolving the lp ... \n" ;
00145 
00146   osi->resolve() ;
00147   val = osi->getObjValue() ;
00148   int pivots = osi->getIterationCount() ;
00149   std::cout << "\nAnd the answer is " << val << " after " <<
00150                pivots << " pivots.\n" ;
00151   delete ws ;
00152   assert(fabs(val - 3.23) < 0.01 && pivots == 0) ;
00153 
00154   osi->setHintParam(OsiDoReducePrint,true,OsiForceDo) ;
00155   std::cout << "Reducing verbosity.\n" ;
00156   std::cout << "Changing objective sense ..." ;
00157   osi->setObjSense(-1.0) ;
00158   std::cout << "Attempting hot start ..." ;
00159   osi->markHotStart() ;
00160   osi->solveFromHotStart() ;
00161   val = osi->getObjValue() ;
00162   std::cout << "\nAnd the answer is " << val << ".\n" ;
00163 /*
00164   Brief interruption for an idiot check again: are the signs of the reduced
00165   costs correct in the solution, given maximisation?
00166 */
00167   { const double *cbar = osi->getReducedCost() ;
00168     ws = osi->getWarmStart() ;
00169     const OsiDylpWarmStartBasis *odsi_wsb =
00170         dynamic_cast<OsiDylpWarmStartBasis *>(ws) ;
00171     std::cout << "Performing sanity test on reduced costs.\n" ;
00172     for (int j = 0 ; j < osi->getNumCols() ; j++)
00173     { switch (odsi_wsb->getStructStatus(j))
00174       { case CoinWarmStartBasis::atUpperBound:
00175         { if (cbar[j] < 0)
00176           { std::cout << "Sign error! " ;
00177             std::cout << "Var " << j
00178                       << " at upper bound, cbar = " << cbar[j] << ".\n" ; }
00179           break ; }
00180         case CoinWarmStartBasis::atLowerBound:
00181         { if (cbar[j] > 0)
00182           { std::cout << "Sign error! " ;
00183             std::cout << "Var " << j
00184                       << " at lower bound, cbar = " << cbar[j] << ".\n" ; }
00185           break ; }
00186         case CoinWarmStartBasis::basic:
00187         { if (fabs(cbar[j]) > 1.0e-5)
00188           { std::cout << "Value error! " ;
00189             std::cout << "Var " << j << " is basic, cbar = " << cbar[j] ;
00190             std::cout << ", should be zero" ;
00191             std::cout << ".\n" ; }
00192           break ; }
00193         default:
00194         { break ; } } }
00195     delete ws ; }
00196 /*
00197   Turn off printing, to make sure we can get dylp to shut up.
00198 */
00199   level = 0 ;
00200   osi->setHintParam(OsiDoReducePrint,true,OsiForceDo,&level) ;
00201   osi->getHintParam(OsiDoReducePrint,sense,strength,info) ;
00202   std::cout << "Verbosity now at " << *static_cast<int *>(info) << ".\n" ;
00203 
00204   std::cout << "And back ..." ;
00205   osi->setObjSense(1.0) ;
00206   std::cout << "Attempting hot start ..." ;
00207   osi->solveFromHotStart() ;
00208   val = osi->getObjValue() ;
00209   std::cout << "\nAnd the answer is " << val << ".\n" ;
00210   assert(fabs(val - 3.23) < 0.01) ;
00211 
00212   delete osi ;
00213 
00214   return ; } ;
00215 
00216 
00223 void OsiDylpSolverInterfaceUnitTest (const std::string &mpsDir,
00224                                      const std::string &netLibDir)
00225 /*
00226   Dylp unit test driver.
00227 */
00228 { std::cout << "Starting dylp OSI interface tests ...\n" ;
00229   OsiDylpSolverInterface* osi = new OsiDylpSolverInterface ;
00230   osi->handler_->setLogLevel(3) ;
00231   osi->handler_->message(ODSI_TEST_MSG,osi->messages_) ;
00232   osi->newLanguage(CoinMessages::uk_en) ;
00233   osi->handler_->message(ODSI_TEST_MSG,osi->messages_) ;
00234   osi->handler_->finish() ;
00235   std::cout <<
00236     "Calling OsiSolverInterfaceCommonUnitTest for basic tests ...\n" ;
00237   OsiSolverInterfaceCommonUnitTest(osi,mpsDir,netLibDir) ;
00238 /*
00239   Test the reset function.
00240 */
00241   std::cout << "Testing reset ...\n" ;
00242   OsiDylpSolverInterface* osi2 = new OsiDylpSolverInterface ;
00243   osi->reset() ;
00244   osi->assert_same(*osi,*osi2,true) ;
00245   delete osi ;
00246   delete osi2 ;
00247   std::cout <<
00248     "Testing cold/warm/hot start ...\n" ;
00249   test_starts(mpsDir) ;
00250 
00251   std::cout << "\n dylp tests completed.\n\n" ;
00252 
00253   return ; }
00254 
00255 #endif // COIN_USE_DYLP
00256 

Generated on Wed Dec 3 14:35:31 2003 for Osi by doxygen 1.3.5