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() const 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 Variable::operator BString() const 170 { 171 BString string; 172 GetString(string); 173 return string; 174 } 175 176 177 /** 178 * Returns index of the variable as String. 179 * E.g. "Var2" 180 * 181 * @return the <code>String</code> index of the variable 182 */ 183 void 184 Variable::GetString(BString& string) const 185 { 186 if (fLabel) { 187 string << fLabel; 188 if (!fIsValid) 189 string << "(invalid)"; 190 } else { 191 string << "Var"; 192 if (!fIsValid) 193 string << "(invalid," << (int32)this << ")"; 194 else 195 string << Index(); 196 } 197 } 198 199 200 /** 201 * Adds a constraint that sets this variable equal to the given one. 202 * 203 * @param var variable that should have the same value 204 * @return the new equality constraint 205 */ 206 Constraint* 207 Variable::IsEqual(Variable* var) 208 { 209 if (!fIsValid) 210 return NULL; 211 212 return fLS->AddConstraint(1.0, this, -1.0, var, OperatorType(EQ), 0.0); 213 } 214 215 216 /** 217 * Adds a constraint that sets this variable smaller or equal to the given one. 218 * 219 * @param var variable that should have a larger or equal value 220 * @return the new constraint 221 */ 222 Constraint* 223 Variable::IsSmallerOrEqual(Variable* var) 224 { 225 if (!fIsValid) 226 return NULL; 227 228 return fLS->AddConstraint(1.0, this, -1.0, var, OperatorType(LE), 0.0); 229 } 230 231 232 /** 233 * Adds a constraint that sets this variable greater or equal to the given one. 234 * 235 * @param var variable that should have a smaller or equal value 236 * @return the new constraint 237 */ 238 Constraint* 239 Variable::IsGreaterOrEqual(Variable* var) 240 { 241 if (!fIsValid) 242 return NULL; 243 244 return fLS->AddConstraint(-1.0, var, 1.0, this, OperatorType(GE), 0.0); 245 } 246 247 248 Constraint* 249 Variable::IsEqual(Variable* var, double penaltyNeg, double penaltyPos) 250 { 251 if (!fIsValid) 252 return NULL; 253 254 return fLS->AddConstraint(1.0, this, -1.0, var, OperatorType(EQ), 0.0, 255 penaltyNeg, penaltyPos); 256 } 257 258 259 Constraint* 260 Variable::IsSmallerOrEqual(Variable* var, double penaltyNeg, double penaltyPos) 261 { 262 if (!fIsValid) 263 return NULL; 264 265 return fLS->AddConstraint(1.0, this, -1.0, var, OperatorType(LE), 0.0, 266 penaltyNeg, penaltyPos); 267 } 268 269 270 Constraint* 271 Variable::IsGreaterOrEqual(Variable* var, double penaltyNeg, double penaltyPos) 272 { 273 if (!fIsValid) 274 return NULL; 275 276 return fLS->AddConstraint(-1.0, var, 1.0, this, OperatorType(GE), 0.0, 277 penaltyNeg, penaltyPos); 278 } 279 280 281 bool 282 Variable::IsValid() 283 { 284 return fIsValid; 285 } 286 287 288 void 289 Variable::Invalidate() 290 { 291 STRACE(("Variable::Invalidate() on %s\n", ToString())); 292 293 if (!fIsValid) 294 return; 295 296 fIsValid = false; 297 del_column(fLS->fLP, Index()); 298 fLS->Variables()->RemoveItem(this); 299 300 // invalidate all constraints that use this variable 301 BList* markedForInvalidation = new BList(); 302 BList* constraints = fLS->Constraints(); 303 for (int i = 0; i < constraints->CountItems(); i++) { 304 Constraint* constraint = static_cast<Constraint*>( 305 constraints->ItemAt(i)); 306 307 if (!constraint->IsValid()) 308 continue; 309 310 BList* summands = constraint->LeftSide(); 311 for (int j = 0; j < summands->CountItems(); j++) { 312 Summand* summand = static_cast<Summand*>(summands->ItemAt(j)); 313 if (summand->Var() == this) { 314 markedForInvalidation->AddItem(constraint); 315 break; 316 } 317 } 318 } 319 for (int i = 0; i < markedForInvalidation->CountItems(); i++) 320 static_cast<Constraint*>(markedForInvalidation->ItemAt(i)) 321 ->Invalidate(); 322 delete markedForInvalidation; 323 } 324 325 326 /** 327 * Constructor. 328 */ 329 Variable::Variable(LinearSpec* ls) 330 : fLS(ls), 331 fUsingSummands(new BList()), 332 fValue(NAN), 333 fMin(0), 334 fMax(DBL_MAX), 335 fLabel(NULL), 336 fIsValid(true) 337 { 338 fLS->Variables()->AddItem(this); 339 340 if (fLS->Variables()->CountItems() > fLS->CountColumns()) { 341 double d = 0; 342 int i = 0; 343 if (!add_columnex(fLS->fLP, 0, &d, &i)) 344 printf("Error in add_columnex."); 345 } 346 347 SetRange(-DBL_MAX, DBL_MAX); 348 } 349 350 351 /** 352 * Destructor. 353 * Removes the variable from its specification. 354 */ 355 Variable::~Variable() 356 { 357 Invalidate(); 358 free(fLabel); 359 delete fUsingSummands; 360 } 361 362