Generated on Tue May 22 09:40:11 2018 for Gecode by doxygen 1.6.3

float-arith.cpp

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Christian Schulte <schulte@gecode.org>
00005  *     Vincent Barichard <Vincent.Barichard@univ-angers.fr>
00006  *
00007  *  Copyright:
00008  *     Christian Schulte, 2006
00009  *     Vincent Barichard, 2012
00010  *
00011  *  This file is part of Gecode, the generic constraint
00012  *  development environment:
00013  *     http://www.gecode.org
00014  *
00015  *  Permission is hereby granted, free of charge, to any person obtaining
00016  *  a copy of this software and associated documentation files (the
00017  *  "Software"), to deal in the Software without restriction, including
00018  *  without limitation the rights to use, copy, modify, merge, publish,
00019  *  distribute, sublicense, and/or sell copies of the Software, and to
00020  *  permit persons to whom the Software is furnished to do so, subject to
00021  *  the following conditions:
00022  *
00023  *  The above copyright notice and this permission notice shall be
00024  *  included in all copies or substantial portions of the Software.
00025  *
00026  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00027  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00028  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00029  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00030  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00031  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00032  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00033  *
00034  */
00035 
00036 #include <gecode/minimodel.hh>
00037 
00038 #ifdef GECODE_HAS_FLOAT_VARS
00039 
00040 namespace Gecode { namespace MiniModel {
00041 
00043   class GECODE_MINIMODEL_EXPORT ArithNonLinFloatExpr :
00044     public NonLinFloatExpr {
00045   public:
00047     enum ArithNonLinFloatExprType {
00048       ANLFE_ABS,   
00049       ANLFE_MIN,   
00050       ANLFE_MAX,   
00051       ANLFE_MULT,  
00052       ANLFE_DIV,   
00053       ANLFE_SQR,   
00054       ANLFE_SQRT,  
00055 #ifdef GECODE_HAS_MPFR
00056       ANLFE_EXP,   
00057       ANLFE_LOG,   
00058       ANLFE_ASIN,  
00059       ANLFE_SIN,   
00060       ANLFE_ACOS,  
00061       ANLFE_COS,   
00062       ANLFE_ATAN,  
00063       ANLFE_TAN,   
00064 #endif
00065       ANLFE_POW,   
00066       ANLFE_NROOT  
00067     } t;
00069     LinFloatExpr* a;
00071     int n;
00073     int aInt;
00075     ArithNonLinFloatExpr(ArithNonLinFloatExprType t0, int n0)
00076       : t(t0), a(heap.alloc<LinFloatExpr>(n0)), n(n0), aInt(-1) {}
00077     ArithNonLinFloatExpr(ArithNonLinFloatExprType t0, int n0, int a0)
00078       : t(t0), a(heap.alloc<LinFloatExpr>(n0)), n(n0), aInt(a0) {}
00080     ~ArithNonLinFloatExpr(void) { heap.free<LinFloatExpr>(a,n); }
00082     virtual FloatVar post(Home home, FloatVar* ret) const {
00083       FloatVar y;
00084       switch (t) {
00085       case ANLFE_ABS:
00086         {
00087           FloatVar x = a[0].post(home);
00088           if (x.min() >= 0)
00089             y = result(home,ret,x);
00090           else {
00091             y = result(home,ret);
00092             abs(home, x, y);
00093           }
00094         }
00095         break;
00096       case ANLFE_MIN:
00097         if (n==1) {
00098           y = result(home,ret, a[0].post(home));
00099         } else if (n==2) {
00100           FloatVar x0 = a[0].post(home);
00101           FloatVar x1 = a[1].post(home);
00102           if (x0.max() <= x1.min())
00103             y = result(home,ret,x0);
00104           else if (x1.max() <= x0.min())
00105             y = result(home,ret,x1);
00106           else {
00107             y = result(home,ret);
00108             min(home, x0, x1, y);
00109           }
00110         } else {
00111           FloatVarArgs x(n);
00112           for (int i=n; i--;)
00113             x[i] = a[i].post(home);
00114           y = result(home,ret);
00115           min(home, x, y);
00116         }
00117         break;
00118       case ANLFE_MAX:
00119         if (n==1) {
00120           y = result(home,ret,a[0].post(home));
00121         } else if (n==2) {
00122           FloatVar x0 = a[0].post(home);
00123           FloatVar x1 = a[1].post(home);
00124           if (x0.max() <= x1.min())
00125             y = result(home,ret,x1);
00126           else if (x1.max() <= x0.min())
00127             y = result(home,ret,x0);
00128           else {
00129             y = result(home,ret);
00130             max(home, x0, x1, y);
00131           }
00132         } else {
00133           FloatVarArgs x(n);
00134           for (int i=n; i--;)
00135             x[i] = a[i].post(home);
00136           y = result(home,ret);
00137           max(home, x, y);
00138         }
00139         break;
00140       case ANLFE_MULT:
00141         {
00142           assert(n == 2);
00143           FloatVar x0 = a[0].post(home);
00144           FloatVar x1 = a[1].post(home);
00145           if (x0.assigned() && (x0.val() == 0.0))
00146             y = result(home,ret,x0);
00147           else if (x0.assigned() && (x0.val() == 1.0))
00148             y = result(home,ret,x1);
00149           else if (x1.assigned() && (x1.val() == 0.0))
00150             y = result(home,ret,x1);
00151           else if (x1.assigned() && (x1.val() == 1.0))
00152             y = result(home,ret,x0);
00153           else {
00154             y = result(home,ret);
00155             mult(home, x0, x1, y);
00156           }
00157         }
00158         break;
00159       case ANLFE_DIV:
00160         {
00161           assert(n == 2);
00162           FloatVar x0 = a[0].post(home);
00163           FloatVar x1 = a[1].post(home);
00164           if (x1.assigned() && (x1.val() == 1.0))
00165             y = result(home,ret,x0);
00166           else if (x0.assigned() && (x0.val() == 0.0))
00167             y = result(home,ret,x0);
00168           else {
00169             y = result(home,ret);
00170             div(home, x0, x1, y);
00171           }
00172         }
00173         break;
00174       case ANLFE_SQR:
00175         {
00176           assert(n == 1);
00177           FloatVar x = a[0].post(home);
00178           if (x.assigned() && ((x.val() == 0.0) || (x.val() == 1.0)))
00179             y = x;
00180           else {
00181             y = result(home,ret);
00182             sqr(home, x, y);
00183           }
00184         }
00185         break;
00186       case ANLFE_SQRT:
00187         {
00188           assert(n == 1);
00189           FloatVar x = a[0].post(home);
00190           if (x.assigned() && ((x.val() == 0.0) || (x.val() == 1.0)))
00191             y = result(home,ret,x);
00192           else {
00193             y = result(home,ret);
00194             sqrt(home, x, y);
00195           }
00196         }
00197         break;
00198       case ANLFE_POW:
00199         {
00200           assert(n == 1);
00201           FloatVar x = a[0].post(home);
00202           if (x.assigned() && ((x.val() == 0.0) || (x.val() == 1.0)))
00203             y = result(home,ret,x);
00204           else {
00205             y = result(home,ret);
00206             pow(home, x, aInt, y);
00207           }
00208         }
00209         break;
00210       case ANLFE_NROOT:
00211         {
00212           assert(n == 1);
00213           FloatVar x = a[0].post(home);
00214           if (x.assigned() && ((x.val() == 0.0) || (x.val() == 1.0)))
00215             y = result(home,ret,x);
00216           else {
00217             y = result(home,ret);
00218             nroot(home, x, aInt, y);
00219           }
00220         }
00221         break;
00222 #ifdef GECODE_HAS_MPFR
00223       case ANLFE_EXP:
00224         {
00225           assert(n == 1);
00226           FloatVar x = a[0].post(home);
00227           if (x.assigned() && (x.val() == 0.0))
00228             y = result(home,ret,x);
00229           else {
00230             y = result(home,ret);
00231             exp(home, x, y);
00232           }
00233         }
00234         break;
00235       case ANLFE_LOG:
00236         {
00237           assert(n == 1);
00238           FloatVar x = a[0].post(home);
00239           y = result(home,ret);
00240           log(home, x, y);
00241         }
00242         break;
00243       case ANLFE_ASIN:
00244         {
00245           assert(n == 1);
00246           FloatVar x = a[0].post(home);
00247           y = result(home,ret);
00248           asin(home, x, y);
00249         }
00250         break;
00251       case ANLFE_SIN:
00252         {
00253           assert(n == 1);
00254           FloatVar x = a[0].post(home);
00255           y = result(home,ret);
00256           sin(home, x, y);
00257         }
00258         break;
00259       case ANLFE_ACOS:
00260         {
00261           assert(n == 1);
00262           FloatVar x = a[0].post(home);
00263           y = result(home,ret);
00264           acos(home, x, y);
00265         }
00266         break;
00267       case ANLFE_COS:
00268         {
00269           assert(n == 1);
00270           FloatVar x = a[0].post(home);
00271           y = result(home,ret);
00272           cos(home, x, y);
00273         }
00274         break;
00275       case ANLFE_ATAN:
00276         {
00277           assert(n == 1);
00278           FloatVar x = a[0].post(home);
00279           y = result(home,ret);
00280           atan(home, x, y);
00281         }
00282         break;
00283       case ANLFE_TAN:
00284         {
00285           assert(n == 1);
00286           FloatVar x = a[0].post(home);
00287           y = result(home,ret);
00288           tan(home, x, y);
00289           }
00290         break;
00291 #endif
00292       default:
00293         GECODE_NEVER;
00294       }
00295       return y;
00296     }
00297     virtual void post(Home home, FloatRelType frt, FloatVal c) const {
00298       if ((t == ANLFE_MIN && frt == FRT_GQ) ||
00299           (t == ANLFE_MAX && frt == FRT_LQ)) {
00300         FloatVarArgs x(n);
00301         for (int i=n; i--;)
00302           x[i] = a[i].post(home);
00303         rel(home, x, frt, c);
00304       } else {
00305         rel(home, post(home,NULL), frt, c);
00306       }
00307     }
00308     virtual void post(Home home, FloatRelType frt, FloatVal c,
00309                       BoolVar b) const {
00310       rel(home, post(home,NULL), frt, c, b);
00311     }
00312   };
00314   bool hasType(const LinFloatExpr& e, ArithNonLinFloatExpr::ArithNonLinFloatExprType t) {
00315     return e.nlfe() &&
00316       dynamic_cast<ArithNonLinFloatExpr*>(e.nlfe()) != NULL &&
00317       dynamic_cast<ArithNonLinFloatExpr*>(e.nlfe())->t == t;
00318   }
00319 
00320 }}
00321 
00322 namespace Gecode {
00323 
00324   LinFloatExpr
00325   abs(const LinFloatExpr& e) {
00326     using namespace MiniModel;
00327     if (hasType(e, ArithNonLinFloatExpr::ANLFE_ABS))
00328       return e;
00329     ArithNonLinFloatExpr* ae =
00330       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_ABS,1);
00331     ae->a[0] = e;
00332     return LinFloatExpr(ae);
00333   }
00334 
00335   LinFloatExpr
00336   min(const LinFloatExpr& e0, const LinFloatExpr& e1) {
00337     using namespace MiniModel;
00338     int n = 0;
00339     if (hasType(e0, ArithNonLinFloatExpr::ANLFE_MIN))
00340       n += static_cast<ArithNonLinFloatExpr*>(e0.nlfe())->n;
00341     else
00342       n += 1;
00343     if (hasType(e1, ArithNonLinFloatExpr::ANLFE_MIN))
00344       n += static_cast<ArithNonLinFloatExpr*>(e1.nlfe())->n;
00345     else
00346       n += 1;
00347     ArithNonLinFloatExpr* ae =
00348       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MIN,n);
00349     int i=0;
00350     if (hasType(e0, ArithNonLinFloatExpr::ANLFE_MIN)) {
00351       ArithNonLinFloatExpr* e0e = static_cast<ArithNonLinFloatExpr*>(e0.nlfe());
00352       for (; i<e0e->n; i++)
00353         ae->a[i] = e0e->a[i];
00354     } else {
00355       ae->a[i++] = e0;
00356     }
00357     if (hasType(e1, ArithNonLinFloatExpr::ANLFE_MIN)) {
00358       ArithNonLinFloatExpr* e1e = static_cast<ArithNonLinFloatExpr*>(e1.nlfe());
00359       int curN = i;
00360       for (; i<curN+e1e->n; i++)
00361         ae->a[i] = e1e->a[i-curN];
00362     } else {
00363       ae->a[i++] = e1;
00364     }
00365     return LinFloatExpr(ae);
00366   }
00367 
00368   LinFloatExpr
00369   min(const FloatVarArgs& x) {
00370     using namespace MiniModel;
00371     ArithNonLinFloatExpr* ae =
00372       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MIN,x.size());
00373     for (int i=x.size(); i--;)
00374       ae->a[i] = x[i];
00375     return LinFloatExpr(ae);
00376   }
00377 
00378   LinFloatExpr
00379   max(const LinFloatExpr& e0, const LinFloatExpr& e1) {
00380     using namespace MiniModel;
00381     int n = 0;
00382     if (hasType(e0, ArithNonLinFloatExpr::ANLFE_MAX))
00383       n += static_cast<ArithNonLinFloatExpr*>(e0.nlfe())->n;
00384     else
00385       n += 1;
00386     if (hasType(e1, ArithNonLinFloatExpr::ANLFE_MAX))
00387       n += static_cast<ArithNonLinFloatExpr*>(e1.nlfe())->n;
00388     else
00389       n += 1;
00390     ArithNonLinFloatExpr* ae =
00391       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MAX,n);
00392     int i=0;
00393     if (hasType(e0, ArithNonLinFloatExpr::ANLFE_MAX)) {
00394       ArithNonLinFloatExpr* e0e = static_cast<ArithNonLinFloatExpr*>(e0.nlfe());
00395       for (; i<e0e->n; i++)
00396         ae->a[i] = e0e->a[i];
00397     } else {
00398       ae->a[i++] = e0;
00399     }
00400     if (hasType(e1, ArithNonLinFloatExpr::ANLFE_MAX)) {
00401       ArithNonLinFloatExpr* e1e = static_cast<ArithNonLinFloatExpr*>(e1.nlfe());
00402       int curN = i;
00403       for (; i<curN+e1e->n; i++)
00404         ae->a[i] = e1e->a[i-curN];
00405     } else {
00406       ae->a[i++] = e1;
00407     }
00408     return LinFloatExpr(ae);
00409   }
00410 
00411   LinFloatExpr
00412   max(const FloatVarArgs& x) {
00413     using namespace MiniModel;
00414     ArithNonLinFloatExpr* ae =
00415       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MAX,x.size());
00416     for (int i=x.size(); i--;)
00417       ae->a[i] = x[i];
00418     return LinFloatExpr(ae);
00419   }
00420 
00421   LinFloatExpr
00422   operator *(const FloatVar& e0, const FloatVar& e1) {
00423     using namespace MiniModel;
00424     ArithNonLinFloatExpr* ae =
00425       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MULT,2);
00426     ae->a[0] = e0;
00427     ae->a[1] = e1;
00428     return LinFloatExpr(ae);
00429   }
00430 
00431   LinFloatExpr
00432   operator *(const LinFloatExpr& e0, const FloatVar& e1) {
00433     using namespace MiniModel;
00434     ArithNonLinFloatExpr* ae =
00435       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MULT,2);
00436     ae->a[0] = e0;
00437     ae->a[1] = e1;
00438     return LinFloatExpr(ae);
00439   }
00440 
00441   LinFloatExpr
00442   operator *(const FloatVar& e0, const LinFloatExpr& e1) {
00443     using namespace MiniModel;
00444     ArithNonLinFloatExpr* ae =
00445       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MULT,2);
00446     ae->a[0] = e0;
00447     ae->a[1] = e1;
00448     return LinFloatExpr(ae);
00449   }
00450 
00451   LinFloatExpr
00452   operator *(const LinFloatExpr& e0, const LinFloatExpr& e1) {
00453     using namespace MiniModel;
00454     ArithNonLinFloatExpr* ae =
00455       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MULT,2);
00456     ae->a[0] = e0;
00457     ae->a[1] = e1;
00458     return LinFloatExpr(ae);
00459   }
00460 
00461   LinFloatExpr
00462   operator /(const LinFloatExpr& e0, const LinFloatExpr& e1) {
00463     using namespace MiniModel;
00464     ArithNonLinFloatExpr* ae =
00465       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_DIV,2);
00466     ae->a[0] = e0;
00467     ae->a[1] = e1;
00468     return LinFloatExpr(ae);
00469   }
00470 
00471   LinFloatExpr
00472   sqr(const LinFloatExpr& e) {
00473     using namespace MiniModel;
00474     ArithNonLinFloatExpr* ae =
00475       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_SQR,1);
00476     ae->a[0] = e;
00477     return LinFloatExpr(ae);
00478   }
00479 
00480   LinFloatExpr
00481   sqrt(const LinFloatExpr& e) {
00482     using namespace MiniModel;
00483     ArithNonLinFloatExpr* ae =
00484       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_SQRT,1);
00485     ae->a[0] = e;
00486     return LinFloatExpr(ae);
00487   }
00488 
00489   LinFloatExpr
00490   pow(const LinFloatExpr& e, int exp) {
00491     using namespace MiniModel;
00492     ArithNonLinFloatExpr* ae =
00493       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_POW,1,exp);
00494     ae->a[0] = e;
00495     return LinFloatExpr(ae);
00496   }
00497 
00498   LinFloatExpr
00499   nroot(const LinFloatExpr& e, int exp) {
00500     using namespace MiniModel;
00501     ArithNonLinFloatExpr* ae =
00502       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_NROOT,1,exp);
00503     ae->a[0] = e;
00504     return LinFloatExpr(ae);
00505   }
00506 
00507 #ifdef GECODE_HAS_MPFR
00508 
00509   LinFloatExpr
00510   exp(const LinFloatExpr& e) {
00511     using namespace MiniModel;
00512     ArithNonLinFloatExpr* ae =
00513       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_EXP,1);
00514     ae->a[0] = e;
00515     return LinFloatExpr(ae);
00516   }
00517 
00518   LinFloatExpr
00519   log(const LinFloatExpr& e) {
00520     using namespace MiniModel;
00521     ArithNonLinFloatExpr* ae =
00522       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_LOG,1);
00523     ae->a[0] = e;
00524     return LinFloatExpr(ae);
00525   }
00526 
00527   LinFloatExpr
00528   asin(const LinFloatExpr& e) {
00529     using namespace MiniModel;
00530     ArithNonLinFloatExpr* ae =
00531       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_ASIN,1);
00532     ae->a[0] = e;
00533     return LinFloatExpr(ae);
00534   }
00535 
00536   LinFloatExpr
00537   sin(const LinFloatExpr& e) {
00538     using namespace MiniModel;
00539     ArithNonLinFloatExpr* ae =
00540       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_SIN,1);
00541     ae->a[0] = e;
00542     return LinFloatExpr(ae);
00543   }
00544 
00545   LinFloatExpr
00546   acos(const LinFloatExpr& e) {
00547     using namespace MiniModel;
00548     ArithNonLinFloatExpr* ae =
00549       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_ACOS,1);
00550     ae->a[0] = e;
00551     return LinFloatExpr(ae);
00552   }
00553 
00554   LinFloatExpr
00555   cos(const LinFloatExpr& e) {
00556     using namespace MiniModel;
00557     ArithNonLinFloatExpr* ae =
00558       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_COS,1);
00559     ae->a[0] = e;
00560     return LinFloatExpr(ae);
00561   }
00562 
00563   LinFloatExpr
00564   atan(const LinFloatExpr& e) {
00565     using namespace MiniModel;
00566     ArithNonLinFloatExpr* ae =
00567       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_ATAN,1);
00568     ae->a[0] = e;
00569     return LinFloatExpr(ae);
00570   }
00571 
00572   LinFloatExpr
00573   tan(const LinFloatExpr& e) {
00574     using namespace MiniModel;
00575     ArithNonLinFloatExpr* ae =
00576       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_TAN,1);
00577     ae->a[0] = e;
00578     return LinFloatExpr(ae);
00579   }
00580 
00581 #endif
00582 
00583 }
00584 
00585 #endif
00586 
00587 // STATISTICS: minimodel-any