00001
00002
00003
00004
00005
00006
00007
00008
00009
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
00025 using namespace Couenne;
00026
00028 int CouenneProblem::findSOS (CbcModel *CbcModelPtr,
00029 OsiSolverInterface *solver,
00030 OsiObject **objects) {
00031
00032
00033
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
00060
00061
00062
00063
00064
00065
00066
00067
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;
00072
00073 if (defVar) {
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
00089
00090
00091
00092
00093 bool
00094 intSOS = (*v) -> isInteger (),
00095 isSOS = true,
00096 onlyOrigVars = true;
00097
00098
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) ||
00106 (fabs (Lb (l -> first -> Index ())) > COUENNE_EPS)) {
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)
00120 continue;
00121
00122
00123
00124
00125
00126
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
00140
00141
00142
00143 CbcSOS *newsos = new CbcSOS (CbcModelPtr, nelem, indices, NULL, nSOS, 1);
00144
00145 objects [nSOS] = newsos;
00146
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 }