Generated on Thu Apr 11 13:59:17 2019 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               (aInt >= 0))
00204             y = result(home,ret,x);
00205           else {
00206             y = result(home,ret);
00207             pow(home, x, aInt, y);
00208           }
00209         }
00210         break;
00211       case ANLFE_NROOT:
00212         {
00213           assert(n == 1);
00214           FloatVar x = a[0].post(home);
00215           if (x.assigned() && ((x.val() == 0.0) || (x.val() == 1.0)) &&
00216               (aInt >= 0))
00217             y = result(home,ret,x);
00218           else {
00219             y = result(home,ret);
00220             nroot(home, x, aInt, y);
00221           }
00222         }
00223         break;
00224 #ifdef GECODE_HAS_MPFR
00225       case ANLFE_EXP:
00226         {
00227           assert(n == 1);
00228           FloatVar x = a[0].post(home);
00229           if (x.assigned() && (x.val() == 0.0)) {
00230             FloatVar one(home,1.0,1.0);
00231             y = result(home,ret,one);
00232           } else {
00233             y = result(home,ret);
00234             exp(home, x, y);
00235           }
00236         }
00237         break;
00238       case ANLFE_LOG:
00239         {
00240           assert(n == 1);
00241           FloatVar x = a[0].post(home);
00242           y = result(home,ret);
00243           log(home, x, y);
00244         }
00245         break;
00246       case ANLFE_ASIN:
00247         {
00248           assert(n == 1);
00249           FloatVar x = a[0].post(home);
00250           y = result(home,ret);
00251           asin(home, x, y);
00252         }
00253         break;
00254       case ANLFE_SIN:
00255         {
00256           assert(n == 1);
00257           FloatVar x = a[0].post(home);
00258           y = result(home,ret);
00259           sin(home, x, y);
00260         }
00261         break;
00262       case ANLFE_ACOS:
00263         {
00264           assert(n == 1);
00265           FloatVar x = a[0].post(home);
00266           y = result(home,ret);
00267           acos(home, x, y);
00268         }
00269         break;
00270       case ANLFE_COS:
00271         {
00272           assert(n == 1);
00273           FloatVar x = a[0].post(home);
00274           y = result(home,ret);
00275           cos(home, x, y);
00276         }
00277         break;
00278       case ANLFE_ATAN:
00279         {
00280           assert(n == 1);
00281           FloatVar x = a[0].post(home);
00282           y = result(home,ret);
00283           atan(home, x, y);
00284         }
00285         break;
00286       case ANLFE_TAN:
00287         {
00288           assert(n == 1);
00289           FloatVar x = a[0].post(home);
00290           y = result(home,ret);
00291           tan(home, x, y);
00292           }
00293         break;
00294 #endif
00295       default:
00296         GECODE_NEVER;
00297       }
00298       return y;
00299     }
00300     virtual void post(Home home, FloatRelType frt, FloatVal c) const {
00301       if ((t == ANLFE_MIN && frt == FRT_GQ) ||
00302           (t == ANLFE_MAX && frt == FRT_LQ)) {
00303         FloatVarArgs x(n);
00304         for (int i=n; i--;)
00305           x[i] = a[i].post(home);
00306         rel(home, x, frt, c);
00307       } else {
00308         rel(home, post(home,nullptr), frt, c);
00309       }
00310     }
00311     virtual void post(Home home, FloatRelType frt, FloatVal c,
00312                       BoolVar b) const {
00313       rel(home, post(home,nullptr), frt, c, b);
00314     }
00315   };
00317   bool hasType(const LinFloatExpr& e, ArithNonLinFloatExpr::ArithNonLinFloatExprType t) {
00318     return e.nlfe() &&
00319       dynamic_cast<ArithNonLinFloatExpr*>(e.nlfe()) != nullptr &&
00320       dynamic_cast<ArithNonLinFloatExpr*>(e.nlfe())->t == t;
00321   }
00322 
00323 }}
00324 
00325 namespace Gecode {
00326 
00327   LinFloatExpr
00328   abs(const LinFloatExpr& e) {
00329     using namespace MiniModel;
00330     if (hasType(e, ArithNonLinFloatExpr::ANLFE_ABS))
00331       return e;
00332     ArithNonLinFloatExpr* ae =
00333       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_ABS,1);
00334     ae->a[0] = e;
00335     return LinFloatExpr(ae);
00336   }
00337 
00338   LinFloatExpr
00339   min(const LinFloatExpr& e0, const LinFloatExpr& e1) {
00340     using namespace MiniModel;
00341     int n = 0;
00342     if (hasType(e0, ArithNonLinFloatExpr::ANLFE_MIN))
00343       n += static_cast<ArithNonLinFloatExpr*>(e0.nlfe())->n;
00344     else
00345       n += 1;
00346     if (hasType(e1, ArithNonLinFloatExpr::ANLFE_MIN))
00347       n += static_cast<ArithNonLinFloatExpr*>(e1.nlfe())->n;
00348     else
00349       n += 1;
00350     ArithNonLinFloatExpr* ae =
00351       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MIN,n);
00352     int i=0;
00353     if (hasType(e0, ArithNonLinFloatExpr::ANLFE_MIN)) {
00354       ArithNonLinFloatExpr* e0e = static_cast<ArithNonLinFloatExpr*>(e0.nlfe());
00355       for (; i<e0e->n; i++)
00356         ae->a[i] = e0e->a[i];
00357     } else {
00358       ae->a[i++] = e0;
00359     }
00360     if (hasType(e1, ArithNonLinFloatExpr::ANLFE_MIN)) {
00361       ArithNonLinFloatExpr* e1e = static_cast<ArithNonLinFloatExpr*>(e1.nlfe());
00362       int curN = i;
00363       for (; i<curN+e1e->n; i++)
00364         ae->a[i] = e1e->a[i-curN];
00365     } else {
00366       ae->a[i++] = e1;
00367     }
00368     return LinFloatExpr(ae);
00369   }
00370 
00371   LinFloatExpr
00372   min(const FloatVarArgs& x) {
00373     using namespace MiniModel;
00374     ArithNonLinFloatExpr* ae =
00375       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MIN,x.size());
00376     for (int i=x.size(); i--;)
00377       ae->a[i] = x[i];
00378     return LinFloatExpr(ae);
00379   }
00380 
00381   LinFloatExpr
00382   max(const LinFloatExpr& e0, const LinFloatExpr& e1) {
00383     using namespace MiniModel;
00384     int n = 0;
00385     if (hasType(e0, ArithNonLinFloatExpr::ANLFE_MAX))
00386       n += static_cast<ArithNonLinFloatExpr*>(e0.nlfe())->n;
00387     else
00388       n += 1;
00389     if (hasType(e1, ArithNonLinFloatExpr::ANLFE_MAX))
00390       n += static_cast<ArithNonLinFloatExpr*>(e1.nlfe())->n;
00391     else
00392       n += 1;
00393     ArithNonLinFloatExpr* ae =
00394       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MAX,n);
00395     int i=0;
00396     if (hasType(e0, ArithNonLinFloatExpr::ANLFE_MAX)) {
00397       ArithNonLinFloatExpr* e0e = static_cast<ArithNonLinFloatExpr*>(e0.nlfe());
00398       for (; i<e0e->n; i++)
00399         ae->a[i] = e0e->a[i];
00400     } else {
00401       ae->a[i++] = e0;
00402     }
00403     if (hasType(e1, ArithNonLinFloatExpr::ANLFE_MAX)) {
00404       ArithNonLinFloatExpr* e1e = static_cast<ArithNonLinFloatExpr*>(e1.nlfe());
00405       int curN = i;
00406       for (; i<curN+e1e->n; i++)
00407         ae->a[i] = e1e->a[i-curN];
00408     } else {
00409       ae->a[i++] = e1;
00410     }
00411     return LinFloatExpr(ae);
00412   }
00413 
00414   LinFloatExpr
00415   max(const FloatVarArgs& x) {
00416     using namespace MiniModel;
00417     ArithNonLinFloatExpr* ae =
00418       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MAX,x.size());
00419     for (int i=x.size(); i--;)
00420       ae->a[i] = x[i];
00421     return LinFloatExpr(ae);
00422   }
00423 
00424   LinFloatExpr
00425   operator *(const FloatVar& e0, const FloatVar& e1) {
00426     using namespace MiniModel;
00427     ArithNonLinFloatExpr* ae =
00428       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MULT,2);
00429     ae->a[0] = e0;
00430     ae->a[1] = e1;
00431     return LinFloatExpr(ae);
00432   }
00433 
00434   LinFloatExpr
00435   operator *(const LinFloatExpr& e0, const FloatVar& e1) {
00436     using namespace MiniModel;
00437     ArithNonLinFloatExpr* ae =
00438       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MULT,2);
00439     ae->a[0] = e0;
00440     ae->a[1] = e1;
00441     return LinFloatExpr(ae);
00442   }
00443 
00444   LinFloatExpr
00445   operator *(const FloatVar& e0, const LinFloatExpr& e1) {
00446     using namespace MiniModel;
00447     ArithNonLinFloatExpr* ae =
00448       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MULT,2);
00449     ae->a[0] = e0;
00450     ae->a[1] = e1;
00451     return LinFloatExpr(ae);
00452   }
00453 
00454   LinFloatExpr
00455   operator *(const LinFloatExpr& e0, const LinFloatExpr& e1) {
00456     using namespace MiniModel;
00457     ArithNonLinFloatExpr* ae =
00458       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_MULT,2);
00459     ae->a[0] = e0;
00460     ae->a[1] = e1;
00461     return LinFloatExpr(ae);
00462   }
00463 
00464   LinFloatExpr
00465   operator /(const LinFloatExpr& e0, const LinFloatExpr& e1) {
00466     using namespace MiniModel;
00467     ArithNonLinFloatExpr* ae =
00468       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_DIV,2);
00469     ae->a[0] = e0;
00470     ae->a[1] = e1;
00471     return LinFloatExpr(ae);
00472   }
00473 
00474   LinFloatExpr
00475   sqr(const LinFloatExpr& e) {
00476     using namespace MiniModel;
00477     ArithNonLinFloatExpr* ae =
00478       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_SQR,1);
00479     ae->a[0] = e;
00480     return LinFloatExpr(ae);
00481   }
00482 
00483   LinFloatExpr
00484   sqrt(const LinFloatExpr& e) {
00485     using namespace MiniModel;
00486     ArithNonLinFloatExpr* ae =
00487       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_SQRT,1);
00488     ae->a[0] = e;
00489     return LinFloatExpr(ae);
00490   }
00491 
00492   LinFloatExpr
00493   pow(const LinFloatExpr& e, int exp) {
00494     using namespace MiniModel;
00495     ArithNonLinFloatExpr* ae =
00496       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_POW,1,exp);
00497     ae->a[0] = e;
00498     return LinFloatExpr(ae);
00499   }
00500 
00501   LinFloatExpr
00502   nroot(const LinFloatExpr& e, int exp) {
00503     using namespace MiniModel;
00504     ArithNonLinFloatExpr* ae =
00505       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_NROOT,1,exp);
00506     ae->a[0] = e;
00507     return LinFloatExpr(ae);
00508   }
00509 
00510 #ifdef GECODE_HAS_MPFR
00511 
00512   LinFloatExpr
00513   exp(const LinFloatExpr& e) {
00514     using namespace MiniModel;
00515     ArithNonLinFloatExpr* ae =
00516       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_EXP,1);
00517     ae->a[0] = e;
00518     return LinFloatExpr(ae);
00519   }
00520 
00521   LinFloatExpr
00522   log(const LinFloatExpr& e) {
00523     using namespace MiniModel;
00524     ArithNonLinFloatExpr* ae =
00525       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_LOG,1);
00526     ae->a[0] = e;
00527     return LinFloatExpr(ae);
00528   }
00529 
00530   LinFloatExpr
00531   asin(const LinFloatExpr& e) {
00532     using namespace MiniModel;
00533     ArithNonLinFloatExpr* ae =
00534       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_ASIN,1);
00535     ae->a[0] = e;
00536     return LinFloatExpr(ae);
00537   }
00538 
00539   LinFloatExpr
00540   sin(const LinFloatExpr& e) {
00541     using namespace MiniModel;
00542     ArithNonLinFloatExpr* ae =
00543       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_SIN,1);
00544     ae->a[0] = e;
00545     return LinFloatExpr(ae);
00546   }
00547 
00548   LinFloatExpr
00549   acos(const LinFloatExpr& e) {
00550     using namespace MiniModel;
00551     ArithNonLinFloatExpr* ae =
00552       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_ACOS,1);
00553     ae->a[0] = e;
00554     return LinFloatExpr(ae);
00555   }
00556 
00557   LinFloatExpr
00558   cos(const LinFloatExpr& e) {
00559     using namespace MiniModel;
00560     ArithNonLinFloatExpr* ae =
00561       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_COS,1);
00562     ae->a[0] = e;
00563     return LinFloatExpr(ae);
00564   }
00565 
00566   LinFloatExpr
00567   atan(const LinFloatExpr& e) {
00568     using namespace MiniModel;
00569     ArithNonLinFloatExpr* ae =
00570       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_ATAN,1);
00571     ae->a[0] = e;
00572     return LinFloatExpr(ae);
00573   }
00574 
00575   LinFloatExpr
00576   tan(const LinFloatExpr& e) {
00577     using namespace MiniModel;
00578     ArithNonLinFloatExpr* ae =
00579       new ArithNonLinFloatExpr(ArithNonLinFloatExpr::ANLFE_TAN,1);
00580     ae->a[0] = e;
00581     return LinFloatExpr(ae);
00582   }
00583 
00584 #endif
00585 
00586 }
00587 
00588 #endif
00589 
00590 // STATISTICS: minimodel-any