You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "François Laferrière (Jira)" <ji...@apache.org> on 2023/06/23 10:42:00 UTC

[jira] [Comment Edited] (MATH-1658) ConvergenceChecker should implement OptimizationData

    [ https://issues.apache.org/jira/browse/MATH-1658?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17736428#comment-17736428 ] 

François Laferrière edited comment on MATH-1658 at 6/23/23 10:41 AM:
---------------------------------------------------------------------

Correct. I stubble on this kind of of field initialization order problem a few time and it is quite annoying.

There are other ways to settle ConvergenceChecker:
 # make  protected BaseOptimizer(ConvergenceChecker) deprecated and leave only the default constructor BaseOptimizer(). Then make parseOptimizationData(...) public so that optimizer creation is done in two steps - A - call constructor - B - parse optimization data. This two steps process may be delegated to a factory.
 # rewrite the BaseOptimizer:parseOptimizationData so that it is private and final, using reflexion and bean interface. The idea is to get the class name of each optData (ex. MaxEval) and search a bean accessor with signature set<className>(Class value).

Proposition 1 is very easy to implements.

Proposition 2 is a bit more tedious, because we will have to convert all parseOptimizationData code (in all BaseOptimizer sub classes)  into a bunch of setter.

for instance
   
{code:java}
 protected void parseOptimizationData(OptimizationData... optData) {
        // The existing values (as set by the previous call) are reused if
        // not provided in the argument list.
        for (OptimizationData data : optData) {
            if (data instanceof MaxEval) {
                maxEvaluations = ((MaxEval) data).getMaxEval();
                continue;
            }
            if (data instanceof MaxIter) {
                maxIterations = ((MaxIter) data).getMaxIter();
                continue;
            }
            if (data instanceof ConvergenceChecker) {
                checker = (ConvergenceChecker<PAIR>) data;
                continue;
            }
        }
    }
{code}


is replaced by

   
{code:java}
 protected void setMaxEval(MaxEval optData) {
        maxEvaluations = optData.getMaxEval();
    }
    
    protected void setMaxIter(MaxIter optData) {
        maxEvaluations = optData.getMaxIter();
    }
    
    protected void setConvergenceChecker(ConvergenceChecker<PAIR> optData) {
        checker = optData;
    }

{code}


As noted above, it is tedious because some code has to be touched in a score of classes. On the other hand side, doing so we get rid of all the ugly instanceof and type casts.


was (Author: JIRAUSER299106):
Correct. I stubble on this kind of of field initialization order problem a few time and it is quite annoying.

There are other ways to settle ConvergenceChecker:
 # make  protected BaseOptimizer(ConvergenceChecker) deprecated and leave only the default constructor BaseOptimizer(). Then make parseOptimizationData(...) public so that optimizer creation is done in two steps - A - call constructor - B - parse optimization data. This two steps process may be delegated to a factory.
 # rewrite the BaseOptimizer:parseOptimizationData so that it is private and final, using reflexion and bean interface. The idea is to get the class name of each optData (ex. MaxEval) and search a bean accessor with signature set<className>(Class value).

Proposition 1 is very easy to implements.

Proposition 2 is a bit more tedious, because we will have to convert all parseOptimizationData code (in all BaseOptimizer sub classes)  into a bunch of setter.

for instance
{{    protected void parseOptimizationData(OptimizationData... optData) {
        // The existing values (as set by the previous call) are reused if
        // not provided in the argument list.
        for (OptimizationData data : optData) {
            if (data instanceof MaxEval) {
                maxEvaluations = ((MaxEval) data).getMaxEval();
                continue;
            }
            if (data instanceof MaxIter) {
                maxIterations = ((MaxIter) data).getMaxIter();
                continue;
            }
            if (data instanceof ConvergenceChecker) {
                checker = (ConvergenceChecker<PAIR>) data;
                continue;
            }
        }
    }
}}

is replaced by

{{    protected void setMaxEval(MaxEval optData) {
        maxEvaluations = optData.getMaxEval();
    }
    
    protected void setMaxIter(MaxIter optData) {
        maxEvaluations = optData.getMaxIter();
    }
    
    protected void setConvergenceChecker(ConvergenceChecker<PAIR> optData) {
        checker = optData;
    }
}}

As noted above, it is tedious because some code has to be touched in a score of classes. On the other hand side, doing so we get rid of all the ugly instanceof and type casts.

> ConvergenceChecker should implement OptimizationData
> ----------------------------------------------------
>
>                 Key: MATH-1658
>                 URL: https://issues.apache.org/jira/browse/MATH-1658
>             Project: Commons Math
>          Issue Type: Improvement
>          Components: legacy
>    Affects Versions: 4.0-beta1
>            Reporter: François Laferrière
>            Priority: Minor
>         Attachments: MATH-1658-ConvergenceChecker-implements-OptimizationData.patch
>
>
> It is a bit peculiar that with BaseOptimizer, ConvergenceChecker can be passed only in constructor.
> It should be possible to change ConvergenceChecker at any other time.
> Further it is a bit strange that the constructor do not accept other OptimizationData.
> In my use cases, I need to create an optimizer once with complex OptimizationData and reuse it many time with very few changes (including changing the ConvergenceChecker).
> So, I suggest that
>  * ConvergenceChecker implements OptimizationData.
>  * protected BaseOptimizer(ConvergenceChecker<PAIR> checker) is replaced by protected BaseOptimizer(OptimizationData... optData) 
> Doing so is compatible with existing code and provide much more flexibility.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)