Generated on for Gecode by doxygen 1.17.0
pow-nroot.hpp
Go to the documentation of this file.
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Vincent Barichard <Vincent.Barichard@univ-angers.fr>
5 *
6 * Copyright:
7 * Vincent Barichard, 2012
8 *
9 * This file is part of Gecode, the generic constraint
10 * development environment:
11 * http://www.gecode.dev
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining
14 * a copy of this software and associated documentation files (the
15 * "Software"), to deal in the Software without restriction, including
16 * without limitation the rights to use, copy, modify, merge, publish,
17 * distribute, sublicense, and/or sell copies of the Software, and to
18 * permit persons to whom the Software is furnished to do so, subject to
19 * the following conditions:
20 *
21 * The above copyright notice and this permission notice shall be
22 * included in all copies or substantial portions of the Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 *
32 */
33
34namespace Gecode { namespace Float { namespace Arithmetic {
35
37 template<class View>
38 class NonZero : public UnaryPropagator<View,PC_FLOAT_BND> {
39 protected:
44
45 NonZero(Home home, View x)
47 public:
49 static ExecStatus post(Home home, View x) {
50 if ((x.max() < 0.0) || (x.min() > 0.0))
51 return ES_OK;
52 if ((x.min() == 0.0) && (x.max() == 0.0))
53 return ES_FAILED;
54 (void) new (home) NonZero<View>(home,x);
55 return ES_OK;
56 }
57
58 virtual Actor* copy(Space& home) {
59 return new (home) NonZero<View>(home,*this);
60 }
61
62 virtual ExecStatus propagate(Space& home, const ModEventDelta&) {
63 if ((x0.max() < 0.0) || (x0.min() > 0.0))
64 return home.ES_SUBSUMED(*this);
65 return ((x0.min() == 0.0) && (x0.max() == 0.0))
66 ? ES_FAILED : ES_FIX;
67 }
68 };
69
71 forceinline FloatNum
73 typedef gecode_boost::numeric::interval_lib::rounded_arith_std<FloatNum>
74 DirectRoundingBase;
75 typedef gecode_boost::numeric::interval_lib::save_state<DirectRoundingBase>
76 DirectRounding;
77 DirectRounding r;
78 FloatNum y = 1.0;
79 while (n > 0) {
80 if ((n & 1) != 0)
81 y = r.mul_down(y,x);
82 n >>= 1;
83 if (n > 0)
84 x = r.mul_down(x,x);
85 }
86 return y;
87 }
88
90 forceinline FloatVal
91 positive_nroot(const FloatVal& x, int n) {
92 if (((n % 2) == 0) && (x.min() == 0.0)) {
93 if (x.max() == 0.0)
94 return FloatVal(0.0,0.0);
95
96 // std::pow is not guaranteed to be correctly rounded. Use it only as
97 // a seed, and certify the upper bound with outward interval arithmetic.
98 FloatNum u = std::pow(x.max(), 1.0 / static_cast<FloatNum>(n));
99 if (!(u > 0.0))
100 u = std::nextafter(0.0,Limits::max);
101 else if (u > Limits::max)
102 u = Limits::max;
103
104 if (positive_pow_down(u,n) < x.max()) {
105 FloatNum l = u;
106 do {
107 u = (l <= Limits::max / 2.0) ? l * 2.0 : Limits::max;
108 if (u > Limits::max)
109 u = Limits::max;
110 else if (!(u > l))
111 u = std::nextafter(l,Limits::max);
112 if (u == l)
113 break;
114 if (positive_pow_down(u,n) < x.max())
115 l = u;
116 else
117 break;
118 } while (true);
119
120 // Find the least representable value between the failed lower bound
121 // and the certified upper bound. This keeps the result tight even if
122 // the initial approximation was many ulps too small.
123 while (std::nextafter(l,u) < u) {
124 FloatNum m = l + (u-l) / 2.0;
125 if (!(m > l) || !(m < u))
126 m = std::nextafter(l,u);
127 if (positive_pow_down(m,n) < x.max())
128 l = m;
129 else
130 u = m;
131 }
132 }
133 return FloatVal(0.0,u);
134 }
135 return nroot(x,n);
136 }
137
138
139 /*
140 * Bounds consistent square operator
141 *
142 */
143
144 template<class A, class B>
145 forceinline
146 Pow<A,B>::Pow(Home home, A x0, B x1, int n)
148
149 template<class A, class B>
151 Pow<A,B>::post(Home home, A x0, B x1, int n) {
152 if (n == 0) {
153 GECODE_ME_CHECK(x1.eq(home,1.0));
154 return NonZero<A>::post(home,x0);
155 }
156
157 GECODE_ME_CHECK(x1.eq(home,pow(x0.domain(),n)));
158 if ((x1.min() == 0.0) && (x1.max() == 0.0)) {
159 GECODE_ME_CHECK(x0.eq(home,0.0));
160 return ES_OK;
161 }
162
163 if ((n % 2) == 0) {
164 if (x1.min() < 0.0) return ES_FAILED;
165 FloatVal d((x1.min() <= 0.0) ? 0.0 : x1.min(), x1.max());
166 FloatVal r = positive_nroot(d,n);
167 if (x0.min() >= 0)
168 GECODE_ME_CHECK(x0.eq(home,r));
169 else if (x0.max() <= 0)
170 GECODE_ME_CHECK(x0.eq(home,-r));
171 else
172 GECODE_ME_CHECK(x0.eq(home,
173 hull(
174 r,
175 -r
176 )
177 ));
178 } else {
179 GECODE_ME_CHECK(x0.eq(home,nroot(x1.domain(),n)));
180 }
181
182 // Inverse propagation can tighten x0. Recompute the forward image before
183 // an assigned x0 causes the constraint to be discarded.
184 GECODE_ME_CHECK(x1.eq(home,pow(x0.domain(),n)));
185
186 if (!x0.assigned()) (void) new (home) Pow<A,B>(home,x0,x1,n);
187 return ES_OK;
188 }
189
190 template<class A, class B>
191 forceinline
194
195 template<class A, class B>
196 Actor*
198 return new (home) Pow<A,B>(home,*this);
199 }
200
201 template<class A, class B>
204 GECODE_ME_CHECK(x1.eq(home,pow(x0.domain(),m_n)));
205
206 if ((x1.min() == 0.0) && (x1.max() == 0.0)) {
207 GECODE_ME_CHECK(x0.eq(home,0.0));
208 return home.ES_SUBSUMED(*this);
209 }
210
211 if ((m_n % 2) == 0) {
212 if (x1.min() < 0.0) return ES_FAILED;
213 FloatVal d((x1.min() <= 0.0) ? 0.0 : x1.min(), x1.max());
215 if (x0.min() >= 0)
216 GECODE_ME_CHECK(x0.eq(home,r));
217 else if (x0.max() <= 0)
218 GECODE_ME_CHECK(x0.eq(home,-r));
219 else
220 GECODE_ME_CHECK(x0.eq(home,
221 hull(
222 r,
223 -r
224 )
225 ));
226 } else {
227 GECODE_ME_CHECK(x0.eq(home,nroot(x1.domain(),m_n)));
228 }
229 GECODE_ME_CHECK(x1.eq(home,pow(x0.domain(),m_n)));
230 return x0.assigned() ? home.ES_SUBSUMED(*this) : ES_NOFIX;
231 }
232
233 /*
234 * Bounds consistent square root operator
235 *
236 */
237
238 template<class A, class B>
239 forceinline
242
243 template<class A, class B>
245 NthRoot<A,B>::post(Home home, A x0, B x1, int n) {
246 if (n == 0) return ES_FAILED;
247 GECODE_ME_CHECK(x0.gq(home,0.0));
248 if (x0.min() < 0.0) return ES_FAILED;
249 FloatVal d((x0.min() <= 0.0) ? 0.0 : x0.min(), x0.max());
250 GECODE_ME_CHECK(x1.eq(home,positive_nroot(d,n)));
251 GECODE_ME_CHECK(x0.eq(home,pow(x1.domain(),n)));
252 (void) new (home) NthRoot<A,B>(home,x0,x1,n);
253 return ES_OK;
254 }
255
256 template<class A, class B>
257 forceinline
260
261 template<class A, class B>
262 Actor*
264 return new (home) NthRoot<A,B>(home,*this);
265 }
266
267 template<class A, class B>
270 if (x0.min() < 0.0) return ES_FAILED;
271 FloatVal d((x0.min() <= 0.0) ? 0.0 : x0.min(), x0.max());
273 GECODE_ME_CHECK(x0.eq(home,pow(x1.domain(),m_n)));
274 return x0.assigned() ? home.ES_SUBSUMED(*this) : ES_NOFIX;
275 }
276
277
278}}}
279
280// STATISTICS: float-prop
Base-class for both propagators and branchers.
Definition core.hpp:635
Float value type.
Definition float.hh:334
friend FloatVal max(const FloatVal &x, const FloatVal &y)
Definition val.hpp:403
friend FloatVal min(const FloatVal &x, const FloatVal &y)
Definition val.hpp:415
NonZero(Home home, View x)
Constructor for posting.
Definition pow-nroot.hpp:45
virtual ExecStatus propagate(Space &home, const ModEventDelta &)
Perform propagation.
Definition pow-nroot.hpp:62
NonZero(Space &home, NonZero< View > &p)
Constructor for cloning a p.
Definition pow-nroot.hpp:42
virtual Actor * copy(Space &home)
Copy propagator during cloning.
Definition pow-nroot.hpp:58
static ExecStatus post(Home home, View x)
Post a non-zero propagator.
Definition pow-nroot.hpp:49
NthRoot(Space &home, NthRoot &p)
Constructor for cloning p.
virtual ExecStatus propagate(Space &home, const ModEventDelta &med)
Perform propagation.
virtual Actor * copy(Space &home)
Create copy during cloning.
static ExecStatus post(Home home, A x0, B x1, int n)
Post propagator for .
static ExecStatus post(Home home, A x0, B x1, int n)
Post propagator for .
virtual ExecStatus propagate(Space &home, const ModEventDelta &med)
Perform propagation.
virtual Actor * copy(Space &home)
Create copy during cloning.
Pow(Space &home, Pow &p)
Constructor for cloning p.
Home class for posting propagators
Definition core.hpp:863
MixBinaryPropagator(Space &home, MixBinaryPropagator &p)
Definition pattern.hpp:597
friend class Space
Definition core.hpp:1075
UnaryPropagator(Space &home, UnaryPropagator &p)
ExecStatus ES_SUBSUMED(Propagator &p)
Propagator p is subsumed
Definition core.hpp:3672
int ModEventDelta
Modification event deltas.
Definition core.hpp:94
#define GECODE_ME_CHECK(me)
Check whether modification event me is failed, and forward failure.
Definition macros.hpp:52
double FloatNum
Floating point number base type.
Definition float.hh:106
Arithmetic propagators
FloatNum positive_pow_down(FloatNum x, int n)
Return a downward-rounded positive integer power.
Definition pow-nroot.hpp:72
FloatVal positive_nroot(const FloatVal &x, int n)
Return nth root for a non-negative interval.
Definition pow-nroot.hpp:91
const FloatNum max
Largest allowed float value.
Definition float.hh:844
Floating point numbers.
FloatVal hull(const FloatVal &x, const FloatVal &y)
Definition val.hpp:524
const Gecode::PropCond PC_FLOAT_BND
Propagate when minimum or maximum of a view changes.
Definition var-type.hpp:300
Gecode toplevel namespace
ExecStatus
Definition core.hpp:479
@ ES_OK
Execution is okay.
Definition core.hpp:483
@ ES_FIX
Propagation has computed fixpoint.
Definition core.hpp:484
@ ES_FAILED
Execution has resulted in failure.
Definition core.hpp:481
@ ES_NOFIX
Propagation has not computed fixpoint.
Definition core.hpp:482
void pow(Home home, FloatVar x0, int n, FloatVar x1)
Post propagator for for .
void nroot(Home home, FloatVar x0, int n, FloatVar x1)
Post propagator for for .