Thanks for this analysis. In my case, I require the more generic version
with overlapping variable sets for component functions. Also, I need to
worry about multiplication of component functions too.

I'll think about the most efficient way to do this.

Cheers,
Ajo.


On Fri, Aug 30, 2013 at 12:21 AM, Luc Maisonobe <luc.maison...@free.fr>wrote:

> Hi Ajo,
>
> Le 29/08/2013 19:05, Ajo Fod a écrit :
> > Hello,
> >
> > I wonder if the number of computations required to compute a derivative
> > structure can be reduced. Say the derivative structure of f to order d=2
> is
> > desired:
> > f(g1(x1), g2(x2), ... gn(xn)) where x1,x2 ... xn are subsets of variables
> > that are not necessarily disjoint.
> >
> > For each gi(xi), O(n^2) variables need to be computed while I only need
> > [xi]^2 different variables. (Where [xi] stands for the cardinality of the
> > set xi)
> >
> > In the extreme case say x1...xn are single variables (sets of cardinality
> > 1):
> > To compute the derivative structure to order 2 of:
> > f(sin(x1)+cos(x2)+... tan(xn))
> > O(n^2) values for each of the n components needs to be computed (or at
> > least memory allocated for that much):
> > so that is a total of over O(n^3) values.
> >
> > If there were a way of computing only derivatives of relevant variables,
> > each term of f() would require only 2 calculations or a total of 2n
> > calculations.
> >
> > So, is there a way to compute the derivative of each component separately
> > and "join" them together? When the derivative structure is sparse, this
> > should reduce computation required from O(n^3) to O(n) ... quite a large
> > saving when n is large.
>
> It is possible, but implies doing all the "join" work by yourself.
>
> The first step is to compute each gi function using DerivativeStructure
> instances configured to one parameter only (regardless of i) and second
> order:
>
>   DerivativeStructure x1   = new DerivativeStructure(1, 2, 0, x1Value);
>   DerivativeStructure g1x1 = g1.value(x1);
>   DerivativeStructure x2   = new DerivativeStructure(1, 2, 0, x2Value);
>   DerivativeStructure g2x2 = g2.value(x2);
>   ...
>   DerivativeStructure xn   = new DerivativeStructure(1, 2, 0, xnValue);
>   DerivativeStructure gnxn = gn.value(xn);
>
> As each gi.value method is called, it gets the value for one variable
> only and is not aware there are other instances lying around. It only
> computes gi, dgi/dxi, d^2gi/dxi^2, so three numbers each. The number of
> computations here remains linear in the number of variables.
>
> Now comes the tricky and manual part: computing f. This method must be
> aware of the full variable set for which you want partial derivatives.
> You can do that by "expanding" your DerivativeStructure instances to add
> 0 derivatives. In the case the xi all have cardinality 1 and you want xi
> to be mapped to index i-1 in the n-cardinality full set, you can use
> something similar to:
>
>  public DerivativeStructure mapGToFullSet(final int parameters,
>                                           final int index,
>                                           final DerivativeStructure g) {
>     final int order = g.getOrder();
>     final DSCompiler compiler =
>       DSCompiler.getCompiler(parameters, index);
>     final double[] derivatives = new double[compiler.getSize()];
>     final int[] orders = new int[order + 1];
>
>     // copy d^k g / dx^k at its dedicated index in the expanded data
>     for (int k = 0; k <= order; ++k) {
>       order[index] = k;
>       derivatives[compiler.getPartialDerivativeIndex(orders)] =
>           g.getPartialDarivatives(k);
>       order[index] = O;
>     }
>
>     return new DerivativeStructure(parameters, order, derivatives);
>
>  }
>
> So you would do
>
>   DerivativeStructure g1 = mapGToFullSet(n, 0, g1x1);
>   DerivativeStructure g2 = mapGToFullSet(n, 1, g2x2);
>   ...
>   DerivativeStructure gn = mapGToFullSet(n, n - 1, gnxn);
>
> And finally
>
>   DerivativeStructure fx1xn = f.value(g1, g2, ..., gn);
>
> The mapping part allocates n full derivatives arrays, but only
> initialize very few elements in them, letting most of the elements set
> to 0. It also don't compute anything, it is simply data copying. It is
> probably O(n^2) for order two derivatives, but with a small coefficient.
>
> The f.value() part is a full-blown computation of all derivatives. It
> may reamin costly as is. In the general case you would save computation
> on the gi, not on f. If f is really a univariate function (like in your
> f(sin(x1)+cos(x2)+... tan(xn)) case), it may be possible to save a
> little more. You would have to compute first y = sin(x1)+cos(x2)+...
> tan(xn) with all derivatives, then build an intermediate single variable
> yTmp and apply f to it (i.e. the internal computation in f would only
> consider a single variable), and then combine the derivatives as follows:
>
>  DerivativeStructure y = ...; // full sin(x1)+cos(x2)+...
>  DerivativeStructure yTmp =
>    new DerivativeStructure(1, 2, 0, y.getValue());
>  DerivativeStructure fTmp = f.value(yTmp); // only one variable, fast!
>  DerivativeStructure z = y.compose(fTmp.getAllDerivatives());
>  return z;
>
>
> Note that if the xi variables are not cardianlity 1 but rather a subset
> of a larger set (say x1 is (a, b), x2 is (a, c), ... xn is (a, b, c)),
> then the mapping function becomes more complicated. It should use the
> compilers of both th initial reduced set and the complete set (in the
> example above our compiler instance was only for the complete set), and
> it should also create an orders derivatives array for the reducced set
> (in the example above, we directly used g.getPartialDarivatives(k)
> because in the special case of one parameter only, it is guaranteed that
> the index and the derivation order match). The mapping function should
> also use some indirection table to know for each variable x1, x2 ...
> what is the reduced set that was used to compute the derivatives (in the
> example above, we simply used an index argument telling the index of the
> single variable in the full set). I don't know if the most general
> mapping function would really be interesting or not. If you feel like
> contributing such a function, I would be happy to review it.
>
> best regards,
> Luc
>
> >
> > Any comments on this? ... or errors in this line of though?
> >
> > Thanks,
> > Ajo.
> >
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
> For additional commands, e-mail: dev-h...@commons.apache.org
>
>

Reply via email to