MC++
interval.hpp
1 // Copyright (C) 2009-2013 Benoit Chachuat, Imperial College London.
2 // All Rights Reserved.
3 
111 #ifndef MC__INTERVAL_HPP
112 #define MC__INTERVAL_HPP
113 
114 #include <iostream>
115 #include <iomanip>
116 #include <stdarg.h>
117 
118 #include "mcfunc.hpp"
119 
120 namespace mc
121 {
129 class Interval
131 {
132  // friends of class Interval for operator overloading
133  friend Interval operator+
134  ( const Interval& );
135  friend Interval operator+
136  ( const Interval&, const Interval& );
137  friend Interval operator+
138  ( const double, const Interval& );
139  friend Interval operator+
140  ( const Interval&, const double );
141  friend Interval operator-
142  ( const Interval& );
143  friend Interval operator-
144  ( const Interval&, const Interval& );
145  friend Interval operator-
146  ( const double, const Interval& );
147  friend Interval operator-
148  ( const Interval&, const double );
149  friend Interval operator*
150  ( const Interval&, const Interval& );
151  friend Interval operator*
152  ( const Interval&, const double );
153  friend Interval operator*
154  ( const double, const Interval& );
155  friend Interval operator/
156  ( const Interval&, const Interval& );
157  friend Interval operator/
158  ( const Interval&, const double );
159  friend Interval operator/
160  ( const double, const Interval& );
161  friend std::ostream& operator<<
162  ( std::ostream&, const Interval& );
163  friend bool operator==
164  ( const Interval&, const Interval& );
165  friend bool operator!=
166  ( const Interval&, const Interval& );
167  friend bool operator<=
168  ( const Interval&, const Interval& );
169  friend bool operator>=
170  ( const Interval&, const Interval& );
171  friend bool operator<
172  ( const Interval&, const Interval& );
173  friend bool operator>
174  ( const Interval&, const Interval& );
175 
176  // friends of class Interval for function overloading
177  friend double diam
178  ( const Interval& );
179  friend double abs
180  ( const Interval& );
181  friend double mid
182  ( const Interval& );
183  friend Interval inv
184  ( const Interval& );
185  friend Interval sqr
186  ( const Interval& );
187  friend Interval exp
188  ( const Interval& );
189  friend Interval log
190  ( const Interval& );
191  friend Interval cos
192  ( const Interval& );
193  friend Interval sin
194  ( const Interval& );
195  friend Interval tan
196  ( const Interval& );
197  friend Interval acos
198  ( const Interval& );
199  friend Interval asin
200  ( const Interval& );
201  friend Interval atan
202  ( const Interval& );
203  friend Interval fabs
204  ( const Interval& );
205  friend Interval sqrt
206  ( const Interval& );
207  friend Interval xlog
208  ( const Interval& );
209  friend Interval erf
210  ( const Interval& );
211  friend Interval erfc
212  ( const Interval& );
213  friend Interval fstep
214  ( const Interval& );
215  friend Interval bstep
216  ( const Interval& );
217  friend Interval arh
218  ( const Interval&, const double );
219  friend Interval pow
220  ( const Interval&, const int );
221  friend Interval pow
222  ( const Interval&, const double );
223  friend Interval pow
224  ( const Interval&, const Interval& );
225  friend Interval monomial
226  ( const unsigned int, const Interval*, const int* );
227  friend Interval hull
228  ( const Interval&, const Interval& );
229  friend Interval min
230  ( const Interval&, const Interval& );
231  friend Interval max
232  ( const Interval&, const Interval& );
233  friend Interval min
234  ( const unsigned int, const Interval* );
235  friend Interval max
236  ( const unsigned int, const Interval* );
237  friend bool inter
238  ( Interval&, const Interval&, const Interval& );
239 
240 public:
241 
242  // other operator overloadings (inline)
243  Interval& operator=
244  ( const double c )
245  {
246  _l = c;
247  _u = c;
248  return *this;
249  }
250  Interval& operator=
251  ( const Interval&I )
252  {
253  _l = I._l;
254  _u = I._u;
255  return *this;
256  }
257  Interval& operator+=
258  ( const double c )
259  {
260  _l += c;
261  _u += c;
262  return *this;
263  }
264  Interval& operator+=
265  ( const Interval&I )
266  {
267  _l += I._l;
268  _u += I._u;
269  return *this;
270  }
271  Interval& operator-=
272  ( const double c )
273  {
274  _l -= c;
275  _u -= c;
276  return *this;
277  }
278  Interval& operator-=
279  ( const Interval&I )
280  {
281  Interval I2( _l, _u );
282  _l = I2._l - I._u;
283  _u = I2._u - I._l;
284  return *this;
285  }
286  Interval& operator*=
287  ( const double c )
288  {
289  Interval I2( _l, _u );
290  *this = I2 * c;
291  return *this;
292 
293  double t = _l;
294  c>=0 ? _l*=c, _u*=c : _l=_u*c, _u=t*c;
295  return *this;
296  }
297  Interval& operator*=
298  ( const Interval&I )
299  {
300  Interval I2( _l, _u );
301  *this = I2 * I;
302  return *this;
303  }
304  Interval& operator/=
305  ( const double c )
306  {
307  Interval I2( _l, _u );
308  *this = I2 / c;
309  return *this;
310  }
311  Interval& operator/=
312  ( const Interval&I )
313  {
314  Interval I2( _l, _u );
315  *this = I2 / I;
316  return *this;
317  }
318 
322  static struct Options
324  {
327  DISPLAY_DIGITS(5)
328  {}
330  unsigned int DISPLAY_DIGITS;
331  } options;
332 
335  {
336  public:
338  enum TYPE{
339  DIV=1,
340  INV,
341  LOG,
346  };
348  Exceptions( TYPE ierr ) : _ierr( ierr ){}
350  int ierr(){ return _ierr; }
352  std::string what(){
353  switch( _ierr ){
354  case DIV:
355  return "mc::Interval\t Division by zero";
356  case INV:
357  return "mc::Interval\t Inverse with zero in range";
358  case LOG:
359  return "mc::Interval\t Log with negative values in range";
360  case SQRT:
361  return "mc::Interval\t Square-root with nonpositive values in range";
362  case ACOS:
363  return "mc::Interval\t Inverse cosine with values outside of [-1,1] range";
364  case ASIN:
365  return "mc::Interval\t Inverse sine with values outside of [-1,1] range";
366  case TAN:
367  return "mc::Interval\t Tangent with values pi/2+k*pi in range";
368  }
369  return "mc::Interval\t Undocumented error";
370  }
371 
372  private:
373  TYPE _ierr;
374  };
377  {}
379  Interval
380  ( const double c ):
381  _l(c), _u(c)
382  {}
384  Interval
385  ( const double l, const double u ):
386  _l(l<u?l:u), _u(l<u?u:l)
387  {}
389  Interval
390  ( const Interval&I ):
391  _l(I._l), _u(I._u)
392  {}
393 
396  {}
397 
399  const double& l() const
400  {
401  return _l;
402  }
404  const double& u() const
405  {
406  return _u;
407  }
408 
410  void l ( const double lb )
411  {
412  _l = lb;
413  }
415  void u ( const double ub )
416  {
417  _u = ub;
418  }
421 private:
422 
424  double _l;
426  double _u;
427 };
428 
430 
431 Interval::Options Interval::options;
432 
433 inline Interval
434 operator+
435 ( const Interval&I )
436 {
437  return I;
438 }
439 
440 inline Interval
441 operator-
442 ( const Interval&I )
443 {
444  Interval I2( -I._u, -I._l );
445  return I2;
446 }
447 
448 inline Interval
449 operator+
450 ( const double c, const Interval&I )
451 {
452  Interval I2( c + I._l, c + I._u );
453  return I2;
454 }
455 
456 inline Interval
457 operator+
458 ( const Interval&I, const double c )
459 {
460  Interval I2( c + I._l, c + I._u );
461  return I2;
462 }
463 
464 inline Interval
465 operator+
466 ( const Interval&I1, const Interval&I2 )
467 {
468  Interval I3( I1._l+I2._l, I1._u+I2._u );
469  return I3;
470 }
471 
472 inline Interval
473 operator-
474 ( const double c, const Interval&I )
475 {
476  Interval I2( c - I._u, c - I._l );
477  return I2;
478 }
479 
480 inline Interval
481 operator-
482 ( const Interval&I, const double c )
483 {
484  Interval I2( I._l-c, I._u-c );
485  return I2;
486 }
487 
488 inline Interval
489 operator-
490 ( const Interval&I1, const Interval&I2 )
491 {
492  Interval I3( I1._l-I2._u, I1._u-I2._l );
493  return I3;
494 }
495 
496 inline Interval
497 operator*
498 ( const double c, const Interval&I )
499 {
500  Interval I2( c>=0? c*I._l: c*I._u, c>=0? c*I._u: c*I._l );
501  return I2;
502 }
503 
504 inline Interval
505 operator*
506 ( const Interval&I, const double c )
507 {
508  Interval I2( c>=0? c*I._l: c*I._u, c>=0? c*I._u: c*I._l );
509  return I2;
510 }
511 
512 inline Interval
513 operator*
514 ( const Interval&I1, const Interval&I2 )
515 {
516  Interval I3( std::min(std::min(I1._l*I2._l,I1._l*I2._u),
517  std::min(I1._u*I2._l,I1._u*I2._u)),
518  std::max(std::max(I1._l*I2._l,I1._l*I2._u),
519  std::max(I1._u*I2._l,I1._u*I2._u)) );
520  return I3;
521 }
522 
523 inline Interval
524 operator/
525 ( const Interval &I, const double c )
526 {
527  if( isequal(c,0.) ) throw Interval::Exceptions( Interval::Exceptions::DIV );
528  return (1./c)*I;
529 }
530 
531 inline Interval
532 operator/
533 ( const double c, const Interval&I )
534 {
535  return c*inv(I);
536 }
537 
538 inline Interval
539 operator/
540 ( const Interval&I1, const Interval&I2 )
541 {
542  return I1*inv(I2);
543 }
544 
545 inline double
546 diam
547 ( const Interval &I )
548 {
549  return I._u-I._l;
550 }
551 
552 inline double
553 mid
554 ( const Interval &I )
555 {
556  return 0.5*(I._u+I._l);
557 }
558 
559 inline double
560 abs
561 ( const Interval &I )
562 {
563  return std::max(std::fabs(I._l),std::fabs(I._u));
564 }
565 
566 inline Interval
567 inv
568 ( const Interval &I )
569 {
570  if ( I._l <= 0. && I._u >= 0. ) throw Interval::Exceptions( Interval::Exceptions::INV );
571  Interval I2( 1./I._u, 1./I._l );
572  return I2;
573 }
574 
575 inline Interval
576 sqr
577 ( const Interval&I )
578 {
579  int imid = -1;
580  Interval I2( mc::sqr( mid(I._l,I._u,0.,imid) ),
581  std::max(mc::sqr(I._l),mc::sqr(I._u)) );
582  return I2;
583 }
584 
585 inline Interval
586 exp
587 ( const Interval &I )
588 {
589  Interval I2( std::exp(I._l), std::exp(I._u) );
590  return I2;
591 }
592 
593 inline Interval
594 arh
595 ( const Interval &I, const double a )
596 {
597  return exp(-a/I);
598 }
599 
600 inline Interval
601 log
602 ( const Interval &I )
603 {
604  if ( I._l <= 0. ) throw Interval::Exceptions( Interval::Exceptions::LOG );
605  Interval I2( std::log(I._l), std::log(I._u) );
606  return I2;
607 }
608 
609 inline Interval
610 xlog
611 ( const Interval&I )
612 {
613  if ( I._l <= 0. ) throw Interval::Exceptions( Interval::Exceptions::LOG );
614  int imid = -1;
615  Interval I2( xlog(mid(I._l,I._u,std::exp(-1.),imid)),
616  std::max(xlog(I._l),xlog(I._u)) );
617  return I2;
618 }
619 
620 inline Interval
621 erf
622 ( const Interval &I )
623 {
624  Interval I2( ::erf(I._l), ::erf(I._u) );
625  return I2;
626 }
627 
628 inline Interval
629 erfc
630 ( const Interval &I )
631 {
632  Interval I2( ::erfc(I._u), ::erfc(I._l) );
633  return I2;
634 }
635 
636 inline Interval
637 sqrt
638 ( const Interval&I )
639 {
640  if ( I._l < 0. ) throw Interval::Exceptions( Interval::Exceptions::SQRT );
641  Interval I2( std::sqrt(I._l), std::sqrt(I._u) );
642  return I2;
643 }
644 
645 inline Interval
646 fabs
647 ( const Interval&I )
648 {
649  int imid = -1;
650  Interval I2( std::fabs(mid(I._l,I._u,0.,imid)),
651  std::max(std::fabs(I._l),std::fabs(I._u)) );
652  return I2;
653 }
654 
655 inline Interval
656 pow
657 ( const Interval&I, const int n )
658 {
659  if( n == 0 ){
660  return 1.;
661  }
662  if( n == 1 ){
663  return I;
664  }
665  if( n >= 2 && n%2 == 0 ){
666  int imid = -1;
667  Interval I2( std::pow(mid(I._l,I._u,0.,imid),n),
668  std::max(std::pow(I._l,n),std::pow(I._u,n)) );
669  return I2;
670  }
671  if ( n >= 3 ){
672  Interval I2( std::pow(I._l,n), std::pow(I._u,n) );
673  return I2;
674  }
675  return inv( pow( I, -n ) );
676 }
677 
678 inline Interval
679 monomial
680 (const unsigned int n, const Interval*I, const int*k)
681 {
682  if( n == 0 ){
683  return 1.;
684  }
685  if( n == 1 ){
686  return pow( I[0], k[0] );
687  }
688  return pow( I[0], k[0] ) * monomial( n-1, I+1, k+1 );
689 }
690 
691 inline Interval
692 pow
693 ( const Interval&I, const double a )
694 {
695  return exp( a * log( I ) );
696 }
697 
698 inline Interval
699 pow
700 ( const Interval&I1, const Interval&I2 )
701 {
702  return exp( I2 * log( I1 ) );
703 }
704 
705 inline Interval
706 hull
707 ( const Interval&I1, const Interval&I2 )
708 {
709  Interval I3( std::min( I1._l, I2._l ), std::max( I1._u, I2._u ) );
710  return I3;
711 }
712 
713 inline Interval
714 min
715 ( const Interval&I1, const Interval&I2 )
716 {
717  Interval I3( std::min( I1._l, I2._l ), std::min( I1._u, I2._u ) );
718  return I3;
719 }
720 
721 inline Interval
722 max
723 ( const Interval&I1, const Interval&I2 )
724 {
725  Interval I3( std::max( I1._l, I2._l ), std::max( I1._u, I2._u ) );
726  return I3;
727 }
728 
729 inline Interval
730 min
731 ( const unsigned int n, const Interval*I )
732 {
733  Interval I2( n==0 || !I ? 0.: I[0] );
734  for( unsigned int i=1; i<n; i++ ) I2 = min( I2, I[i] );
735  return I2;
736 }
737 
738 inline Interval
739 max
740 ( const unsigned int n, const Interval*I )
741 {
742  Interval I2( n==0 || !I ? 0.: I[0] );
743  for( unsigned int i=1; i<n; i++ ) I2 = max( I2, I[i] );
744  return I2;
745 }
746 
747 inline Interval
748 cos
749 ( const Interval&I )
750 {
751  const int k = std::ceil(-(1.+I._l/PI)/2.); // -pi <= xL+2*k*pi < pi
752  const double l = I._l+2.*PI*k, u = I._u+2.*PI*k;
753  if( l <= 0 ){
754  if( u <= 0 ){
755  Interval I2( std::cos(l), std::cos(u) );
756  return I2;
757  }
758  if( u >= PI ){
759  Interval I2( -1., 1. );
760  return I2;
761  }
762  Interval I2( std::min(std::cos(l), std::cos(u)), 1. );
763  return I2;
764  }
765  if( u <= PI ){
766  Interval I2( std::cos(u), std::cos(l) );
767  return I2;
768  }
769  if( u >= 2.*PI ){
770  Interval I2( -1., 1. );
771  return I2;
772  }
773  Interval I2( -1., std::max(std::cos(l), std::cos(u)));
774  return I2;
775 }
776 
777 inline Interval
778 sin
779 ( const Interval &I )
780 {
781  return cos( I - PI/2. );
782 }
783 
784 inline Interval
785 tan
786 ( const Interval&I )
787 {
788  const int k = std::ceil(-0.5-I._l/PI); // -pi/2 <= xL+k*pi < pi/2
789  const double l = I._l+PI*k, u = I._u+PI*k;
790  if( u >= 0.5*PI ) throw Interval::Exceptions( Interval::Exceptions::TAN );
791  Interval I2( std::tan(l), std::tan(u) );
792  return I2;
793 }
794 
795 inline Interval
796 acos
797 ( const Interval &I )
798 {
799  if ( I._l < -1. || I._u > 1. ) throw Interval::Exceptions( Interval::Exceptions::ACOS );
800  Interval I2( std::acos(I._u), std::acos(I._l) );
801  return I2;
802 }
803 
804 inline Interval
805 asin
806 ( const Interval &I )
807 {
808  if ( I._l < -1. || I._u > 1. ) throw Interval::Exceptions( Interval::Exceptions::ASIN );
809  Interval I2( std::asin(I._l), std::asin(I._u) );
810  return I2;
811 }
812 
813 inline Interval
814 atan
815 ( const Interval &I )
816 {
817  Interval I2( std::atan(I._l), std::atan(I._u) );
818  return I2;
819 }
820 
821 inline Interval
822 fstep
823 ( const Interval &I )
824 {
825  if( I._l >= 0 ) return Interval(1.);
826  else if( I._u < 0 ) return Interval(0.);
827  return Interval(0.,1.);
828 }
829 
830 inline Interval
831 bstep
832 ( const Interval &I )
833 {
834  return fstep( -I );
835 }
836 
837 inline std::ostream&
838 operator<<
839 ( std::ostream&out, const Interval&I)
840 {
841  out << std::right << std::scientific << std::setprecision(Interval::options.DISPLAY_DIGITS);
842  out << "[ " << std::setw(Interval::options.DISPLAY_DIGITS+7) << I.l()
843  << " : " << std::setw(Interval::options.DISPLAY_DIGITS+7) << I.u() << " ]";
844  return out;
845 }
846 
847 inline bool
848 inter
849 ( Interval &XIY, const Interval &X, const Interval &Y )
850 {
851  if( X._l > Y._u || Y._l > X._u ) return false;
852  XIY._l = std::max( X._l, Y._l );
853  XIY._u = std::min( X._u, Y._u );
854  return true;
855 }
856 
857 inline bool
858 operator==
859 ( const Interval&I1, const Interval&I2 )
860 {
861  return( I1._l == I2._l && I1._u == I2._u );
862 }
863 
864 inline bool
865 operator!=
866 ( const Interval&I1, const Interval&I2 )
867 {
868  return( I1._l != I2._l || I1._u != I2._u );
869 }
870 
871 inline bool
872 operator<=
873 ( const Interval&I1, const Interval&I2 )
874 {
875  return( I1._l >= I2._l && I1._u <= I2._u );
876 }
877 
878 inline bool
879 operator>=
880 ( const Interval&I1, const Interval&I2 )
881 {
882  return( I1._l <= I2._l && I1._u >= I2._u );
883 }
884 
885 inline bool
886 operator<
887 ( const Interval&I1, const Interval&I2 )
888 {
889  return( I1._l > I2._l && I1._u < I2._u );
890 }
891 
892 inline bool
893 operator>
894 ( const Interval&I1, const Interval&I2 )
895 {
896  return( I1._l < I2._l && I1._u > I2._u );
897 }
898 
899 } // namespace mc
900 
901 #include "mcop.hpp"
902 
903 namespace mc
904 {
905 
907 template <> struct Op<mc::Interval>
908 {
909  typedef mc::Interval T;
910  static T point( const double c ) { return T(c); }
911  static T zeroone() { return T(0.,1.); }
912  static void I(T& x, const T&y) { x = y; }
913  static double l(const T& x) { return x.l(); }
914  static double u(const T& x) { return x.u(); }
915  static double abs (const T& x) { return mc::abs(x); }
916  static double mid (const T& x) { return mc::mid(x); }
917  static double diam(const T& x) { return mc::diam(x); }
918  static T inv (const T& x) { return mc::inv(x); }
919  static T sqr (const T& x) { return mc::sqr(x); }
920  static T sqrt(const T& x) { return mc::sqrt(x); }
921  static T log (const T& x) { return mc::log(x); }
922  static T xlog(const T& x) { return mc::xlog(x); }
923  static T fabs(const T& x) { return mc::fabs(x); }
924  static T exp (const T& x) { return mc::exp(x); }
925  static T sin (const T& x) { return mc::sin(x); }
926  static T cos (const T& x) { return mc::cos(x); }
927  static T tan (const T& x) { return mc::tan(x); }
928  static T asin(const T& x) { return mc::asin(x); }
929  static T acos(const T& x) { return mc::acos(x); }
930  static T atan(const T& x) { return mc::atan(x); }
931  static T erf (const T& x) { return mc::erf(x); }
932  static T erfc(const T& x) { return mc::erfc(x); }
933  static T fstep(const T& x) { return mc::fstep(x); }
934  static T bstep(const T& x) { return mc::bstep(x); }
935  static T hull(const T& x, const T& y) { return mc::hull(x,y); }
936  static T min (const T& x, const T& y) { return mc::min(x,y); }
937  static T max (const T& x, const T& y) { return mc::max(x,y); }
938  static T arh (const T& x, const double k) { return mc::arh(x,k); }
939  template <typename X, typename Y> static T pow(const X& x, const Y& y) { return mc::pow(x,y); }
940  static T monomial (const unsigned int n, const T* x, const int* k) { return mc::monomial(n,x,k); }
941  static bool inter(T& xIy, const T& x, const T& y) { return mc::inter(xIy,x,y); }
942  static bool eq(const T& x, const T& y) { return x==y; }
943  static bool ne(const T& x, const T& y) { return x!=y; }
944  static bool lt(const T& x, const T& y) { return x<y; }
945  static bool le(const T& x, const T& y) { return x<=y; }
946  static bool gt(const T& x, const T& y) { return x>y; }
947  static bool ge(const T& x, const T& y) { return x>=y; }
948 };
949 
950 } // namespace mc
951 
952 #endif
int ierr()
Return error flag.
Definition: interval.hpp:350
void u(const double ub)
Set upper bound to ub
Definition: interval.hpp:415
std::string what()
Return error description.
Definition: interval.hpp:352
const double & u() const
Return upper bound.
Definition: interval.hpp:404
Log with negative values in range.
Definition: interval.hpp:341
Inverse cosine with values outside of [-1,1] range.
Definition: interval.hpp:343
~Interval()
Destructor.
Definition: interval.hpp:395
unsigned int DISPLAY_DIGITS
Number of digits displayed with << operator (default=5)
Definition: interval.hpp:330
Square-root with nonpositive values in range.
Definition: interval.hpp:342
Options()
Constructor.
Definition: interval.hpp:326
Interval()
Default constructor (needed for arrays of mc::Interval elements)
Definition: interval.hpp:376
Inverse with zero in range.
Definition: interval.hpp:340
TYPE
Enumeration type for mc::Interval exceptions.
Definition: interval.hpp:338
Exceptions of mc::Interval.
Definition: interval.hpp:334
void l(const double lb)
Set lower bound to lb
Definition: interval.hpp:410
Exceptions(TYPE ierr)
Constructor for error flag ierr
Definition: interval.hpp:348
Inverse sine with values outside of [-1,1] range.
Definition: interval.hpp:344
Tangent with values , with , in range.
Definition: interval.hpp:345
C++ class for (non-verified) interval bounding of factorable function.
Definition: interval.hpp:129
const double & l() const
Return lower bound.
Definition: interval.hpp:399
C++ structure to allow usage of various template parameters in the types mc::McCormick, mc::TModel, mc::TVar, and mc::SpecBnd of MC++ _ Specialization of this structure is required for the template parameters can be found in the header files defining the types mc::McCormick, mc::TModel, mc::TVar, and mc::SpecBnd.
Definition: mcop.hpp:13
Options of mc::Interval.
Definition: interval.hpp:323
Division by zero.
Definition: interval.hpp:339