1 //------------------------------------------------------------------------
2 // P.J. Williams
3 // Sandia National Laboratories
4 // pwillia@sandia.gov
5 // Last modified 03/20/2003
6 //------------------------------------------------------------------------
7
8 #include "CompoundConstraint.h"
9 #include "ioformat.h"
10
11 using NEWMAT::ColumnVector;
12 using NEWMAT::Matrix;
13 using NEWMAT::SymmetricMatrix;
14 using std::cout;
15
16
17 namespace OPTPP {
18
19 // Constructors
CompoundConstraint()20 CompoundConstraint::CompoundConstraint(): constraints_(0),
21 numOfSets_(0), lower_(0) , upper_(0){}
22
CompoundConstraint(const Constraint & c1)23 CompoundConstraint::CompoundConstraint(const Constraint& c1):
24 constraints_(0), numOfSets_(1)
25 {
26 constraints_.append(c1);
27 lower_ = getLower();
28 upper_ = getUpper();
29 }
30
CompoundConstraint(const Constraint & c1,const Constraint & c2)31 CompoundConstraint::CompoundConstraint(const Constraint& c1,
32 const Constraint& c2):
33 constraints_(0), numOfSets_(2)
34 {
35 constraints_.append(c1);
36 constraints_.append(c2);
37 insertSort();
38 lower_ = getLower();
39 upper_ = getUpper();
40 }
41
CompoundConstraint(const OptppArray<Constraint> & constraints)42 CompoundConstraint::CompoundConstraint(const OptppArray<Constraint>& constraints):
43 constraints_(constraints), numOfSets_(constraints.length())
44 {
45 insertSort();
46 lower_ = getLower();
47 upper_ = getUpper();
48 }
49
CompoundConstraint(const CompoundConstraint & cc)50 CompoundConstraint::CompoundConstraint(const CompoundConstraint& cc):
51 constraints_(0), numOfSets_(cc.numOfSets_), lower_(cc.lower_),
52 upper_(cc.upper_)
53 {
54 if(numOfSets_ > 0){
55 for(int i = 0; i < numOfSets_; i++)
56 constraints_.append(cc[i]);
57 }
58 }
59
60 CompoundConstraint& CompoundConstraint::operator=(const CompoundConstraint& cc)
61 {
62 if(this != &cc){
63 numOfSets_ = cc.numOfSets_;
64 lower_ = cc.lower_;
65 upper_ = cc.upper_;
66 for(int i = 0; i < numOfSets_; i++)
67 constraints_.append(cc[i]);
68 }
69 return *this;
70 }
71
72 // Accessor Methods
getNumOfNLCons()73 int CompoundConstraint::getNumOfNLCons() const
74 {
75 int Mi, i, k = 0;
76 Constraint test;
77
78 for(i = 0; i < numOfSets_; i++){
79 test = constraints_[i];
80 ColumnVector temp = test.getConstraintType();
81 if (temp(1) == NLeqn || temp(1) == NLineq){
82 Mi = test.getNumOfCons();
83 k += Mi;
84 }
85 }
86 return k;
87 }
88
getNumOfCons()89 int CompoundConstraint::getNumOfCons() const
90 {
91 int Mi, i, k = 0;
92 Constraint test;
93
94 for(i = 0; i < numOfSets_; i++){
95 test = constraints_[i];
96 Mi = test.getNumOfCons();
97 k += Mi;
98 }
99 return k;
100 }
101
getNumOfVars()102 int CompoundConstraint::getNumOfVars() const
103 {
104 int Mi, i, k = 0;
105 Constraint test;
106
107 for(i = 0; i < numOfSets_; i++){
108 test = constraints_[i];
109 Mi = test.getNumOfVars();
110 k += Mi;
111 }
112 if( k!= 0 && k == Mi*numOfSets_ )
113 return Mi;
114 else
115 return 0;
116 }
117
getLower()118 ColumnVector CompoundConstraint::getLower() const
119 {
120 ColumnVector result(getNumOfCons());
121 Constraint test;
122
123 for(int i = 0; i < numOfSets_; i++){
124 test = constraints_[i];
125 ColumnVector temp = test.getLower();
126 if (i == 0)
127 result = temp;
128 else
129 result &= temp;
130 }
131 return result;
132 }
133
getUpper()134 ColumnVector CompoundConstraint::getUpper() const
135 {
136 ColumnVector result(getNumOfCons());
137 Constraint test;
138
139 for(int i = 0; i < numOfSets_; i++){
140 test = constraints_[i];
141 ColumnVector temp = test.getUpper();
142 if (i == 0)
143 result = temp;
144 else
145 result &= temp;
146 }
147 return result;
148
149 }
150
getConstraintType()151 ColumnVector CompoundConstraint::getConstraintType() const
152 {
153 ColumnVector result(getNumOfCons());
154 Constraint test;
155
156 for(int i = 0; i < numOfSets_; i++){
157 test = constraints_[i];
158 ColumnVector temp = test.getConstraintType();
159 if (i == 0)
160 result = temp;
161 else
162 result &= temp;
163 }
164 return result;
165 }
166
getConstraintMappingIndices()167 OptppArray<int> CompoundConstraint::getConstraintMappingIndices() const
168 {
169 OptppArray<int> result;
170 Constraint test;
171
172 for(int i = 0; i < numOfSets_; i++){
173 test = constraints_[i];
174 OptppArray<int> temp = test.getConstraintMappingIndices();
175 for(int j = 0; j < temp.length(); j++)
176 result.append(temp[j]);
177 }
178 return result;
179
180 }
181
getConstraintValue()182 ColumnVector CompoundConstraint::getConstraintValue() const
183 {
184 /*
185 * Returns the raw value of all the constraints.
186 */
187
188 Constraint test;
189 ColumnVector temp, value;
190
191 for(int i = 0; i < numOfSets_; i++){
192 test = constraints_[i];
193 temp = test.getConstraintValue();
194
195 if (i == 0)
196 value = temp;
197 else
198 value &= temp;
199 }
200 return value;
201 }
202
getNLConstraintValue()203 ColumnVector CompoundConstraint::getNLConstraintValue() const
204 {
205 /*
206 * Returns the raw value of the nonlinear equations and inequalities.
207 */
208
209 int j = 0;
210 Constraint test;
211 ColumnVector temp, type, value, zero(1);
212
213 // If there are no nonlinear constraints, initialize a return value of zero
214 zero = 0;
215
216 for(int i = 0; i < numOfSets_; i++){
217 test = constraints_[i];
218 type = test.getConstraintType();
219
220 if(type(1) == NLeqn || type(1) == NLineq){
221 temp = test.getConstraintValue();
222 if(j == 0)
223 value = temp;
224 else
225 value &= temp;
226 j++;
227 }
228 }
229
230 if( j == 0) value = zero;
231
232 return value;
233 }
234
getConstraintViolation()235 ColumnVector CompoundConstraint::getConstraintViolation() const
236 {
237 /* CPJW - Rethink!
238 * Returns the infeasibility with respect to the constraints.
239 */
240
241 Constraint test;
242 ColumnVector temp, value;
243
244 for(int i = 0; i < numOfSets_; i++){
245 test = constraints_[i];
246 temp = test.getConstraintViolation();
247
248 if(i == 0)
249 value = temp;
250 else
251 value &= temp;
252 }
253 return value;
254 }
255
computeFeasibleBounds(ColumnVector & xc,double epsilon)256 void CompoundConstraint::computeFeasibleBounds(ColumnVector&xc, double epsilon)
257 {
258 /*
259 * Returns a point that is feasible with respect to the bound constraints
260 */
261
262 int i, j, nvars;
263 Constraint test;
264 ColumnVector type, lower, upper;
265
266 for(i = 0; i < numOfSets_; i++){
267 test = constraints_[i];
268 type = test.getConstraintType();
269
270 if(type(1) == Bound){
271 nvars = test.getNumOfVars();
272 lower = test.getLower();
273 upper = test.getUpper();
274
275 for(j = 1; j < nvars; j++){
276 if( xc(j) < lower(j) || xc(j) > upper(j)){
277 if(lower(j) > -BIG_BND && upper(j) == MAX_BND)
278 xc(j) = lower(j) + epsilon;
279 else if(upper(j) < BIG_BND && lower(j) == MIN_BND)
280 xc(j) = upper(j) + epsilon;
281 else
282 xc(j) = (lower(j) + upper(j))/2.0 + epsilon;
283 }
284 }
285 }
286 }
287 }
288
computeFeasibleInequalities(ColumnVector & xc,double ftol)289 void CompoundConstraint::computeFeasibleInequalities(ColumnVector&xc, double ftol)
290 {
291 /*
292 * Returns a point that is feasible with respect to general inequalities
293 */
294
295 int i, j, ncons;
296 double alpha = 0.5;
297 Constraint test;
298 Matrix grad_c;
299 ColumnVector g, gTg, type, v;
300
301 for(i = 0; i < numOfSets_; i++){
302 test = constraints_[i];
303 type = test.getConstraintType();
304
305 if(type(1) == Lineq || type(1) == NLineq){
306 if(!test.amIFeasible(xc,ftol)){
307 v = test.getConstraintViolation();
308 grad_c = test.evalGradient(xc);
309 if(type(1) == Lineq || type(1) == NLineq){
310 ncons = v.Nrows();
311 gTg.ReSize(ncons);
312 OptppArray<int> indices = test.getConstraintMappingIndices();
313 for(j = 1; j <ncons; j++ ){
314 if( abs(v(j)) > alpha ) {
315 g = grad_c.Column(indices[j-1]);
316 gTg(j) = Dot(g,g);
317 xc += (-v(j)/gTg(j))*g;
318 }
319 }
320 }
321 }
322 }
323 }
324 }
325
326
printConstraints()327 void CompoundConstraint::printConstraints()
328 {
329 /*
330 * Prints the raw value of the constraints.
331 */
332
333 int i, j, index, ncons, nvars;
334 Constraint test;
335 ColumnVector lower, upper, type, value;
336 OptppArray<int> mapping;
337 char s[2];
338
339 for(i = 0; i < numOfSets_; i++){
340 test = constraints_[i];
341 type = test.getConstraintType();
342
343 value = test.getConstraintValue();
344 lower = test.getLower();
345 upper = test.getUpper();
346
347 if(type(1) == Bound){
348 cout <<"\nBound Constraints: \n";
349 }
350 else if(type(1) == NLeqn || type(1) == NLineq)
351 cout <<"\nNonlinear Constraints: \n";
352 else if(type(1) == Leqn || type(1) == Lineq)
353 cout <<"\nLinear Constraints: \n";
354
355 if(type(1) != Bound){
356 ncons = test.getNumOfCons();
357 mapping = test.getConstraintMappingIndices();
358 cout << "Index Type Lower \t Constraint \t Upper \n";
359 for (j = 1; j<=ncons; j++) {
360 index = mapping[j-1];
361 if(type(index) == NLeqn || type(index) == Leqn) strcpy(s,"E");
362 if(type(index) == NLineq || type(index) == Lineq) strcpy(s,"I");
363 cout << d(index,5) << "\t" << s << "\t"
364 << e(lower(index),12,4) << "\t"
365 << e(value(index),12,4) << "\t"
366 << e(upper(index),12,4) << "\n";
367 }
368 }
369 else{
370 nvars = getNumOfVars();
371 cout << "Index \t Lower \t\t\t X \t Upper \n";
372 for (j = 1; j<=nvars; j++) {
373 cout << d(j,5) << "\t" << e(lower(j),12,4) << "\t"
374 << e(value(j),12,4) << "\t" << e(upper(j),12,4)
375 << "\n";
376 }
377 }
378 }
379 }
380
evalCFGH(const ColumnVector & xc)381 void CompoundConstraint::evalCFGH(const ColumnVector & xc) const
382 {
383 Constraint test;
384 ColumnVector result(numOfSets_);
385
386 for(int i = 0; i < numOfSets_; i++){
387 test = constraints_[i];
388 test.evalCFGH(xc);
389 }
390 }
391
392 // Evaluation
evalResidual(const ColumnVector & xc)393 ColumnVector CompoundConstraint::evalResidual(const ColumnVector& xc ) const
394 {
395 Constraint test;
396 ColumnVector result(numOfSets_);
397
398 for(int i = 0; i < numOfSets_; i++){
399 test = constraints_[i];
400 ColumnVector temp = test.evalResidual(xc);
401 if (i == 0)
402 result = temp;
403 else
404 result &= temp;
405 }
406 return result;
407 }
408
evalGradient(const ColumnVector & xc)409 Matrix CompoundConstraint::evalGradient(const ColumnVector& xc ) const
410 {
411 Matrix grad;
412 Constraint test;
413
414 for(int i = 0; i < numOfSets_; i++){
415 test = constraints_[i];
416 Matrix temp = test.evalGradient(xc);
417 if(i == 0)
418 grad = temp;
419 else
420 grad |= temp;
421 }
422 return grad;
423 }
424
evalHessian(ColumnVector & xc)425 SymmetricMatrix CompoundConstraint::evalHessian(ColumnVector& xc ) const
426 {
427 // Extremely adhoc. Conceived on 12/07/2000. Vertical Concatenation
428 SymmetricMatrix hessian(xc.Nrows());
429 hessian = 0;
430 return hessian;
431 }
432
evalHessian(ColumnVector & xc,int darg)433 OptppArray<SymmetricMatrix> CompoundConstraint::evalHessian(ColumnVector& xc, int darg ) const
434 {
435 // Extremely adhoc. Conceived on 12/07/2000. Vertical Concatenation
436 SymmetricMatrix hessianT(xc.Nrows());
437 hessianT = 0;
438 OptppArray<SymmetricMatrix> hessian(1);
439 hessian[0] = hessianT;
440 return hessian;
441 }
442
evalHessian(ColumnVector & xc,const ColumnVector & mult)443 SymmetricMatrix CompoundConstraint::evalHessian(ColumnVector& xc,
444 const ColumnVector& mult) const
445 {
446 int k, tncons;
447 SymmetricMatrix hessian(xc.Nrows());
448 OptppArray<SymmetricMatrix> temp;
449 ColumnVector type;
450 Constraint test;
451
452 k = 0;
453 hessian = 0.0;
454
455 for(int i = 0; i < numOfSets_; i++){
456 test = constraints_[i];
457 type = test.getConstraintType();
458 tncons = test.getNumOfCons();
459 k += tncons;
460
461 if(type(1) == NLeqn || type(1) == NLineq){
462 temp = test.evalHessian(xc, i);
463 for(int j = 0; j < temp.length(); j++){
464 hessian += mult(j+1)*temp[j];
465 }
466 }
467 }
468 return hessian;
469 }
470
amIFeasible(const ColumnVector & xc,double epsilon)471 bool CompoundConstraint::amIFeasible(const ColumnVector& xc, double epsilon ) const
472 {
473 bool feasible = true;
474 ColumnVector type;
475 Constraint test;
476
477 for(int i = 0; i < numOfSets_; i++){
478 test = constraints_[i];
479 type = test.getConstraintType();
480 if(type(1) == Bound)
481 feasible = test.amIFeasible(xc,epsilon);
482 if(!feasible){
483 // OptppmathError("The current iterate is infeasible wrt to the bound and
484 // linear constraints");
485 break;
486 }
487 }
488 return feasible;
489 }
490
insertSort(const OptppArray<Constraint> & constraints)491 void CompoundConstraint::insertSort(const OptppArray<Constraint>& constraints)
492 {
493 Constraint ctemp;
494 int dim = constraints.length();
495 OptppArray<Constraint> sorted(dim);
496 sorted = constraints;
497 int i;
498
499 if(dim == 1)
500 constraints_ = sorted;
501 else{
502 for(int j = 1; j < dim; j++){
503 ctemp = sorted[j];
504 i = j - 1;
505 while(i > -1 && compare(sorted[i],ctemp) > 0){
506 sorted[i+1] = sorted[i];
507 i--;
508 }
509 sorted[i+1] = ctemp;
510 }
511 constraints_ = sorted;
512 }
513 }
514
insertSort()515 void CompoundConstraint::insertSort()
516 {
517 Constraint ctemp;
518 int dim = constraints_.length();
519 int i;
520
521 if(dim > 1){
522 for(int j = 1; j < dim; j++){
523 ctemp = constraints_[j];
524 i = j - 1;
525 while(i > -1 && compare(constraints_[i],ctemp) > 0){
526 constraints_[i+1] = constraints_[i];
527 i--;
528 }
529 constraints_[i+1] = ctemp;
530 }
531 }
532 }
533
compare(const Constraint & c1,const Constraint & c2)534 int CompoundConstraint::compare(const Constraint& c1, const Constraint& c2)
535 {
536 ColumnVector ct1 = c1.getConstraintType();
537 ColumnVector ct2 = c2.getConstraintType();
538
539 if(ct1(1) < ct2(1))
540 return -1;
541 else if(ct1(1) > ct2(1))
542 return 1;
543 else
544 return 0;
545
546 }
547
548 } // namespace OPTT
549