Boost logo

Boost Users :

Subject: Re: [Boost-users] [review][constrained_value] Review of Constrained Value Library begins today
From: Jesse Perla (jesseperla_at_[hidden])
Date: 2008-12-03 12:16:55


As someone who was about to try to write something similar out of necessity,
let me throw out a few practical considerations and a use case. These are a
wish list from a library user that is not a generic library programmer:
What I really want is to have a "type" that contains bounds information,
rather than for bounds checking itself (which is gravy). And I want to use
this for pretty functional programming, and see this as an incredibly useful
library and integral to taking C++ to the next level for programming
mathematics. I do not see this as primarily an equivalence to units, though
I understand that use case. My primary cases for this are:

   1. For functors that contain domain/range sets to match the blackboard
   mathematics I am implementing in code. Including "operators" that map
   functors to functors (my main case being a derivative operator or a
   conditional expectation).
   2. To use this an optimizer framework. The problem is that you end up
   having to keep around lists of reasonable bounds on what values the
   optimizer should be allowed to use. But this information becomes separated
   from the real "type" of the variable, even though that is where it
   conceptually belongs. And when you call optimizers you need to have both.
   Of course, this optimizer/root finder problem is really the same issue as
   maintaining range/domain for functors.

So a few comments on what I would love to be able to do to support this:

   1. The closed/open bounds in here is necessary, especially for optimizers
   where you frequently have asymptotes at the bounds (virtually always in the
   dynamic programming for economics problems I work with).
   2. I would go further than saying that the closed/open bounds is a
   starting point and that the library should ultimately be designed to
   accomodate (runtime) unions of intervals and discrete points i.e. [x,x] in
   intervals. This would be very useful for game theory applications where you
   could get non-connected sets of equilibrium conditions. Or functions where
   you can have asymptotes in the middle that are not defined, but it is
   defined on both sides. Last, would be nice to allow for a discrete set of
   real values as bounds. If the design of the library could support this
   (maybe by returning an iterator over the ranges if necessary?) then it could
   be implemented later. Keep in mind that my need is to access/set the bounds
   at runtime rather than just boundschecking by writing my own bounds checking
   predicate.
   3. Turning off the bounds-checking at runtime could be useful (though
   certinaly not through NDEBUG!), but you would NEVER want to turn off the
   availability of the bounds information at runtime since that is the core
   usefulness of the library.
   4. If it is true in general, then this statement:
   http://student.agh.edu.pl/~kawulak/constrained_value/constrained_value/rationale.html#constrained_value.rationale.no_floats
   makes this library practically useless. I understand the rationale, but
   since all optimizers take floats or doubles, and 99% of functions map
   doubles to doubles for me, this is an unreasonable constraint. If the
   problem here is just for the bounds checking, then I am not worried since I
   really want type information.
   5. Sometimes you want to have compile-time fixed bounds , other times
   modifiable at runtime. So I like this, but they need to behave the same
   way. But what I really want to do is change the bounds of the type itself
   at runtime, not just the bounds on an individual instantiation. See the
   following to see if I am misundertanding the library:

typedef bounded<double> interest_rate;
interest_rate r1, r2;
change_bounds(r1, .8, .99);

Now the interest rate bounds on r2 don't exist, right? This is a big
problem for me... It would mean that the bounds information is not kept on
the type, but on the instantiation... this has extra data and has completely
different semantics from the static bounds case where it really is
associated with the type.
What I would really want is some kind of static data associated with the
type. I understand the difficulty here, but nevertheless this is the main
usefulness of the library. I also note that this means the "typedef"
approach may be a problem as it is set up since the library would have no
way to tell the difference between these types to store static bounds, even
though this is exactly what I want.:
typedef bounded<double> interest_rate;
typedef bounded<double> risk_aversion;
interest_rate r;
risk_aversion crra ;
change_bounds(r, .8. .99); //Storing this statically
change_bounds(crra, 1.0, 10.0); //Statically.
interest_rate r_guess; //Want the right bounds! Can't exist here?

Of course, with static bounds this kind of thing works. Perhaps it is
reasonable to throw in some sort of useless trick for the compiler to
separate when storing static data to keep semantics with the static bounds
the same? I don't know if this is a good approach, but it would be
reasonable to ask of library users:
typedef bounded<double, "INTEREST RATE"> interest_rate; //In fact, I
wouldn't even mind having the "name" available at runtime for
pretty_printing...
typedef bounded<double, "RISK_AVERSION"> risk_aversion;
interest_rate r;
risk_aversion crra ;
change_bounds(r, .8. .99); //Storing this statically, now the two types are
distinct?
change_bounds(crra, .5, 10); //Statically.
interest_rate r_guess; //Want the right bounds.

Naturally, there are other cases where you might want to change the bounds
on an instantiation. If both could be supported (and returned through the
same bounds function, modified through different ones) that would be nice,
but the above use case is far more important to me.

6) Is there any way to get the library to compile: std::max(2, i) instead of
using i.value() as mentioned in the tutorial for a constrained i? This
really is essential to make the library equivalent to normal operations, but
with extra type information. Again, I am willing to forgo ease of use on
the bounds checking for this... What I really want is the instantiation to
behave EXACTLY the same as an underlying type. So overloading the ++, +,
etc. are useful, but I would go further to say that perhaps everything could
be done by just going back to the underlying type... with abolutely no
overhead since it would make this useless for numeric programming. If I
multiply or add these kinds of values, I would want the result to be of the
underlying type and don't care about the mechanics of ensuring that the
result type is bounded itself, etc. I can construct my own bounded type for
the return type if I have to...

Thanks for listening. And if people have better ideas of a framework or
approach to do this kind of stuff, please tell me. I may be stretching the
expectations of this library...
-Jesse



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net