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 "Constraint.h" 8 #include "LinearSpec.h" 9 #include "Variable.h" 10 11 #include "lp_lib.h" 12 13 14 /** 15 * Gets the index of the constraint. 16 * 17 * @return the index of the constraint 18 */ 19 int32 20 Constraint::Index() 21 { 22 int32 i = fLS->Constraints()->IndexOf(this); 23 if (i == -1) 24 printf("Constraint not part of fLS->Constraints()."); 25 return i + 1; 26 } 27 28 29 /** 30 * Gets the left side of the constraint. 31 * 32 * @return pointer to a BList containing the summands on the left side of the constraint 33 */ 34 BList* 35 Constraint::LeftSide() 36 { 37 return fLeftSide; 38 } 39 40 41 /** 42 * Sets the summands on the left side of the constraint. 43 * The old summands are NOT deleted. 44 * 45 * @param summands a BList containing the Summand objects that make up the new left side 46 */ 47 void 48 Constraint::SetLeftSide(BList* summands) 49 { 50 fLeftSide = summands; 51 UpdateLeftSide(); 52 } 53 54 55 void 56 Constraint::UpdateLeftSide() 57 { 58 double coeffs[fLeftSide->CountItems() + 2]; 59 int varIndexes[fLeftSide->CountItems() + 2]; 60 int32 i; 61 for (i = 0; i < fLeftSide->CountItems(); i++) { 62 Summand* s = (Summand*)fLeftSide->ItemAt(i); 63 coeffs[i] = s->Coeff(); 64 varIndexes[i] = s->Var()->Index(); 65 } 66 67 if (fDNegObjSummand != NULL && fOp != OperatorType(LE)) { 68 varIndexes[i] = fDNegObjSummand->Var()->Index(); 69 coeffs[i] = 1.0; 70 i++; 71 } 72 73 if (fDPosObjSummand != NULL && fOp != OperatorType(GE)) { 74 varIndexes[i] = fDPosObjSummand->Var()->Index(); 75 coeffs[i] = -1.0; 76 i++; 77 } 78 79 if (!set_rowex(fLS->fLP, this->Index(), i, &coeffs[0], &varIndexes[0])) 80 printf("Error in set_rowex."); 81 82 fLS->UpdateObjFunction(); 83 fLS->RemovePresolved(); 84 } 85 86 87 void 88 Constraint::SetLeftSide(double coeff1, Variable* var1) 89 { 90 for (int i=0; i<fLeftSide->CountItems(); i++) 91 delete (Summand*)fLeftSide->ItemAt(i); 92 fLeftSide->MakeEmpty(); 93 fLeftSide->AddItem(new Summand(coeff1, var1)); 94 UpdateLeftSide(); 95 } 96 97 98 void 99 Constraint::SetLeftSide(double coeff1, Variable* var1, 100 double coeff2, Variable* var2) 101 { 102 for (int i=0; i<fLeftSide->CountItems(); i++) 103 delete (Summand*)fLeftSide->ItemAt(i); 104 fLeftSide->MakeEmpty(); 105 fLeftSide->AddItem(new Summand(coeff1, var1)); 106 fLeftSide->AddItem(new Summand(coeff2, var2)); 107 UpdateLeftSide(); 108 } 109 110 111 void 112 Constraint::SetLeftSide(double coeff1, Variable* var1, 113 double coeff2, Variable* var2, 114 double coeff3, Variable* var3) 115 { 116 for (int i=0; i<fLeftSide->CountItems(); i++) 117 delete (Summand*)fLeftSide->ItemAt(i); 118 fLeftSide->MakeEmpty(); 119 fLeftSide->AddItem(new Summand(coeff1, var1)); 120 fLeftSide->AddItem(new Summand(coeff2, var2)); 121 fLeftSide->AddItem(new Summand(coeff3, var3)); 122 UpdateLeftSide(); 123 } 124 125 126 void 127 Constraint::SetLeftSide(double coeff1, Variable* var1, 128 double coeff2, Variable* var2, 129 double coeff3, Variable* var3, 130 double coeff4, Variable* var4) 131 { 132 for (int i=0; i<fLeftSide->CountItems(); i++) 133 delete (Summand*)fLeftSide->ItemAt(i); 134 fLeftSide->MakeEmpty(); 135 fLeftSide->AddItem(new Summand(coeff1, var1)); 136 fLeftSide->AddItem(new Summand(coeff2, var2)); 137 fLeftSide->AddItem(new Summand(coeff3, var3)); 138 fLeftSide->AddItem(new Summand(coeff4, var4)); 139 UpdateLeftSide(); 140 } 141 142 143 /** 144 * Gets the operator used for this constraint. 145 * 146 * @return the operator used for this constraint 147 */ 148 OperatorType 149 Constraint::Op() 150 { 151 return fOp; 152 } 153 154 155 /** 156 * Sets the operator used for this constraint. 157 * 158 * @param value operator 159 */ 160 void 161 Constraint::SetOp(OperatorType value) 162 { 163 fOp = value; 164 if (!set_constr_type(fLS->fLP, this->Index(), 165 ((fOp == OperatorType(EQ)) ? EQ 166 : (fOp == OperatorType(GE)) ? GE 167 : LE))) 168 printf("Error in set_constr_type."); 169 170 fLS->RemovePresolved(); 171 } 172 173 174 /** 175 * Gets the constant value that is on the right side of the operator. 176 * 177 * @return the constant value that is on the right side of the operator 178 */ 179 double 180 Constraint::RightSide() 181 { 182 return fRightSide; 183 } 184 185 186 /** 187 * Sets the constant value that is on the right side of the operator. 188 * 189 * @param value constant value that is on the right side of the operator 190 */ 191 void 192 Constraint::SetRightSide(double value) 193 { 194 fRightSide = value; 195 if (!set_rh(fLS->fLP, Index(), fRightSide)) 196 printf("Error in set_rh."); 197 198 fLS->RemovePresolved(); 199 } 200 201 202 /** 203 * Gets the penalty coefficient for negative deviations. 204 * 205 * @return the penalty coefficient 206 */ 207 double 208 Constraint::PenaltyNeg() 209 { 210 if (fDNegObjSummand == NULL) 211 return INFINITY; 212 return fDNegObjSummand->Coeff(); 213 } 214 215 216 /** 217 * The penalty coefficient for negative deviations from the soft constraint's exact solution, 218 * i.e. if the left side is too large. 219 * 220 * @param value coefficient of negative penalty <code>double</code> 221 */ 222 void 223 Constraint::SetPenaltyNeg(double value) 224 { 225 if (fDNegObjSummand == NULL) { 226 fDNegObjSummand = new Summand(value, new Variable(fLS)); 227 fLS->ObjFunction()->AddItem(fDNegObjSummand); 228 UpdateLeftSide(); 229 fLS->UpdateObjFunction(); 230 return; 231 } 232 233 if (value == fDNegObjSummand->Coeff()) 234 return; 235 236 fDNegObjSummand->SetCoeff(value); 237 fLS->UpdateObjFunction(); 238 } 239 240 241 /** 242 * Gets the penalty coefficient for positive deviations. 243 * 244 * @return the penalty coefficient 245 */ 246 double 247 Constraint::PenaltyPos() 248 { 249 if (fDPosObjSummand == NULL) 250 return INFINITY; 251 return fDPosObjSummand->Coeff(); 252 } 253 254 255 /** 256 * The penalty coefficient for negative deviations from the soft constraint's exact solution, 257 * i.e. if the left side is too small. 258 * 259 * @param value coefficient of positive penalty <code>double</code> 260 */ 261 void 262 Constraint::SetPenaltyPos(double value) 263 { 264 if (fDPosObjSummand == NULL) { 265 fDPosObjSummand = new Summand(value, new Variable(fLS)); 266 fLS->ObjFunction()->AddItem(fDPosObjSummand); 267 UpdateLeftSide(); 268 fLS->UpdateObjFunction(); 269 return; 270 } 271 272 if (value == fDPosObjSummand->Coeff()) 273 return; 274 275 fDPosObjSummand->SetCoeff(value); 276 fLS->UpdateObjFunction(); 277 } 278 279 280 /** 281 * Gets the slack variable for the negative variations. 282 * 283 * @return the slack variable for the negative variations 284 */ 285 Variable* 286 Constraint::DNeg() const 287 { 288 if (fDNegObjSummand == NULL) 289 return NULL; 290 return fDNegObjSummand->Var(); 291 } 292 293 294 /** 295 * Gets the slack variable for the positive variations. 296 * 297 * @return the slack variable for the positive variations 298 */ 299 Variable* 300 Constraint::DPos() const 301 { 302 if (fDPosObjSummand == NULL) 303 return NULL; 304 return fDPosObjSummand->Var(); 305 } 306 307 308 /** 309 * Constructor. 310 */ 311 Constraint::Constraint(LinearSpec* ls, BList* summands, OperatorType op, 312 double rightSide, double penaltyNeg, double penaltyPos) 313 { 314 fLS = ls; 315 fLeftSide = summands; 316 fOp = op; 317 fRightSide = rightSide; 318 319 double coeffs[summands->CountItems() + 2]; 320 int varIndexes[summands->CountItems() + 2]; 321 int32 i; 322 for (i = 0; i < summands->CountItems(); i++) { 323 Summand* s = (Summand*)summands->ItemAt(i); 324 coeffs[i] = s->Coeff(); 325 varIndexes[i] = s->Var()->Index(); 326 } 327 328 if (penaltyNeg != INFINITY 329 && fOp != OperatorType(LE)) { 330 fDNegObjSummand = new Summand(penaltyNeg, new Variable(ls)); 331 ls->fObjFunction->AddItem(fDNegObjSummand); 332 varIndexes[i] = fDNegObjSummand->Var()->Index(); 333 coeffs[i] = 1.0; 334 i++; 335 } 336 else 337 fDNegObjSummand = NULL; 338 339 if (penaltyPos != INFINITY 340 && fOp != OperatorType(GE)) { 341 fDPosObjSummand = new Summand(penaltyPos, new Variable(ls)); 342 ls->fObjFunction->AddItem(fDPosObjSummand); 343 varIndexes[i] = fDPosObjSummand->Var()->Index(); 344 coeffs[i] = -1.0; 345 i++; 346 } 347 else 348 fDPosObjSummand = NULL; 349 350 if (!add_constraintex(ls->fLP, i, &coeffs[0], &varIndexes[0], 351 ((fOp == OperatorType(EQ)) ? EQ 352 : (fOp == OperatorType(GE)) ? GE 353 : LE), rightSide)) 354 printf("Error in add_constraintex."); 355 356 fLS->UpdateObjFunction(); 357 ls->Constraints()->AddItem(this); 358 } 359 360 361 /** 362 * Destructor. 363 * Removes the constraint from its specification and deletes all the summands. 364 */ 365 Constraint::~Constraint() 366 { 367 for (int i=0; i<fLeftSide->CountItems(); i++) 368 delete (Summand*)fLeftSide->ItemAt(i); 369 delete fLeftSide; 370 371 if (fDNegObjSummand != NULL) { 372 delete fDNegObjSummand->Var(); 373 delete fDNegObjSummand; 374 } 375 if (fDPosObjSummand != NULL) { 376 delete fDPosObjSummand->Var(); 377 delete fDPosObjSummand; 378 } 379 380 del_constraint(fLS->fLP, Index()); 381 fLS->Constraints()->RemoveItem(this); 382 } 383 384