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