
Proto : 
Subject: Re: [proto] Manipulating an expression tree
From: Thomas Heller (thom.heller_at_[hidden])
Date: 20110408 07:43:05
On Fri, Apr 8, 2011 at 10:56 AM, Karsten Ahnert
<karsten.ahnert_at_[hidden]> wrote:
>>>> If you need to compute intermediate values, you can use a transform to
>>>> build a parallel structure.
>>>
>>> Do you mean to build an entire new tree, or just to replace some nodes?
>>
>> If only some nodes have associated intermediate result, then you could
>> just replace some nodes.
>
> Ok, this is a clear hint.
>
>>> In my current algorithm I use callable contexts to do the work. I think
>>> this is more favorable since I have to evaluate the tree N times to
>>> obtain
>>> the result.
>>
>> Why does that matter? Transforms are almost always a better choice.
>>
>>> I think it would be nice to replace some nodes and customizing
>>> the evaluation context, such that these nodes can be used to store the
>>> intermediates.
>>
>> If you're doing calculation *and* tree transformation, then drop the
>> callable contexts. They can't do the job.
>
> First I do tree transformation and then calculation. A Callable context
> will not do the job, since one only gets the tag of the current node, but
> not the node itself. So I have to implement my own context.
>
> I am not sure if transforms can do that job. It is definitely not possible
> to obtain the full tree for 10th derivative. Maybe some other tricks are
> possible with transforms. At the moment I don't understand them in detail,
> but I will try to change this. Thanks for your advice.
Why not just write a transform that calculates one derivative and call
it N times to get the Nth derivative?
Something like:
struct derivative
: proto::or_<
proto::when<
proto::plus<derivative, derivative>
, proto::_make_plus<derivative(proto::_left),
derivative(proto::_right)>
>
proto::when<
proto::multiplies<derivative, derivative>
, proto::_make_plus<
proto::_make_multiplies<derivative(proto::_left), proto::_right>
,proto::_make_multiplies<proto::_left, derivative(proto::_right)>
>
>
>
/* add more derivation rules*/
{};
template <int N>
struct derive_impl
{
template <typename Sig>
struct result;
template <typename This, typename Expr>
struct result<This(Expr)>
{
typedef typename boost::result_of<derivative(Expr)>::type
first_derivative;
typedef typename
boost::result_of<derive_impl<N1>(first_derivative)>::type type;
};
template <typename Expr>
typename result<derive_impl(Expr const&)>::type
operator()(Expr const & expr) const
{
return derive_impl<N1>(derivative()(expr));
}
};
template <>
struct derive_impl<0>
{
template <typename Sig>
struct result;
template <typename This, typename Expr>
struct result<This(Expr)>
: result<This(Expr const &)>
{};
template <typename This, typename Expr>
struct result<This(Expr &)>
{ typedef Expr type; };
template <typename Expr>
typename result<derive_impl(Expr const&)>::type
operator()(Expr const & expr) const
{
return expr;
}
};
template <int N, typename Expr>
typename boost::result_of<derive_impl<N>(Expr const &)>::type
derive(Expr const & expr)
{
return derive_impl()(expr);
}
Proto list run by eric at boostpro.com