commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Phil Steitz <phil.ste...@gmail.com>
Subject Re: [math] Matrix decomposition API
Date Fri, 05 Dec 2008 01:51:34 GMT
Luc Maisonobe wrote:
> Phil Steitz a écrit :
>   
>> Luc Maisonobe wrote:
>>     
>>> Luc Maisonobe a écrit :
>>>  
>>>       
>>>> Phil Steitz a écrit :
>>>>    
>>>>         
>>>>> There are a couple of things about the decomposition API that are
>>>>> starting to bug me.  Apologies for not having raised them until now,
>>>>> since they apply to LU as well as the new Eigen decomp.
>>>>>
>>>>> 1) I don't like the state dependencies bleeding into the decomposition
>>>>> interfaces - i.e., having the interface contract include the
>>>>> requirement
>>>>> that decompose() be called before the getters.  Logically, the
>>>>> decomposition interfaces should just *be* the getters, which is now the
>>>>> case for EigenDecomposition, but not LU (where the interface includes
>>>>> the decompose method).   The state dependency is an implementation
>>>>> artifact that should not be included in the decomposition interface.
>>>>>
>>>>> 2) It would seem natural for decompose return a decomposition, rather
>>>>> than void.
>>>>> I am not sure if there is an efficient way to address both of these,
>>>>> since the caching and incremental computation in the current impls is
>>>>> sort of essential.  At a minimum, we should probably remove the
>>>>> advertised exceptions and decompose methods from the interfaces.
>>>>>
>>>>> Here is one idea that may or may not work.  It would make the API a
>>>>> little more complicated, but if we split the implementation classes
>>>>> into
>>>>> decomposers and decompositions, with decompose producing a
>>>>> decomposition, the decompositions would be able to handle state
>>>>> transparently to users.
>>>>>       
>>>>>           
>>>> I will try to introduce this.
>>>>     
>>>>         
>>> A few more thoughts. If I understand correctly, you propose is to
>>> separate the decomposition part in an interface with a decompose method
>>> and the solver part as the interface returned by this decompose method.
>>> We would have two parallel hierarchies of interfaces/classes:
>>>
>>> interface DecompositionEngine {
>>>   public DecompositionSolver decompose(RealMatrix);
>>> }
>>>
>>> interface XYZEngine extends DecompositionEngine {
>>>
>>>   public void setThreshold(final double threshold) {
>>>      this.threshold = threshold;
>>>   }
>>>
>>>   public XYZDecomposition xyzDecompose(RealMatrix matrix) {
>>>     XYZDecomposition decomposition = new XYZDecompositionImpl();
>>>     decomposition.setThreshold(threshold);
>>>     decomposition.doWhatYouWantWithMatrix(matrix);
>>>     return decomposition;
>>>   }
>>>
>>>   public DecompositionSolver decompose(RealMatrix matrix) {
>>>     return xyzDecompose(matrix);
>>>   }
>>>
>>> }
>>>
>>> interface DecompositionSolver {
>>>   public RealVector solve(RealVector);
>>> }
>>>
>>> interface XYZDecomposition extends DecompositionSolver {
>>>   public void setThreshold(double threshold);
>>>   public RealMatrix getX();
>>>   public RealMatrix getY();
>>>   public RealMatrix getZ();
>>> }
>>>
>>> class XYZDecompositionImpl() implements XYZDecomposition {
>>> }
>>>
>>> This allows both dedicated use of a specific algorithm (XYZ) and the
>>> extra methods it provides (setThrehold, getX ...) and use of generic
>>> interfaces (DecompositionEngine, DecompositionSolver) and the generic
>>> methods (solve, getInverse ...). It is however quite complex.
>>>
>>> A simpler approach is to remove the umbrella interface
>>> DecompositionEngine and the generic decompose method and retain
>>> everything else (perhaps reusing the single name "decompose" for the now
>>> independent methods with different return types). The
>>> DecompositionSolver interface would be kept. This prevents use of a
>>> generic engine.
>>>
>>> An even simpler approach would be to completely remove the state
>>> dependencies part by removing the decompose method and forcing
>>> everything to be set up right at construction. I'm not sure you would
>>> consider it addresses your second point.
>>>
>>> Luc
>>>   
>>>       
>> Sorry I was not clear.  What I meant was to split things more along the
>> following lines (assuming this can be made to work), for e.g.
>> EigenDecompostion.
>>
>> 1. Keep EigenDecomposition as is, but make it standalone - i.e., drop
>> the "Extends DecompositionSolver".  So this now just represents a
>> decomposition.
>>
>> 2. Leave the decompose method in a DecompositionEngine or somesuch with
>> signature
>> EigenDecomposition decompose(RealMatrix).  Leave solve there or put in a
>> separate solver class with signature
>> double[] solve(double[] b, EigenDecomposition ed)
>>
>> So you use decompose(RealMatrix) do create a decomposition that can be
>> used directly or passed to a solver.    This gets around the state
>> dependencies and the need to have constructors do the decompositions. 
>> The DecompositionEngine's decompose method could return a
>> DecompositionImpl that handles state / incremental computation
>> transparently to users.
>>     
>
> I have implemented this. I agree the separation between decomposition
> and solve was worth the change. Could you have a look to the new API ?
>
> Luc
>
>   
Looks good.  Just one last question / suggestion.   In the 
DecompositionSolver, why to we keep the argumentless decompose() methods 
and the matrix as an instance variable?  The argumentless methods just 
delegate to the ones that take a matrix as an argument and the instance 
variable is otherwise unused. 

Phil
>> Phil
>>
>>     
>>>  
>>>       
>>>> Thanks for the advice.
>>>> Luc
>>>>
>>>>    
>>>>         
>>>>> Phil
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
>>>>> For additional commands, e-mail: dev-help@commons.apache.org
>>>>>
>>>>>
>>>>>       
>>>>>           
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
>>>> For additional commands, e-mail: dev-help@commons.apache.org
>>>>
>>>>
>>>>     
>>>>         
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
>>> For additional commands, e-mail: dev-help@commons.apache.org
>>>
>>>   
>>>       
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
>> For additional commands, e-mail: dev-help@commons.apache.org
>>
>>
>>     
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
> For additional commands, e-mail: dev-help@commons.apache.org
>
>   


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org


Mime
View raw message