ExecStatus ReLqFloat<View,CtrlView,rm>::post(Home home, View x, FloatVal c, CtrlView b) { if (b.one()) { if (rm != RM_PMI) GECODE_ME_CHECK(x.lq(home,c.max())); } if (b.zero()) { if (rm != RM_IMP) { GECODE_ME_CHECK(x.gq(home,c.min())); if (x.assigned() && (x.min() <= c.max())) return ES_FAILED; (void) new (home) ReLqFloat<View,CtrlView,rm>(home,x,c,b); } } else { switch (rtest_lq(x,c)) { case RT_TRUE: if (rm != RM_IMP) GECODE_ME_CHECK(b.one(home)); break; case RT_FALSE: if (rm != RM_PMI) GECODE_ME_CHECK(b.zero(home)); break; case RT_MAYBE: (void) new (home) ReLqFloat<View,CtrlView,rm>(home,x,c,b); break; default: GECODE_NEVER; } } return ES_OK; }
forceinline ModEvent FloatVarImp::gq(Space& home, const FloatVal& n) { if (n.min() <= dom.min()) return ME_FLOAT_NONE; if (n.min() > dom.max()) return ME_FLOAT_FAILED; FloatDelta d(dom.min(),n.max()); ModEvent me = ME_FLOAT_BND; dom = intersect(dom,FloatVal(n.max(),dom.max())); if (assigned()) me = ME_FLOAT_VAL; GECODE_ASSUME((me == ME_FLOAT_VAL) | (me == ME_FLOAT_BND)); return notify(home,me,d); }
void estimate(Term* t, int n, FloatVal c, FloatNum& l, FloatNum &u) { FloatVal est = c; for (int i=n; i--; ) est += t[i].a * t[i].x.domain(); FloatNum min = est.min(); FloatNum max = est.max(); if (min < Limits::min) min = Limits::min; if (min > Limits::max) min = Limits::max; l = min; if (max < Limits::min) max = Limits::min; if (max > Limits::max) max = Limits::max; u = max; }
ExecStatus aTanProject(const V& aTanIv, FloatVal& iv) { #define I0__PI_2I FloatVal(0,pi_half_upper()) #define IPI_2__PII FloatVal(pi_half_lower(),pi_upper()) #define POS(X) ((I0__PI_2I.in(X))?0:1) #define CASE(X,Y) case ((X << 2) | Y) : #define SHIFTN_UP(N,X) Round.add_up(Round.mul_up(N,pi_upper()),X) #define GROWING(I) Round.tan_down(iv.min()) <= Round.tan_up(iv.max()) #define ATANINF_DOWN Round.atan_down(aTanIv.min()) #define ATANSUP_UP Round.atan_up(aTanIv.max()) #define PI_UP pi_upper() #define PI_DOWN pi_lower() #define PI_TWICE_DOWN pi_twice_lower() int n = iv.max() / pi_lower(); // 0 <=> in [0;PI/2] // 1 <=> in [PI/2;PI] switch ( (POS(iv.min()) << 2) | POS(Round.sub_up(iv.max(),Round.mul_up(n,PI_UP))) ) { CASE(0,0) if (GROWING(iv)) iv.assign(ATANINF_DOWN,SHIFTN_UP(n,ATANSUP_UP)); else if (Round.tan_down(iv.min()) <= aTanIv.max()) if (Round.tan_up(iv.max()) >= aTanIv.min()) break; // Nothing changed else iv.assign(iv.min(),SHIFTN_UP(n-1, ATANSUP_UP)); else if (Round.tan_up(iv.max()) >= aTanIv.min()) iv.assign(Round.add_down(PI_DOWN, ATANINF_DOWN), iv.max()); else { if (n <= 1) return ES_FAILED; else iv.assign(Round.add_down(PI_DOWN, ATANINF_DOWN), SHIFTN_UP(n-1, ATANSUP_UP)); } break; CASE(0,1) if (Round.tan_down(iv.min()) <= aTanIv.max()) if (Round.tan_up(iv.max()) >= aTanIv.min()) break; // Nothing changed else iv.assign(iv.min(), SHIFTN_UP(n,ATANSUP_UP)); else if (Round.tan_up(iv.max()) >= aTanIv.min()) iv.assign(Round.add_down(PI_DOWN, ATANINF_DOWN), iv.max()); else { if (n <= 1) return ES_FAILED; else iv.assign(Round.add_down(PI_DOWN, ATANINF_DOWN), SHIFTN_UP(n,ATANSUP_UP)); } break; CASE(1,0) iv.assign(Round.add_down(PI_DOWN, ATANINF_DOWN), SHIFTN_UP(n,ATANSUP_UP)); break; CASE(1,1) if (GROWING(iv)) iv.assign(Round.add_down(PI_DOWN, ATANINF_DOWN), SHIFTN_UP(n+1,ATANSUP_UP)); else if (Round.tan_down(iv.min()) <= aTanIv.max()) if (Round.tan_up(iv.max()) >= aTanIv.min()) break; // Nothing changed else iv.assign(iv.min(), SHIFTN_UP(n,ATANSUP_UP)); else if (Round.tan_up(iv.max()) >= aTanIv.min()) iv.assign(Round.add_down(PI_TWICE_DOWN, ATANINF_DOWN), iv.max()); else { if (n <= 1) return ES_FAILED; iv.assign(Round.add_down(PI_TWICE_DOWN, ATANINF_DOWN), SHIFTN_UP(n,ATANSUP_UP)); } break; default: GECODE_NEVER; break; } return ES_OK; #undef PI_TWICE_DOWN #undef PI_UP #undef PI_DOWN #undef ATANINF_DOWN #undef ATANSUP_UP #undef GROWING #undef SHIFTN_UP #undef CASE #undef POS #undef I0__PI_2I #undef IPI_2__PII }
void dopost(Home home, Term* t, int n, FloatRelType frt, FloatVal c) { Limits::check(c,"Float::linear"); for (int i=n; i--; ) if (t[i].x.assigned()) { c -= t[i].a * t[i].x.val(); t[i]=t[--n]; } if ((c < Limits::min) || (c > Limits::max)) throw OutOfLimits("Float::linear"); /* * Join coefficients for aliased variables: * */ { // Group same variables TermLess tl; Support::quicksort<Term,TermLess>(t,n,tl); // Join adjacent variables int i = 0; int j = 0; while (i < n) { Limits::check(t[i].a,"Float::linear"); FloatVal a = t[i].a; FloatView x = t[i].x; while ((++i < n) && same(t[i].x,x)) { a += t[i].a; Limits::check(a,"Float::linear"); } if (a != 0.0) { t[j].a = a; t[j].x = x; j++; } } n = j; } Term *t_p, *t_n; int n_p, n_n; /* * Partition into positive/negative coefficents * */ if (n > 0) { int i = 0; int j = n-1; while (true) { while ((t[j].a < 0) && (--j >= 0)) ; while ((t[i].a > 0) && (++i < n)) ; if (j <= i) break; std::swap(t[i],t[j]); } t_p = t; n_p = i; t_n = t+n_p; n_n = n-n_p; } else { t_p = t; n_p = 0; t_n = t; n_n = 0; } /* * Make all coefficients positive * */ for (int i=n_n; i--; ) t_n[i].a = -t_n[i].a; if (frt == FRT_GQ) { frt = FRT_LQ; std::swap(n_p,n_n); std::swap(t_p,t_n); c = -c; } if (n == 0) { switch (frt) { case FRT_EQ: if (!c.in(0.0)) home.fail(); break; case FRT_LQ: if (c.max() < 0.0) home.fail(); break; default: GECODE_NEVER; } return; } /* * Test for unit coefficients only * */ bool is_unit = true; for (int i=n; i--; ) if (t[i].a != 1.0) { is_unit = false; break; } if (is_unit) { // Unit coefficients ViewArray<FloatView> x(home,n_p); for (int i = n_p; i--; ) x[i] = t_p[i].x; ViewArray<FloatView> y(home,n_n); for (int i = n_n; i--; ) y[i] = t_n[i].x; post_nary<FloatView>(home,x,y,frt,c); } else { // Arbitrary coefficients ViewArray<ScaleView> x(home,n_p); for (int i = n_p; i--; ) x[i] = ScaleView(t_p[i].a,t_p[i].x); ViewArray<ScaleView> y(home,n_n); for (int i = n_n; i--; ) y[i] = ScaleView(t_n[i].a,t_n[i].x); post_nary<ScaleView>(home,x,y,frt,c); } }
forceinline FloatNum ScaleView::size(void) const { FloatVal c = x.size(); c *= a; return c.max(); }
forceinline FloatNum ScaleView::med(void) const { FloatVal c = x.med(); c *= a; return (c.min()+c.max())/2; }
forceinline FloatNum ScaleView::max(const Delta& d) const { FloatVal c = x.max(d); c *= a; return c.max(); }
forceinline ModEvent ScaleView::lq(Space& home, FloatVal n) { FloatVal c = n; c /= a; return x.lq(home,c.max()); }