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 > > Phil > >> >>> Thanks for the advice. >>> Luc >>> >>> >>>> Phil >>>> >>>> --------------------------------------------------------------------- >>>> To unsubscribe, e-mail: [EMAIL PROTECTED] >>>> For additional commands, e-mail: [EMAIL PROTECTED] >>>> >>>> >>>> >>> --------------------------------------------------------------------- >>> To unsubscribe, e-mail: [EMAIL PROTECTED] >>> For additional commands, e-mail: [EMAIL PROTECTED] >>> >>> >>> >> >> >> --------------------------------------------------------------------- >> To unsubscribe, e-mail: [EMAIL PROTECTED] >> For additional commands, e-mail: [EMAIL PROTECTED] >> >> > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] > > --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]