1 /* 2 * Copyright 2007-2008, Christof Lutteroth, lutteroth@cs.auckland.ac.nz 3 * Copyright 2007-2008, James Kim, jkim202@ec.auckland.ac.nz 4 * Distributed under the terms of the MIT License. 5 */ 6 7 #include "Variable.h" 8 #include "Constraint.h" 9 #include "LinearSpec.h" 10 #include "OperatorType.h" 11 12 #include "lp_lib.h" 13 14 #include <float.h> // for DBL_MAX 15 16 17 // Toggle debug output 18 //#define DEBUG_VARIABLE 19 20 #ifdef DEBUG_VARIABLE 21 # define STRACE(x) debug_printf x 22 #else 23 # define STRACE(x) ; 24 #endif 25 26 27 /** 28 * Gets index of the variable. 29 * 30 * @return the index of the variable 31 */ 32 int32 33 Variable::Index() 34 { 35 int32 i = fLS->Variables()->IndexOf(this); 36 if (i == -1) { 37 printf("Variable not part of fLS->Variables()."); 38 return -1; 39 } 40 return i + 1; 41 } 42 43 44 /** 45 * Gets the current linear specification. 46 * 47 * @return the current linear specification 48 */ 49 LinearSpec* 50 Variable::LS() const 51 { 52 return fLS; 53 } 54 55 56 /** 57 * Gets the value. 58 * 59 * @return the value 60 */ 61 double 62 Variable::Value() const 63 { 64 return fValue; 65 } 66 67 68 /** 69 * Sets the value. 70 * 71 * @param value the value 72 */ 73 void 74 Variable::SetValue(double value) 75 { 76 fValue = value; 77 } 78 79 80 /** 81 * Gets the minimum value of the variable. 82 * 83 * @return the minimum value of variable 84 */ 85 double 86 Variable::Min() const 87 { 88 return fMin; 89 } 90 91 92 /** 93 * Sets the minimum value of the variable. 94 * 95 * @param min minimum value 96 */ 97 void 98 Variable::SetMin(double min) 99 { 100 if (!fIsValid) 101 return; 102 103 fMin = min; 104 set_bounds(fLS->fLP, this->Index(), fMin, fMax); 105 } 106 107 108 /** 109 * Gets the maximum value of the variable. 110 * 111 * @return the maximum value of variable 112 */ 113 double 114 Variable::Max() const 115 { 116 return fMax; 117 } 118 119 120 /** 121 * Sets the maximum value of the variable. 122 * 123 * @param max maximum value 124 */ 125 void 126 Variable::SetMax(double max) 127 { 128 if (!fIsValid) 129 return; 130 131 fMax = max; 132 set_bounds(fLS->fLP, this->Index(), fMin, fMax); 133 } 134 135 136 /** 137 * Sets the minimum and maximum values of the variable. 138 * 139 * @param min minimum value 140 * @param max maximum value 141 */ 142 void 143 Variable::SetRange(double min, double max) 144 { 145 if (!fIsValid) 146 return; 147 148 fMin = min; 149 fMax = max; 150 set_bounds(fLS->fLP, this->Index(), fMin, fMax); 151 } 152 153 154 const char* 155 Variable::Label() 156 { 157 return fLabel; 158 } 159 160 161 void 162 Variable::SetLabel(const char* label) 163 { 164 fLabel = (char*) malloc(strlen(label) + 1); 165 strcpy(fLabel, label); 166 } 167 168 169 /** 170 * Returns index of the variable as String. 171 * E.g. "Var2" 172 * 173 * @return the <code>String</code> index of the variable 174 */ 175 BString* 176 Variable::ToBString() 177 { 178 BString* str = new BString(); 179 if (fLabel) { 180 *str << fLabel; 181 if (!fIsValid) 182 *str << "(invalid)"; 183 } else { 184 *str << "Var"; 185 if (!fIsValid) 186 *str << "(invalid," << (int32)this << ")"; 187 else 188 *str << Index(); 189 } 190 return str; 191 } 192 193 194 const char* 195 Variable::ToString() 196 { 197 BString* str = ToBString(); 198 char* result = (char*) malloc(str->Length() + 1); 199 str->CopyInto(result, 0, str->Length()); 200 delete str; 201 return result; 202 } 203 204 205 /** 206 * Adds a constraint that sets this variable equal to the given one. 207 * 208 * @param var variable that should have the same value 209 * @return the new equality constraint 210 */ 211 Constraint* 212 Variable::IsEqual(Variable* var) 213 { 214 if (!fIsValid) 215 return NULL; 216 217 return fLS->AddConstraint(1.0, this, -1.0, var, OperatorType(EQ), 0.0); 218 } 219 220 221 /** 222 * Adds a constraint that sets this variable smaller or equal to the given one. 223 * 224 * @param var variable that should have a larger or equal value 225 * @return the new constraint 226 */ 227 Constraint* 228 Variable::IsSmallerOrEqual(Variable* var) 229 { 230 if (!fIsValid) 231 return NULL; 232 233 return fLS->AddConstraint(1.0, this, -1.0, var, OperatorType(LE), 0.0); 234 } 235 236 237 /** 238 * Adds a constraint that sets this variable greater or equal to the given one. 239 * 240 * @param var variable that should have a smaller or equal value 241 * @return the new constraint 242 */ 243 Constraint* 244 Variable::IsGreaterOrEqual(Variable* var) 245 { 246 if (!fIsValid) 247 return NULL; 248 249 return fLS->AddConstraint(-1.0, var, 1.0, this, OperatorType(GE), 0.0); 250 } 251 252 253 Constraint* 254 Variable::IsEqual(Variable* var, double penaltyNeg, double penaltyPos) 255 { 256 if (!fIsValid) 257 return NULL; 258 259 return fLS->AddConstraint(1.0, this, -1.0, var, OperatorType(EQ), 0.0, 260 penaltyNeg, penaltyPos); 261 } 262 263 264 Constraint* 265 Variable::IsSmallerOrEqual(Variable* var, double penaltyNeg, double penaltyPos) 266 { 267 if (!fIsValid) 268 return NULL; 269 270 return fLS->AddConstraint(1.0, this, -1.0, var, OperatorType(LE), 0.0, 271 penaltyNeg, penaltyPos); 272 } 273 274 275 Constraint* 276 Variable::IsGreaterOrEqual(Variable* var, double penaltyNeg, double penaltyPos) 277 { 278 if (!fIsValid) 279 return NULL; 280 281 return fLS->AddConstraint(-1.0, var, 1.0, this, OperatorType(GE), 0.0, 282 penaltyNeg, penaltyPos); 283 } 284 285 286 bool 287 Variable::IsValid() 288 { 289 return fIsValid; 290 } 291 292 293 void 294 Variable::Invalidate() 295 { 296 STRACE(("Variable::Invalidate() on %s\n", ToString())); 297 298 if (!fIsValid) 299 return; 300 301 fIsValid = false; 302 del_column(fLS->fLP, Index()); 303 fLS->Variables()->RemoveItem(this); 304 305 // invalidate all constraints that use this variable 306 BList* markedForInvalidation = new BList(); 307 BList* constraints = fLS->Constraints(); 308 for (int i = 0; i < constraints->CountItems(); i++) { 309 Constraint* constraint = static_cast<Constraint*>( 310 constraints->ItemAt(i)); 311 312 if (!constraint->IsValid()) 313 continue; 314 315 BList* summands = constraint->LeftSide(); 316 for (int j = 0; j < summands->CountItems(); j++) { 317 Summand* summand = static_cast<Summand*>(summands->ItemAt(j)); 318 if (summand->Var() == this) { 319 markedForInvalidation->AddItem(constraint); 320 break; 321 } 322 } 323 } 324 for (int i = 0; i < markedForInvalidation->CountItems(); i++) 325 static_cast<Constraint*>(markedForInvalidation->ItemAt(i)) 326 ->Invalidate(); 327 delete markedForInvalidation; 328 } 329 330 331 /** 332 * Constructor. 333 */ 334 Variable::Variable(LinearSpec* ls) 335 : fLS(ls), 336 fUsingSummands(new BList()), 337 fValue(NAN), 338 fMin(0), 339 fMax(DBL_MAX), 340 fLabel(NULL), 341 fIsValid(true) 342 { 343 fLS->Variables()->AddItem(this); 344 345 if (fLS->Variables()->CountItems() > fLS->CountColumns()) { 346 double d = 0; 347 int i = 0; 348 if (!add_columnex(fLS->fLP, 0, &d, &i)) 349 printf("Error in add_columnex."); 350 } 351 } 352 353 354 /** 355 * Destructor. 356 * Removes the variable from its specification. 357 */ 358 Variable::~Variable() 359 { 360 Invalidate(); 361 free(fLabel); 362 delete fUsingSummands; 363 } 364 365