Hello.

Le jeu. 20 janv. 2022 à 15:06, qiqi tang <tangonepiece...@gmail.com> a écrit :
>
> Dear Sir/Madam,
>        I recently used the CurveFitter tool inside the commons package and
> I found a problem that I couldn't constrain the relevant parameters.

A possible approach is to transform the relevant parameters so
that whatever value is tried by the optimizer, it always maps to a
value within the allowed range (see below).

> The specific relevant codes are as follows:

import org.apache.commons.math4.legacy.analysis.function.Logit;
import org.apache.commons.math4.legacy.analysis.function.Sigmoid;

> public class MyFuncFitter extends AbstractCurveFitter {
    private Sigmoid constrainedM;
    private Logit unconstrainedK;
    private Sigmoid constrainedK;
    private Logit unconstrainedK

    public MyFuncFitter(minM, maxM, minK, maxK) {
        constrainedM = new Sigmoid(minM, maxM);
        unconstrainedM = new Logit(minM, maxM);
        constrainedK = new Sigmoid(minK, maxK);
        unconstrainedK = new Logit(minK, maxK);
   }

>     @Override
>     protected LeastSquaresProblem
> getProblem(Collection<WeightedObservedPoint> points) {
>         final int len = points.size();
>         final double[] target = new double[len];
>         final double[] weights = new double[len];
>         final double[] initialGuess = {
              unconstrainedM.value(50),
              unconstrainedK.value(1.0),
              1.0
           };
>
>         int i = 0;
>         for (WeightedObservedPoint point : points) {
>             target[i] = point.getY();
>             weights[i] = point.getWeight();
>             i += 1;
>         }
>
>         final AbstractCurveFitter.TheoreticalValuesFunction model =
> new AbstractCurveFitter.TheoreticalValuesFunction(new MyFunc(),
> points);
>
>         return new LeastSquaresBuilder().
>                 maxEvaluations(Integer.MAX_VALUE).
>                 maxIterations(Integer.MAX_VALUE).
>                 start(initialGuess).
>                 target(target).
>                 weight(new DiagonalMatrix(weights)).
>                 model(model.getModelFunction(),
> model.getModelFunctionJacobian()).build();
>     }}
>
> public class MyFunc implements ParametricUnivariateFunction {
>     @Override
>     public double value(double x, double... parameters) {
         final double m = constrainedM.value(parameters[0]);
         final double k = constrainedK.value(parameters[1]);
         final double b = parameters[2];

>         return m * k * b * Math.exp(-k * x) * Math.pow(1 - Math.exp(-k
> * x), b - 1);
>     }
>
>     @Override
>     public double[] gradient(double x, double... parameters) {
         final double m = constrainedM.value(parameters[0]);
         final double k = constrainedK.value(parameters[1]);
         final double b = parameters[2];

>         return new double[]{
>                 b * k * Math.exp(-k * x) * Math.pow(1 - Math.exp(-k *
> x), b - 1),
>                 (b - 1) * b * k * m * x * Math.exp(-2 * k * x) *
> Math.pow(1 - Math.exp(-k * x), b - 2) + b * m * Math.exp(-k * x) *
> Math.pow(1 - Math.exp(-k * x), b - 1) - b * k * m * x * Math.exp(-k *
> x) * Math.pow(1 - Math.exp(-k * x), b - 1),
>                 k * m * Math.exp(-k * x) * Math.pow(1 - Math.exp(-k *
> x), b - 1) + b * k * m * Math.exp(-k * x) * Math.pow(1 - Math.exp(-k *
> x), b - 1) * Math.log(1 - Math.exp(-k * x))
>         };

    @Override
    public double[] fit(Collection<WeightedObservedPoint> points) {
        final double[] p = super.fit(points);
        return new double[] {
            constrainedM.value(p[0]),
            constrainedK.value(p[1]),
            p[2]
        };
    }

>     }
>
>     public static void main(String[] args) {
>         MyFuncFitter fitter = new MyFuncFitter();
>         ArrayList<WeightedObservedPoint> points = new ArrayList<>();
>         points.add(new WeightedObservedPoint(1.0, 0.25, 3.801713179));
>         points.add(new WeightedObservedPoint(1.0, 4, 10.46561902));
>         final double coeffs[] = fitter.fit(points);
>         System.out.println(Arrays.toString(coeffs));
>     }}
>
> Then, What should I do to limit the parameters 'm' to 1 to 100 and 'k'
> to 100 to 10,000,It would be nice if the code dome was available.

I don't understand what "code dome" means.

> Please help me thank you very much!

Let us know how the above suggestion (untested code) went.

Best regards,
Gilles

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscr...@commons.apache.org
For additional commands, e-mail: user-h...@commons.apache.org

Reply via email to