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