/home/coin/SVN-release/OS-2.4.1/Couenne/src/problem/CouenneSOS.cpp

Go to the documentation of this file.
00001 /* $Id: CouenneSOS.cpp 549 2011-03-26 17:44:33Z pbelotti $
00002  *
00003  * Name:    CouenneSOS.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: find SOS constraints in problem and add them to list of
00006  *          branching objects
00007  *
00008  * (C) Carnegie-Mellon University, 2008-10.
00009  * This file is licensed under the Eclipse Public License (EPL)
00010  */
00011 
00012 #include <vector>
00013 
00014 #include "CouenneExprGroup.hpp"
00015 #include "CouenneExprAux.hpp"
00016 
00017 #include "CbcModel.hpp"
00018 #include "CbcBranchActual.hpp"
00019 #include "CbcCutGenerator.hpp"
00020 #include "CbcCompareActual.hpp"
00021 
00022 #include "CouenneProblem.hpp"
00023 
00024 //using namespace Osi;
00025 using namespace Couenne;
00026 
00028 int CouenneProblem::findSOS (CbcModel *CbcModelPtr,
00029                              OsiSolverInterface *solver,
00030                              OsiObject **objects) {
00031 
00032   // check auxiliaries defined as 
00033   // x_i binary. Disable it and add relative SOS to array "objects"
00034 
00035   int nSOS = 0;
00036 
00037   for (std::vector <exprVar *>::const_iterator v = variables_.begin ();
00038        v != variables_.end (); ++v) 
00039 
00040     if (((*v) -> Type             () ==                AUX) &&
00041         ((*v) -> Multiplicity     () >                   0) &&
00042         ((*v) -> sign             () == expression::AUX_EQ) &&
00043         ((*v) -> Image () -> code () ==      COU_EXPRGROUP)) {
00044 
00045       expression *img = (*v) -> Image ();
00046 
00047       exprGroup *group = dynamic_cast <exprGroup *> (img -> isaCopy () ? 
00048                                                      img -> Copy () :
00049                                                      img);
00050       if (!group)
00051         continue;
00052 
00053       int wind = (*v) -> Index ();
00054       CouNumber cterm = group -> getc0 ();
00055       bool 
00056         defVar    = true, 
00057         invertSOS = false;
00058 
00059       // now check if this is 
00060       //
00061       // defvar==true:
00062       // 1)  an auxiliary fixed to one  ==> it's a SOS if its image is  x1+x2+...+xk
00063       // 1a) an auxiliary fixed to -1   ==> it's a SOS if its image is -x1-x2-...-xk (see minlplib/csched2)
00064       //
00065       // defvar==false:
00066       // 2)  an auxiliary fixed to zero ==> it's a SOS if its image is -x1-x2-...-xk+1
00067       // 2a)                                        or if its image is  x1+x2+...+xk-1
00068 
00069       if      (fabs (cterm - 1.) < COUENNE_EPS) {defVar = false;}
00070       else if (fabs (cterm + 1.) < COUENNE_EPS) {defVar = false; invertSOS = true;}
00071       else if (fabs (cterm)      > COUENNE_EPS) continue; // and defVar is true
00072 
00073       if (defVar) {                                  // implies cterm == 0
00074         if        ((fabs (Lb (wind) + 1.) < COUENNE_EPS) && (fabs (Ub (wind) + 1.) < COUENNE_EPS)) invertSOS = true;
00075         else if (!((fabs (Lb (wind) - 1.) < COUENNE_EPS) && (fabs (Ub (wind) - 1.) < COUENNE_EPS))) continue;
00076       } else
00077 
00078         if ((fabs (Lb (wind)) > COUENNE_EPS) ||
00079             (fabs (Ub (wind)) > COUENNE_EPS))
00080           continue;
00081 
00082       size_t lsz = group -> lcoeff (). size ();
00083 
00084       if (((lsz <= 2) &&  defVar) ||
00085           ((lsz <= 1) && !defVar))
00086         continue;
00087 
00088       // there are two possibilities:
00089       //
00090       // 1) w is defined as w = 1 - \sum_{i=0}^n x_i         -- defvar = false
00091       // 2) w is defined as \sum_{i=0}^n x_i and w \in [1,1] -- defvar = true
00092 
00093       bool
00094         intSOS = (*v) -> isInteger (),
00095         isSOS  = true,
00096         onlyOrigVars = true; // if SOS constraint only contains
00097                              // original variables, it has been
00098                              // spotted by Cbc already
00099 
00100       exprGroup::lincoeff &lcoe = group -> lcoeff ();
00101       exprGroup::lincoeff::iterator l = lcoe. begin (); 
00102 
00103       for (;l != lcoe. end (); ++l) {
00104 
00105         if ((fabs (l -> second - (invertSOS ? -1. : 1.)) > COUENNE_EPS) || // wrong coefficient?
00106             (fabs (Lb (l -> first -> Index ()))          > COUENNE_EPS)) { // positive lower bound?
00107 
00108           isSOS = false;
00109           break;
00110 
00111         } else 
00112           if (!(l -> first -> isInteger ()))
00113             intSOS = false;
00114 
00115         if (l -> first -> Index () >= nOrigVars_) // 
00116           onlyOrigVars = false;
00117       }
00118 
00119       if (!isSOS || !intSOS)// || onlyOrigVars) 
00120         continue;
00121 
00122       // printf ("----- found SOS: ");
00123       // (*v) -> print (); printf (" := ");
00124       // (*v) -> Image () -> print (); printf ("\n");
00125 
00126       // it is a SOS -- if intSOS==true, it's also integer
00127 
00128       int
00129         indStart = defVar ? 0 : 1,
00130         nelem    = indStart + lcoe. size (), 
00131         *indices = new int [nelem];
00132 
00133       if (!defVar)
00134         indices [0] = (*v) -> Index ();
00135 
00136       for (int i=indStart, j=0; i<nelem; i++)
00137         indices [i] = lcoe [j++]. first -> Index ();
00138 
00139       // TODO: if use Cbc, add CbcSOSBranchingObject
00140 
00141       //CouenneSOSObject *newsos = new CouenneSOSObject (solver, nelem, indices, NULL, 1, jnlst_, true, true);
00142       //OsiSOS *newsos = new OsiSOS (solver, nelem, indices, NULL, 1);
00143       CbcSOS *newsos = new CbcSOS (CbcModelPtr, nelem, indices, NULL, nSOS, 1);
00144 
00145       objects [nSOS] = newsos;
00146       // as in BonBabSetupBase.cpp:675
00147       newsos -> setPriority (10);
00148       newsos -> setIntegerValued (intSOS);
00149 
00150       nSOS++;
00151     }
00152 
00153   if (nSOS)
00154     jnlst_ -> Printf (Ipopt::J_ERROR, J_COUENNE, "%d SOS constraint%s found\n", nSOS, nSOS == 1 ? "" : "s");
00155 
00156   return nSOS;
00157 }

Generated on Thu Nov 10 03:05:46 2011 by  doxygen 1.4.7