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