00001 #include "simplex.h"
00002
00003 #include "defines.h"
00004 #include "random.h"
00005
00006
00019 void SimplexExpandBounds(unsigned int eq_type,Tinterval *b)
00020 {
00021 double v1,v2;
00022
00023 v1=LowerLimit(b);
00024 v2=UpperLimit(b);
00025
00026 if (eq_type==LEQ)
00027 v1=-INF;
00028 else
00029 {
00030 if (eq_type==GEQ)
00031 v2=INF;
00032 }
00033
00034 NewInterval(v1,v2,b);
00035 }
00036
00037
00038
00039
00040 void SetSimplexBounds(Tbox *b,TSimplex *lp)
00041 {
00042 unsigned int i;
00043 Tinterval *is;
00044 unsigned int nv;
00045
00046 #if (_DEBUG>4)
00047 printf(" Setting bound for columns (variable):\n");
00048 #endif
00049
00050 nv=GetBoxNIntervals(b);
00051 is=GetBoxIntervals(b);
00052 for(i=0;i<nv;i++)
00053 {
00054 SimplexSetColBounds(i,&(is[i]),lp);
00055
00056 #if (_DEBUG>4)
00057 printf(" %u: ",i);
00058 PrintInterval(stdout,&(is[i]));
00059 if (IntervalSize(&(is[i]))<INF)
00060 printf(" -> %g\n",IntervalSize(&(is[i])));
00061 else
00062 printf(" -> +inf\n");
00063 #endif
00064 }
00065 }
00066
00067 boolean SimplexAddNewConstraint(double epsilon,
00068 TLinearConstraint *lc,
00069 unsigned int eq_type,
00070 Tinterval *is,
00071 TSimplex *s)
00072 {
00073 boolean full;
00074 TLinearConstraint lcInt;
00075 unsigned int n;
00076 Tinterval bounds;
00077 double es;
00078
00079 full=TRUE;
00080
00081
00082
00083 CopyLinearConstraint(&lcInt,lc);
00084
00085 #if (_DEBUG>4)
00086 printf(" Adding new constraint:\n ");
00087 PrintLinearConstraint(stdout,TRUE,NULL,&lcInt);
00088 #endif
00089
00090
00091
00092 CleanLinearConstraint((_SIMPLEX_ENGINE==_GLPK?epsilon:ZERO),is,&lcInt);
00093
00094 #if (_DEBUG>4)
00095 printf(" Constraint after cleaning:\n ");
00096 PrintLinearConstraint(stdout,TRUE,NULL,&lcInt);
00097 #endif
00098
00099 n=GetNumTermsInLinearConstraint(&lcInt);
00100
00101 if (n>0)
00102 {
00103
00104
00105
00106 GetLinearConstraintError(&bounds,&lcInt);
00107 SimplexExpandBounds(eq_type,&bounds);
00108 SetLinearConstraintError(&bounds,&lcInt);
00109
00110 #if (_DEBUG>4)
00111 printf(" Constraint after expanding bounds:\n ");
00112 PrintLinearConstraint(stdout,TRUE,NULL,&lcInt);
00113 #endif
00114
00115 if (!SimplifyLinearConstraint(&full,is,&lcInt))
00116 {
00117
00118
00119
00120
00121 es=IntervalSize(&bounds);
00122 if ((eq_type==EQU)&&(es>0.0)&&(es<epsilon)&&(epsilon>=1e-6))
00123 SimplexExpandBounds((randomDouble()<0.5?LEQ:GEQ),&bounds);
00124 SetLinearConstraintError(&bounds,&lcInt);
00125
00126
00127 SimplexAddNewConstraintRaw(&lcInt,s);
00128 }
00129 #if (_DEBUG>4)
00130 else
00131 printf(" Empty simplified equation\n");
00132 #endif
00133 }
00134 #if (_DEBUG>4)
00135 else
00136 printf(" Empty input equation\n");
00137 #endif
00138
00139 DeleteLinearConstraint(&lcInt);
00140
00141 return(full);
00142 }
00143
00144 double SimplexGetOptimalValue(unsigned int safe_simplex,double m,Tbox *x,TSimplex *s)
00145 {
00146 double o_safe;
00147
00148 if (safe_simplex==0)
00149 o_safe=SimplexGetOptimalValueRaw(s);
00150 else
00151 {
00152
00153
00154
00155
00156
00157
00158 double *lambda,*obj_c;
00159 double o,rl,ru;
00160 unsigned int n,m;
00161 unsigned int i,j,k;;
00162 Tinterval r,obj,a;
00163 TLinearConstraint lc;
00164 Tinterval bounds;
00165 double ct_l,ct_u;
00166 TLinearConstraint s_obj;
00167
00168 m=SimplexNRows(s);
00169 n=SimplexNColumns(s);
00170
00171 NEW(lambda,m,double);
00172 for(j=0;j<m;j++)
00173 lambda[j]=SimplexGetRowDual(j,s);
00174
00175 NEW(obj_c,n,double);
00176 for(i=0;i<n;i++)
00177 obj_c[i]=0.0;
00178 SimplexGetOptimizationFunction(&s_obj,s);
00179 k=GetNumTermsInLinearConstraint(&s_obj);
00180 for(i=0;i<k;i++)
00181 obj_c[GetLinearConstraintVariable(i,&s_obj)]=GetLinearConstraintCoefficient(i,&s_obj);
00182 DeleteLinearConstraint(&s_obj);
00183
00184
00185
00186
00187
00188
00189
00190
00191 o_safe=0.0;
00192 ROUNDDOWN;
00193 for(j=0;j<m;j++)
00194 {
00195 SimplexGetRowBounds(j,&bounds,s);
00196
00197 ct_l=LowerLimit(&bounds);
00198 ct_u=UpperLimit(&bounds);
00199
00200 if ((ct_u==INF)||(lambda[j]>0))
00201 o_safe+=(lambda[j]*ct_l);
00202 else
00203 o_safe+=(lambda[j]*ct_u);
00204 }
00205 ROUNDNEAR;
00206
00207 NewInterval(0,0,&obj);
00208
00209 for(i=0;i<n;i++)
00210 {
00211
00212 SimplexGetColConstraint(i,&lc,s);
00213 k=GetNumTermsInLinearConstraint(&lc);
00214
00215 ROUNDDOWN;
00216 rl=-obj_c[i];
00217 for(j=0;j<k;j++)
00218 rl+=(GetLinearConstraintCoefficient(j,&lc)*lambda[GetLinearConstraintVariable(j,&lc)]);
00219
00220 ROUNDUP;
00221 ru=-obj_c[i];
00222 for(j=0;j<k;j++)
00223 ru+=(GetLinearConstraintCoefficient(j,&lc)*lambda[GetLinearConstraintVariable(j,&lc)]);
00224
00225 ROUNDNEAR;
00226 NewInterval(rl,ru,&r);
00227
00228
00229 IntervalProduct(&r,GetBoxInterval(i,x),&a);
00230
00231
00232 IntervalAdd(&obj,&a,&obj);
00233
00234 DeleteLinearConstraint(&lc);
00235 }
00236
00237 free(lambda);
00238 free(obj_c);
00239
00240 ROUNDDOWN;
00241 o_safe=o_safe-UpperLimit(&obj);
00242 ROUNDNEAR;
00243
00244 o=SimplexGetOptimalValueRaw(s);
00245
00246 o_safe=(o_safe<o?o_safe:o);
00247 }
00248
00249 return(o_safe<m?m:o_safe);
00250 }
00251
00252
00253
00254
00255
00256
00257
00258 unsigned int ReduceRange(double epsilon,unsigned int safe_simplex,
00259 unsigned int nv,Tbox *b,TSimplex *lp)
00260 {
00261 unsigned int j;
00262 unsigned int r;
00263 boolean empty;
00264 boolean err;
00265 Tinterval new_range;
00266 Tinterval *i_in;
00267 double s_in;
00268 double o;
00269 TLinearConstraint obj;
00270
00271 empty=FALSE;
00272 err=FALSE;
00273
00274
00275 SetSimplexBounds(b,lp);
00276
00277 #if (_SIMPLEX_ENGINE!=_CLP)
00278 if (safe_simplex>1)
00279 {
00280
00281 ResetSimplex(lp);
00282 }
00283 #endif
00284
00285 i_in=GetBoxInterval(nv,b);
00286
00287 s_in=IntervalSize(i_in);
00288
00289 #if (_DEBUG>4)
00290 printf(" Reducing interval %u via simplex\n",nv);
00291 printf(" Original Interval ");
00292 PrintInterval(stdout,i_in);
00293 if (s_in>=INF) printf(" s: inf\n");
00294 else printf(" s:%g\n",s_in);
00295 #endif
00296
00297 CopyInterval(&new_range,i_in);
00298
00299 if (s_in>=epsilon)
00300 {
00301 InitLinearConstraint(&obj);
00302
00303 for(j=0;((!empty)&&(!err)&&(j<2));j++)
00304 {
00305 ResetLinearConstraint(&obj);
00306 if (j==0)
00307 {
00308 AddTerm2LinearConstraint(nv,+1.0,&obj);
00309
00310 #if (_DEBUG>4)
00311 printf("Determining lower bound for variable %u -> \n",nv);
00312 #endif
00313 }
00314 else
00315 {
00316 AddTerm2LinearConstraint(nv,-1.0,&obj);
00317
00318 #if (_DEBUG>4)
00319 printf("Determining upper bound for variable %u -> \n",nv);
00320 #endif
00321 }
00322
00323 SimplexSetOptimizationFunction(&obj,lp);
00324
00325 #if (_SIMPLEX_ENGINE!=_CLP)
00326 if ((safe_simplex>2)&&(j==1))
00327 {
00328
00329
00330 ResetSimplex(lp);
00331 }
00332 #endif
00333
00334
00335 #if (_DEBUG>4)
00336 printf("==================================================================================\n");
00337 #endif
00338 r=SimplexSolve(lp);
00339
00340 if (r==REDUCED_BOX)
00341 {
00342 if (IntervalSize(i_in)<INF)
00343 o=SimplexGetOptimalValue(safe_simplex,(j==0?LowerLimit(i_in):-UpperLimit(i_in)),b,lp);
00344 else
00345 o=SimplexGetOptimalValueRaw(lp);
00346 }
00347
00348 #if (_SIMPLEX_ENGINE!=_CLP)
00349 if ((r==EMPTY_BOX)||
00350 (r==ERROR_IN_PROCESS)||
00351 ((j==1)&&(r==REDUCED_BOX)&&(-o<LowerLimit(&new_range))))
00352 {
00353
00354
00355
00356 ResetSimplex(lp);
00357 r=SimplexSolve(lp);
00358 }
00359 #endif
00360
00361 #if (_DEBUG>4)
00362 printf("==================================================================================\n");
00363 #endif
00364
00365 switch(r)
00366 {
00367 case REDUCED_BOX:
00368 if (j==0)
00369 {
00370 SetLowerLimit(o,&new_range);
00371
00372 #if (_DEBUG>4)
00373 printf(" The new lower limit is %g\n",LowerLimit(&new_range));
00374 #endif
00375 }
00376 else
00377 {
00378 SetUpperLimit(-o,&new_range);
00379
00380 #if (_DEBUG>4)
00381 printf(" The new upper limit is %g\n",UpperLimit(&new_range));
00382 fflush(stdout);
00383 #endif
00384 }
00385 break;
00386
00387 #if (_DEBUG>4)
00388 case UNBOUNDED_BOX:
00389 printf(" The range can not be bounded\n");
00390 break;
00391 #endif
00392
00393 case EMPTY_BOX:
00394 empty=TRUE;
00395 break;
00396
00397 case ERROR_IN_PROCESS:
00398 #if (_SIMPLEX_ENGINE!=_CLP)
00399 ResetSimplex(lp);
00400 #endif
00401 err=TRUE;
00402 break;
00403
00404 default:
00405 Error("Unknow Error in ReduceRange");
00406 }
00407 }
00408
00409 DeleteLinearConstraint(&obj);
00410
00411
00412 #if (_DEBUG>4)
00413 if (!empty)
00414 printf(" Interval out of simplex [%g %g] s:%g\n",
00415 LowerLimit(&new_range),
00416 UpperLimit(&new_range),
00417 IntervalSize(&new_range));
00418 else
00419 printf(" Empty Interval out of simplex\n");
00420 #endif
00421
00422
00423 if ((!empty)&&(!err))
00424 {
00425
00426
00427
00428
00429
00430
00431 if (EmptyInterval(&new_range))
00432 err=TRUE;
00433 else
00434 CopyInterval(i_in,&new_range);
00435 }
00436 }
00437 #if (_DEBUG>4)
00438 else
00439 printf(" Input interval is too small to be reduced any more\n");
00440 #endif
00441
00442 if (empty)
00443 return(EMPTY_BOX);
00444 else
00445 {
00446 if (err)
00447 return(ERROR_IN_PROCESS);
00448 else
00449 return(REDUCED_BOX);
00450 }
00451 }