[fusion] named parameter technique with fusion::map
Hi, After I discovered Boost.Fusion I realize that I can define proper named functions with Boost.Fusion. Named in the sense of instrospection (not in the sense of default user parameters). It was something that is easy to achieve but it was very verbose. I simplified a little bit the syntax but at the end I got stuck just before achieving something useful with this ideas. I need a little help towards the end. using namespace boost::fusion; double H(double p, double q){ // original function for reference return p*p + q*q; } struct p{}; struct q{}; double H(map<pair<p, double>, pair<q, double> > const& args){ return H(at_key<p>(args), at_key<q>(args)); } int main(){ cout << H( map<pair<p, double>, pair<q, double> >( make_pair<p>(1.), make_pair<q>(2.) ) ); return 0; } One question: Why I can not interchange the order of p and q in the last call, after all it is a map at the library could in principle differentiate the pairs? making it possible to call an unordered named parameter. e.g. cout << H( map<pair<p, double>, pair<q, double> >( make_pair<q>(2.), // was p make_pair<p>(1.) // was q ) ); Is it possible to interchange the order to give more flexibility to the user? After a little playing I gladly found that the make_pair is not stricly necesary cout << H( map<pair<p, double>, pair<q, double> >(1.,2.) ); which is a nice improvement. It seems that still there is some redundancy, so I tried cout << H(make_map<p, q>(1.,2.)); and worked! On the side of the function definition I can have an alternative syntax which may be shorter but more difficult to interpret: double H(result_of::make_map<p, q, double, double>::type const& args) { ... } although it is not a great improvement. Second question: Does it occur to anyone how simplify things further? This is nice because *in principle* I can distinguish between the two parameters (strictly speaking is all one big parameter) at compile time via templates. Third question: I say in principle because I am stuck here. For example how can I implement a named parameter bind? It seems to me that I am close to achieving this but I don't know exactly how. What I want is some kind of "bind<H, q>(3.0)" which is a function object that effectively evaluates to H( pvalue, 3.0) or to H(make_map<p>(pvariable), 3.0) when calling bind<H, q>(3.0)(pvalue) or bind<H, q>(3.0)(make_map<p>(pvalue)). Note that the most general case is something that defines partial parameters by a map //if H had four parameters: auto b = my::bind<H, set<q1, q2> >( make_map<q1, q2>(3.0, 4.0) ) ; // or my::make_bind<H>( make_map<q1, q2>(3.0, 4.0) ) // and then use it as b(make_map<p1, p2>(5.0,6.0)); I think this seems to be promising although I need a little push to finish the technique I hope it is useful for someone (if I am not reinventing the wheel) and that we can round up the idea. or just wanted to know some opinions. Thank you, Alfredo (Note, named parameter boost library is not the proper way to go here because the of the level of instrospection I need in the functions, and because the use of named parameters is not to omit passing parameters but to recognize 'externally' certain parameters).
comments inline... alfC schrieb:
Hi,
After I discovered Boost.Fusion I realize that I can define proper named functions with Boost.Fusion. Named in the sense of instrospection (not in the sense of default user parameters). It was something that is easy to achieve but it was very verbose. I simplified a little bit the syntax but at the end I got stuck just before achieving something useful with this ideas. I need a little help towards the end.
using namespace boost::fusion; double H(double p, double q){ // original function for reference return p*p + q*q; } struct p{}; struct q{}; double H(map<pair<p, double>, pair<q, double> > const& args){ return H(at_key<p>(args), at_key<q>(args)); } int main(){ cout << H( map<pair<p, double>, pair<q, double> >( make_pair<p>(1.), make_pair<q>(2.) ) ); return 0; }
One question: Why I can not interchange the order of p and q in the last call, after all it is a map at the library could in principle differentiate the pairs? making it possible to call an unordered named parameter. e.g. cout << H( map<pair<p, double>, pair<q, double> >( make_pair<q>(2.), // was p make_pair<p>(1.) // was q ) ); Is it possible to interchange the order to give more flexibility to the user?
I don't think that this is a good idea. Reordering is a quite expensive operation and it would really slow down compile times. On top of that, fusion::map is a forward sequence which has a definite order (!) on its elements. Reordering does not feel natural here. Having that said, you can easily write your own, reordering associative sequence or you can construct your map from another another fusion sequence that you reorder on the fly, for example via fusion::nview .
After a little playing I gladly found that the make_pair is not stricly necesary cout << H( map<pair<p, double>, pair<q, double> >(1.,2.) ); which is a nice improvement. It seems that still there is some redundancy, so I tried
cout << H(make_map<p, q>(1.,2.));
and worked!
On the side of the function definition I can have an alternative syntax which may be shorter but more difficult to interpret:
double H(result_of::make_map<p, q, double, double>::type const& args) { ... } although it is not a great improvement.
Second question: Does it occur to anyone how simplify things further?
Check the attached main.cpp!
This is nice because *in principle* I can distinguish between the two parameters (strictly speaking is all one big parameter) at compile time via templates.
Third question: I say in principle because I am stuck here. For example how can I implement a named parameter bind? It seems to me that I am close to achieving this but I don't know exactly how. What I want is some kind of "bind<H, q>(3.0)" which is a function object that effectively evaluates to H( pvalue, 3.0) or to H(make_map<p>(pvariable), 3.0) when calling bind<H, q>(3.0)(pvalue) or bind<H, q>(3.0)(make_map<p>(pvalue)). Note that the most general case is something that defines partial parameters by a map //if H had four parameters: auto b = my::bind<H, set<q1, q2> >( make_map<q1, q2>(3.0, 4.0) ) ; // or my::make_bind<H>( make_map<q1, q2>(3.0, 4.0) ) // and then use it as b(make_map<p1, p2>(5.0,6.0));
I do not understand that. There is a bind example in libs/fusion/example/cookbook/do_the_bind.cpp . Proto might be more helpful here, though.
I think this seems to be promising although I need a little push to finish the technique I hope it is useful for someone (if I am not reinventing the wheel) and that we can round up the idea. or just wanted to know some opinions.
Thank you, Alfredo
(Note, named parameter boost library is not the proper way to go here because the of the level of instrospection I need in the functions, and because the use of named parameters is not to omit passing parameters but to recognize 'externally' certain parameters).
-Christopher
Third question: I say in principle because I am stuck here. For example how can I implement a named parameter bind? It seems to me that I am close to achieving this but I don't know exactly how. What I want is some kind of "bind<H, q>(3.0)" which is a function object that effectively evaluates to H( pvalue, 3.0) or to H(make_map<p>(pvariable), 3.0) when calling bind<H, q>(3.0)(pvalue) or bind<H, q>(3.0)(make_map<p>(pvalue)). Note that the most general case is something that defines partial parameters by a map //if H had four parameters: auto b = my::bind<H, set<q1, q2> >( make_map<q1, q2>(3.0, 4.0) ) ; // or my::make_bind<H>( make_map<q1, q2>(3.0, 4.0) ) // and then use it as b(make_map<p1, p2>(5.0,6.0));
I do not understand that. There is a bind example in libs/fusion/example/cookbook/do_the_bind.cpp . Proto might be more helpful here, though.
do_the_bind seem to be what I am looking for except that the bind is done by placeholder number instead of key (named parameter) in any case I couldn't go far because the do_the_bind.cpp doesn't compile for me (attached is the error message).
On 07/11/10 04:11, Alfredo Correa wrote:
I do not understand that. There is a bind example in libs/fusion/example/cookbook/do_the_bind.cpp . Proto might be more helpful here, though.
Speaking of proto, we did make the exercice on writing a Boost.Parameters look-alike using it. https://github.com/jfalcou/boosties/tree/master/options and one of the insight stuff was to not use fusion::map but let proto tree holds the values and make a transform able to extract them based on their ID.
On 11/06/10 08:26, Christopher Schmidt wrote:
comments inline...
alfC schrieb: [snip]
One question: Why I can not interchange the order of p and q in the last call, after all it is a map at the library could in principle differentiate the pairs? making it possible to call an unordered named parameter. e.g. cout << H( map<pair<p, double>, pair<q, double> >( make_pair<q>(2.), // was p make_pair<p>(1.) // was q ) ); Is it possible to interchange the order to give more flexibility to the user?
I don't think that this is a good idea. Reordering is a quite expensive operation and it would really slow down compile times. On top of that, fusion::map is a forward sequence which has a definite order (!) on its elements. Reordering does not feel natural here. Having that said, you can easily write your own, reordering associative sequence or you can construct your map from another another fusion sequence that you reorder on the fly, for example via fusion::nview .
The attached produces output: ------------------------- default values for tuple: ------------------------- at1=ti<1>(-1) at2=ti<2>(-1) at3=ti<3>(-1) ------------------------------- named/default values for tuple: ------------------------------- at1=ti<1>(1) at2=ti<2>(2) at3=ti<3>(-1) ================================ The args to pairs_nam_ti1_3_t CTOR could be the args to some map-like structure and then, inside that CTOR, a pairs_nam_ti1_3_t could be constructed and used to fill the map. It doesn't look too compile-time expensive, but I've done no measurements. HTH. -Larry
On 11/07/10 23:33, Larry Evans wrote: [snip]
The attached produces output:
[snip]
------------------------------- named/default values for tuple: ------------------------------- at1=ti<1>(1) at2=ti<2>(2) at3=ti<3>(-1) ================================
The args to pairs_nam_ti1_3_t CTOR could be the [snip] Unfortunately, reversing args to airs_nam_ti1_3_t CTOR, as in:
pairs_nam_ti1_3_t pairs_nam_ti1_3_v ( fusion::pair<mpl::int_<2>,ti<2> >(2) , fusion::pair<mpl::int_<1>,ti<1> >(1) ) causes compile error about "no matching function". Investigating. -Larry BTW, just read: http://www.boost.org/doc/libs/1_44_0/libs/fusion/doc/html /fusion/notes.html#fusion.notes.overloaded_functions which says: There is an overloaded function, f(k), for each key type k. The compiler chooses the appropriate function given a key, k. which is exactly the method used in named_component_ctor.cpp, where the overloaded function is arg.
On 11/08/10 06:55, Larry Evans wrote: [snip]
Unfortunately, reversing args to airs_nam_ti1_3_t CTOR, as in:
pairs_nam_ti1_3_t pairs_nam_ti1_3_v ( fusion::pair<mpl::int_<2>,ti<2> >(2) , fusion::pair<mpl::int_<1>,ti<1> >(1) )
causes compile error about "no matching function".
Investigating.
Problem solved By adding a templated member function, put, to pairs_named template. Also, renamed overloaded arg function to at_key, since that's more descriptive.
-Larry
BTW, just read:
http://www.boost.org/doc/libs/1_44_0/libs/fusion/doc/html /fusion/notes.html#fusion.notes.overloaded_functions
which says:
There is an overloaded function, f(k), for each key type k. The compiler chooses the appropriate function given a key, k.
which is exactly the method used in named_component_ctor.cpp, where the overloaded function is arg.
It's not obvious to me, after looking at: key_of_impl.hpp value_of_impl.hpp in boost/fusion/container/map/detail where this overloaded function, f, is located. (Of course I assume it's not named f, but something like value_of...). Could someone point it out? TIA. -Larry
On 11/08/10 08:25, Larry Evans wrote: [snip]
Problem solved By adding a templated member function, put, to pairs_named template.
Also, renamed overloaded arg function to at_key, since that's more descriptive.
The attached is a further simplification. Instead of 2 folds, only 1 is used and the resulting structure is really a map, map_default<P1,P2,...,Pn>, which allows the user to select which args to specify in the CTOR. One disadvantage is such a CTOR causes a default initialization of some values which are immediately overwritten by the call to put(value_pairs...) in the CTOR. Maybe another disadvantage is inheriting the values(instead of using fusion::vector) consumes more space. Haven't tested. -Larry
Larry Evans schrieb:
On 11/08/10 06:55, Larry Evans wrote: [snip] [snip]
BTW, just read:
http://www.boost.org/doc/libs/1_44_0/libs/fusion/doc/html /fusion/notes.html#fusion.notes.overloaded_functions
which says:
There is an overloaded function, f(k), for each key type k. The compiler chooses the appropriate function given a key, k.
which is exactly the method used in named_component_ctor.cpp, where the overloaded function is arg.
It's not obvious to me, after looking at:
key_of_impl.hpp value_of_impl.hpp
in boost/fusion/container/map/detail where this overloaded function, f, is located. (Of course I assume it's not named f, but something like value_of...). Could someone point it out?
Larry, thanks for your work! I am responsible for that change. The old implementation, that is the implementation up to revision 40392, did lookup values by key type via one single overloaded function: https://svn.boost.org/trac/boost/browser/trunk/boost/fusion/container/map/de... https://svn.boost.org/trac/boost/browser/trunk/boost/fusion/container/map/de... I ditched that when I merged associative iterators from my port back to the trunk. I did some benchmarking back then. IIRC, overloaded value lookup did worse than the unrolled value lookup. Here is the original post: http://article.gmane.org/gmane.comp.lib.boost.user/52510 Another benchmark: http://article.gmane.org/gmane.comp.lib.boost.devel/194407 I did not use gcc 4.5 and clang back then, though. I will try to get my benchmarks running again and try your implementation. Regarding the actual topic - reordering on construction has been requested before. Actually we already have a ticket that was opened 3 years ago: https://svn.boost.org/trac/boost/ticket/1404 I think implementing reordering in fusion::map and fusion::set is not a good idea. At any rate reordering per se does increase compile time and does not fit to the underlying concept of random access (sequence). On the other hand, reordering via fusion::nview is simple. I think it might be a good idea to get this documented, as an example maybe, or in a "useful bits&pieces"-section. Best regards, Christopher
On 11/08/10 13:30, Christopher Schmidt wrote:
Larry Evans schrieb:
On 11/08/10 06:55, Larry Evans wrote: [snip] [snip]
BTW, just read:
http://www.boost.org/doc/libs/1_44_0/libs/fusion/doc/html /fusion/notes.html#fusion.notes.overloaded_functions
which says:
There is an overloaded function, f(k), for each key type k. The compiler chooses the appropriate function given a key, k.
which is exactly the method used in named_component_ctor.cpp, where the overloaded function is arg.
It's not obvious to me, after looking at:
key_of_impl.hpp value_of_impl.hpp
in boost/fusion/container/map/detail where this overloaded function, f, is located. (Of course I assume it's not named f, but something like value_of...). Could someone point it out?
Larry,
thanks for your work!
Sure. It's interesting.
I am responsible for that change. The old implementation, that is the implementation up to revision 40392, did lookup values by key type via one single overloaded function:
https://svn.boost.org/trac/boost/browser/trunk/boost/fusion/container/map/de... https://svn.boost.org/trac/boost/browser/trunk/boost/fusion/container/map/de...
I ditched that when I merged associative iterators from my port back to the trunk. I did some benchmarking back then. IIRC, overloaded value lookup did worse than the unrolled value lookup. Here is the original post:
http://article.gmane.org/gmane.comp.lib.boost.user/52510
Another benchmark:
http://article.gmane.org/gmane.comp.lib.boost.devel/194407
I did not use gcc 4.5 and clang back then, though. I will try to get my benchmarks running again and try your implementation.
Regarding the actual topic - reordering on construction has been requested before. Actually we already have a ticket that was opened 3 years ago:
https://svn.boost.org/trac/boost/ticket/1404
I think implementing reordering in fusion::map and fusion::set is not a good idea. At any rate reordering per se does increase compile time and does not fit to the underlying concept of random access (sequence). On the other hand, reordering via fusion::nview is simple. I think it might be a good idea to get this documented, as an example maybe, or in a "useful bits&pieces"-section.
Thanks Christopher; however, I must be misunderstanding what Alfredo wanted. I just thought he wanted named parameters. I thought the example he gave:
One question: Why I can not interchange the order of p and q in the last call, after all it is a map at the library could in principle differentiate the pairs? making it possible to call an unordered named parameter. e.g. cout << H( map<pair<p, double>, pair<q, double> >( make_pair<q>(2.), // was p make_pair<p>(1.) // was q ) );
in his OP illustrated that, and I thought my last code example did just that: typedef map_default < mpl::pair<mpl::int_<1>,ti<1> > , mpl::pair<mpl::int_<2>,ti<2> > , mpl::pair<mpl::int_<3>,ti<3> > > map_def_ti1_3_t; ... map_def_ti1_3_t map_def_ti1_3_val2_1 ( fusion::pair<mpl::int_<2>,ti<2> >(2) , fusion::pair<mpl::int_<1>,ti<1> >(1) ); What am I missing? Thanks much for the explanation and history. That sort of detail sure makes it easier to understand why the code is the way it is. -regards, Larry
I think implementing reordering in fusion::map and fusion::set is not a good idea. At any rate reordering per se does increase compile time and does not fit to the underlying concept of random access (sequence). On the other hand, reordering via fusion::nview is simple. I think it might be a good idea to get this documented, as an example maybe, or in a "useful bits&pieces"-section.
Thanks Christopher; however, I must be misunderstanding what Alfredo wanted. I just thought he wanted named parameters. I thought the example he gave:
yes, I wanted named parameters but not just to call the function, but also to define functionals (I think in C++ called higher order function). The example of the derivative with respect to one parameter is an example of a funtional (because the derivative at a point is a funcion of the function). I just wanted to stress that the parameter name should be know not only by the used but also by other parts of the program. I think that request complicates things a little bit the things. Although after reading Dave message I might be wrong and it is just more of the same.
One question: Why I can not interchange the order of p and q in the last call, after all it is a map at the library could in principle differentiate the pairs? making it possible to call an unordered named parameter. e.g. cout << H( map<pair<p, double>, pair<q, double> >( make_pair<q>(2.), // was p make_pair<p>(1.) // was q ) );
in his OP illustrated that, and I thought my last code example did just that:
typedef map_default < mpl::pair<mpl::int_<1>,ti<1> > , mpl::pair<mpl::int_<2>,ti<2> > , mpl::pair<mpl::int_<3>,ti<3> > > map_def_ti1_3_t; ... map_def_ti1_3_t map_def_ti1_3_val2_1 ( fusion::pair<mpl::int_<2>,ti<2> >(2) , fusion::pair<mpl::int_<1>,ti<1> >(1) );
What am I missing?
Hi Larry, thank you for your work. I didn't understand the code with the "map_def_ti1_3_t;", etc code, but I think you achieved arbitrary named parameter ordering with it. But the free_at.hpp example is almost exactly what I was looking for, except that instead of using an integer for defining the "free" (only not bound) parameter I wanted to use a name (fusion map key). So I adapted your free_at.hpp to use fusion::map instead of fusion::vector but the code is very similar, I will post it here once it is finished. I think the map implementation is more general because potentially the map elements can be addressed by positional index also. Originally I was thinking in a very complicated way to do this by defining a bind function with all the non free parameters specified and then operator() with the free parameter. But given the application I am looking for, the free_at is not part of the interface but some internal temporary representation and since the value of the free parameter is actually used (to take the derivative at the end), your implementation is the perfect shortcut, small code easy to understand, it is genius. I guess I was too demanding at wanting all the notational flexibility all at once. I think it is still an interesting question. I just hope that in the future boost::fusion gets incorporated as part of the language in some way. After all Larry's example was all about converting variadic templates into fusion sequences. I think that what fusion does is so fundamental that it should be part of the language. That would be so cool. Thanks very much, Alfredo (PS: I hope the discussion continues, these things are very interesting. I think a language is ALL about notation, so what ever increases the expressiveness should be welcome).
On 11/08/10 13:30, Christopher Schmidt wrote:
Larry Evans schrieb:
On 11/08/10 06:55, Larry Evans wrote: [snip] [snip]
BTW, just read:
http://www.boost.org/doc/libs/1_44_0/libs/fusion/doc/html /fusion/notes.html#fusion.notes.overloaded_functions
which says:
There is an overloaded function, f(k), for each key type k. The compiler chooses the appropriate function given a key, k.
which is exactly the method used in named_component_ctor.cpp, where the overloaded function is arg.
It's not obvious to me, after looking at:
key_of_impl.hpp value_of_impl.hpp
in boost/fusion/container/map/detail where this overloaded function, f, is located. (Of course I assume it's not named f, but something like value_of...). Could someone point it out?
Larry,
thanks for your work!
I am responsible for that change. The old implementation, that is the implementation up to revision 40392, did lookup values by key type via one single overloaded function:
https://svn.boost.org/trac/boost/browser/trunk/boost/fusion/container/map/de... https://svn.boost.org/trac/boost/browser/trunk/boost/fusion/container/map/de...
I ditched that when I merged associative iterators from my port back to the trunk. I did some benchmarking back then. IIRC, overloaded value lookup did worse than the unrolled value lookup. Here is the original post:
[snip] The attached looks like a pretty simple map implementation and may be worth considering. Of course it only works with a variadic template compiler. -regards, Larry
On Sat, Nov 6, 2010 at 5:19 AM, alfC <alfredo.correa@gmail.com> wrote:
(Note, named parameter boost library is not the proper way to go here because the of the level of instrospection I need in the functions, and because the use of named parameters is not to omit passing parameters but to recognize 'externally' certain parameters).
I would be *very* surprised if there was some kind of introspection possible that Boost.Parameter didn't allow. And I don't understand what you mean about omitting passing parameters or external recognition. I think you're reinventing the wheel; a Boost.Parameter ArgumentPack is essentially a fusion map. -- Dave Abrahams BoostPro Computing http://www.boostpro.com
On Sat, Nov 6, 2010 at 2:19 PM, Dave Abrahams <dave@boostpro.com> wrote:
On Sat, Nov 6, 2010 at 5:19 AM, alfC <alfredo.correa@gmail.com> wrote:
(Note, named parameter boost library is not the proper way to go here because the of the level of instrospection I need in the functions, and because the use of named parameters is not to omit passing parameters but to recognize 'externally' certain parameters).
I would be *very* surprised if there was some kind of introspection possible that Boost.Parameter didn't allow. And I don't understand what you mean about omitting passing parameters or external recognition. I think you're reinventing the wheel; a Boost.Parameter ArgumentPack is essentially a fusion map.
ok, since I am probably missing the point, I am going to be one order of magnitude more specific in defining what I want to achieve. In the following example I will mix C++ and mathematical language to make the point clear. In "math", one can define a function of parameters and with some abuse of notation one can use the names of parameters to define functionals (e.g. derivatives), so for example H(p,q) = p*p + q; which can be evaluated, e.g. H(1.,2.) == 3. but one can also "invoke" the derivatives of H, dH/dq(1.,2.) == 4. To be consistent with the abuse of notation one can also say H(p=1., q=2.) or even H(q=2.,p=1), etc. It is this degree of notational flexibility what I would like to achieve. Let's switch to C++ double H(double p, double q){ return p*p+q; } if I call H(1.,2.) I get of course the desired result. I would also like to call something like d<H, q>(1.,2.) which is the numerical derivative of H with respect to q evaluated at p=1., q=2. That is not possible with the naive definition of H because "q" means nothing in the template parameter of "d". So the next step is to inform C++ of the naming of the parameters, so I did: struct p{}; struct q{}; double H(map<pair<p, double>, pair<q, double> > const& args){ return at_key<p>(args)*at_key<p>(args) + at_key<q>(args); // same as return H(at_key<p>(args), at_key<q>(args)); } great, now the compiler has some idea of what the parameters are. I can call this function as H(make_map<p,q>(1.,2.)); H(make_set(1.,2.)); or even as H(1.,2.) now the derivative problem: suppose I already have a magical templated function, called 'derivative' that returns the numerical derivative of a function or function object, when this function has only one argument. template<double(f)(double)> double derivative(double const& x){ ...already defined... } double f(double x){return x*x;} used as derivative<f>(1.); the question is how to define a function "d" that takes a function like H with fusion container arguments, bind it against all arguments except one and calls derivative on that function. For example d<H, q>(1.,2.); internally, the code should bind all the parameters except q to its corresponding values in the argument. in this case it is H binded with p=1. and then *derivative* of H( __, 2.) is called with argument 1. Christofere pointed example libs/fusion/example/cookbook/do_the_bind.cpp seems to be in the right direction but the code is hard to read, not to mention that it doesn't compile. Thank you, Alfredo
-- Dave Abrahams BoostPro Computing http://www.boostpro.com _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-- Sie haben diese Nachricht erhalten, da Sie der Google Groups-Gruppe Boost Users beigetreten sind. Wenn Sie Nachrichten in dieser Gruppe posten möchten, senden Sie eine E-Mail an boostusers@googlegroups.com. Wenn Sie aus dieser Gruppe austreten möchten, senden Sie eine E-Mail an boostusers+unsubscribe@googlegroups.com<boostusers%2Bunsubscribe@googlegroups.com> . Besuchen Sie die Gruppe unter http://groups.google.com/group/boostusers?hl=de, um weitere Optionen zu erhalten.
On 11/07/10 13:07, Alfredo Correa wrote: [snip]
template<double(f)(double)> double derivative(double const& x){ ...already defined... }
double f(double x){return x*x;}
used as derivative<f>(1.);
the question is how to define a function "d" that takes a function like H with fusion container arguments, bind it against all arguments except one and calls derivative on that function. For example
d<H, q>(1.,2.);
internally, the code should bind all the parameters except q to its corresponding values in the argument. in this case it is H binded with p=1. and then *derivative* of H( __, 2.) is called with argument 1.
[snip] What about just creating a fusion::vector for tuple containing an initial value, then store that into a templated functor taking the free variable index as one of the template arguments, and then the operator()(double value) would use value to set the tuple at the template index and then call the function. For example: //{-- free_at.hpp -- template < typename Tuple//e.g. fusion::vector<T1,T2,...Tn> < typename Functor//functor taking value of type Tuple. , unsigned FreeIndex//the index of the Tuple component that's "free"
struct free_at : Tuple { Functor functor ; template<typename... Args> free_at(Functor f, Args... args) : Tuple(args...) , functor(f) {} template<unsigned FreeOther> free_at ( free_at < Tuple , Functor , FreeOther >const& free_other ) //Change the free_variable from FreeOther to FreeIndex : Tuple(free_other) , functor(free_other.f) {} template<typename FreeValu> typename Functor::result_type operator()(FreeValue free_value) { fusion::at_c<FreeIndex>(*this) = free_value; return functor(*this); } }: //}-- free_at.hpp -- Of course the above code uses variadic template notation, but I hope it's clear anyway. Also, Functor is assumed to take a Tuple as an argument. Obviously if the actual function used doesn't do that, then Functor could just contain a pointer to the actual function and expand the Tuple arguments in a call to the actual function. HTH. -Larry
On Sun, Nov 7, 2010 at 2:11 PM, Larry Evans <cppljevans@suddenlink.net>wrote:
On 11/07/10 13:07, Alfredo Correa wrote: [snip]
template<double(f)(double)> double derivative(double const& x){ ...already defined... }
double f(double x){return x*x;}
used as derivative<f>(1.);
the question is how to define a function "d" that takes a function like H with fusion container arguments, bind it against all arguments except one and calls derivative on that function. For example
d<H, q>(1.,2.);
internally, the code should bind all the parameters except q to its corresponding values in the argument. in this case it is H binded with p=1. and then *derivative* of H( __, 2.) is called with argument 1.
[snip] What about just creating a fusion::vector for tuple containing an initial value, then store that into a templated functor taking the free variable index as one of the template arguments, and then the operator()(double value) would use value to set the tuple at the template index and then call the function. For example:
Hi Larry, I used your free_at.hpp to implement numerical derivative on named parameters of a function object. This post has the final solution that I was looking for: 1) First the "derivable" functor with named parameters, it has this general shape: struct p{}; struct q{}; struct H{ double operator()(double p, double q){ return p*p + q*q; } typedef result_of::make_map< p , q , double, double >::type mapped_arguments; double operator()(mapped_arguments const& args){ return operator()(at_key<p>(args), at_key<q>(args)); } }; The operator()( .. map ..) part is not very elegant. I don't know if it can be improved (suggestions?). 2) Now, how to use the derivative with respect to ONE particular named parameter, this is the notation I wanted to achieve. I think it is decent but I accept suggestions. So, the usage: H h; double uno = 1., dos = 2.; clog << h( uno, dos) << endl; // value at 1., 2., prints 5. clog << d<q>(h)(uno, dos) << endl; // value of derivative at 1.,2. prints 4. // more specific name should be // partial<q>(h) where partial stands for partial derivative Now the internal code that makes the magic in "d", that administers the derivation parameter and ultimately takes the numerical derivative on that function: using namespace boost::fusion; template< class FusionMap, // e.g. fusion::map<T1,T2,...Tn> class Functor, // double(FreeFunction)(FusionMap const&), class FreeArgumentMapKey
struct bind_free_at : Functor, FusionMap{ bind_free_at(Functor const& f, FusionMap const& fm) : Functor(f), FusionMap(fm){} double operator()(typename result_of::value_at_key<FusionMap, FreeArgumentMapKey>::type const& free_value){ at_key<FreeArgumentMapKey>(*this) = free_value; return Functor::operator()(*this); } }; template<class ParameterKey, class Functor, class Args> //, class FusionMap> struct d_ { Functor f; template <class Seq> struct result{ typedef double type; }; d_(Functor const& f) : f(f){} typename result<Args>::type operator()(Args const& args) const{ bind_free_at<Args, Functor, ParameterKey> bf(f, args); double x = at_key<ParameterKey>(args); return gsl::derivative::central(bf, x); // this ithe magical function that calculates // the numerical derivative of one-parameter (double->double) function } }; template<class ParameterKey, class Functor, class Args=typename Functor::mapped_arguments> unfused<d_<ParameterKey, Functor, Args> > d(Functor const& f){ return unfused<d_<ParameterKey, Functor, Args> >( d_<ParameterKey, Functor, Args>(f) ); }; The final code is shorter than what I expected. I think there are some internal redundancies and unnecessary copying but at least it works. Another restriction inherited from fusion::fused is that the d<q>(h) object can only take Lvalues. I hope this helps somebody else, having named derivatives like in mathematical notation is a blessing for my code. Note that I gladly accept suggestions/improvements and that I didn't explore the possibility of using Boost.Parameter because I don't understand that library good enough. Another problem left is that in principle I could also use integer index to define the partial derivative parameter. clog << d<1>(h)( ... ) << endl; // derivative with respect to second (or first??) argument, i.e. equal to d<q>(h)(...) shouldn't be complicated since even if I used named parameters in a fusion map they can bereferenced by integer indeces. Cheers and thanks everyone for your help, Alfredo
On 11/09/10 05:02, Alfredo Correa wrote: [snip]
Another problem left is that in principle I could also use integer index to define the partial derivative parameter.
clog << d<1>(h)( ... ) << endl; // derivative with respect to second (or first??) argument, i.e. equal to d<q>(h)(...)
shouldn't be complicated since even if I used named parameters in a fusion map they can bereferenced by integer indeces.
With named parameters, IIUC, you have to declare a struct for each argument. For example, for: double f( double height, double width, double depth); you'd need: struct f_height{}; struct f_width{}; struct f_depth{}; What about using an enum instead: enum f_args { f_height , f_width , f_depty }; ? In that case, there's no need for dereferencing an integer index and the names(i.e. the enumerators) would be just as meaningful. WARNING: not tested. HTH. -Larry
On 11/09/10 05:02, Alfredo Correa wrote: [snip]
I hope this helps somebody else, having named derivatives like in mathematical notation is a blessing for my code.
You might try repeating the process on a derivative. IOW, take a derivative of a derivative. I'm sure it would be interesting. [snip]
On Tue, Nov 9, 2010 at 5:45 AM, Larry Evans <cppljevans@suddenlink.net>wrote:
On 11/09/10 05:02, Alfredo Correa wrote: [snip]
I hope this helps somebody else, having named derivatives like in mathematical notation is a blessing for my code.
You might try repeating the process on a derivative. IOW, take a derivative of a derivative.
yes, yes. Even crossed derivatives, partial<q>(partial<p>(h))(make_set(1.,2.)) Last night I tryed this and works with some limitations on the way passing parameters to the second derivative. for the monent I can't use it as partial<q>(partial<p>(h))(uno, dos) In fact the other threads in the Boost group I opened are to solve this. In a few words, for derivative to have the same interface as H (the model functor) (and automatically generated), I need it to be "fused" and "unfused" at the same time. Which is problematic. You can help in the other threads, if you want. Thank you, Alfredo
I'm sure it would be interesting.
[snip]
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-- Sie haben diese Nachricht erhalten, da Sie der Google Groups-Gruppe Boost Users beigetreten sind. Wenn Sie Nachrichten in dieser Gruppe posten möchten, senden Sie eine E-Mail an boostusers@googlegroups.com. Wenn Sie aus dieser Gruppe austreten möchten, senden Sie eine E-Mail an boostusers+unsubscribe@googlegroups.com<boostusers%2Bunsubscribe@googlegroups.com> . Besuchen Sie die Gruppe unter http://groups.google.com/group/boostusers?hl=de, um weitere Optionen zu erhalten.
On Nov 9, 12:53 pm, Alfredo Correa <alfredo.cor...@gmail.com> wrote:
On Tue, Nov 9, 2010 at 5:45 AM, Larry Evans <cppljev...@suddenlink.net>wrote:
On 11/09/10 05:02, Alfredo Correa wrote: [snip]
I hope this helps somebody else, having named derivatives like in mathematical notation is a blessing for my code.
You might try repeating the process on a derivative. IOW, take a derivative of a derivative.
yes, yes. Even crossed derivatives, partial<q>(partial<p>(h))(make_set(1.,2.))
Last night I tryed this and works with some limitations on the way passing parameters to the second derivative.
for the monent I can't use it as partial<q>(partial<p>(h))(uno, dos)
In fact the other threads in the Boost group I opened are to solve this. In a few words, for derivative to have the same interface as H (the model functor) (and automatically generated), I need it to be "fused" and "unfused" at the same time. Which is problematic.
I achieved concatenated (repeated) derivative notation by using variadic templates: given an original functor that can be called as h(1.,2.); //or h(make_map<p,q>(1.,2.)); you can define the second derivative by repeatedly calling partial<p>(partial<q>(h))(1.,2.); //crossed derivative // or partial<p>(partial<q>(h))(make_map<p,q>(1.,2.)) partial<p>(partial<p>(h))(1.,2.); //second derivative partial<q>(partial<q>(h))(1.,2.); //another second derivative Note 1: calculating second derivatives in this way is not efficient or numerically stable, there are more efficient ways to calculate second derivatives than. Note 2: fortunatelly partial<...> can be specialized for certain function objects, therefore can contain the *explicit* first derivative of the functor) below is the implementation, the addition with respect to the old is using a variadic operator(): --- using namespace boost::fusion; template< class FusionMap, // e.g. fusion::map<T1,T2,...Tn> class Functor, // double(FreeFunction)(FusionMap const&), class FreeArgumentMapKey
struct bind_free_at{ mutable FusionMap m; Functor f; bind_free_at(Functor const& f, FusionMap const& fm) : m(fm), f(f){} //bind_free_at(bind_free_at const& other) : FusionMap((FusionMap const&)other), f(other.f){} double operator()(typename result_of::value_at_key<FusionMap, FreeArgumentMapKey>::type const& free_value) const{ at_key<FreeArgumentMapKey>(m) = free_value; return f(m); } }; template<class ParameterKey, class Functor, class Args=typename Functor::mapped_arguments> //, class FusionMap> struct d_{ Functor f; d_(Functor const& f) : f(f){} template <class Seq> struct result{typedef double type;}; typedef typename Functor::mapped_arguments mapped_arguments; double operator()(mapped_arguments args) const{ bind_free_at<Args, Functor, ParameterKey> bf(f, args); double x = at_key<ParameterKey>(args); return gsl::derivative::central(bf, x); } template<class... DomainTypeS> double operator()(DomainTypeS ... domainS) const{ //BOOST_STATIC_ASSERT((sizeof...(DomainTypeS))>1); return (*this)(mapped_arguments(domainS ... )); } }; template<class ParameterKey, class Functor, class Args=typename Functor::mapped_arguments> d_<ParameterKey, Functor, Args> partial(Functor const& f){ return d_<ParameterKey, Functor, Args>(f); }; still TODO: improve notation for second derivatives: partial<p, 2>(h)(1.,2.); //second derivative with respect to p
participants (7)
-
alfC
-
Alfredo Correa
-
Alfredo Correa
-
Christopher Schmidt
-
Dave Abrahams
-
joel falcou
-
Larry Evans