Return-Path: Delivered-To: apmail-commons-dev-archive@www.apache.org Received: (qmail 25152 invoked from network); 5 Dec 2008 01:53:10 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 5 Dec 2008 01:53:10 -0000 Received: (qmail 37943 invoked by uid 500); 5 Dec 2008 01:53:21 -0000 Delivered-To: apmail-commons-dev-archive@commons.apache.org Received: (qmail 37861 invoked by uid 500); 5 Dec 2008 01:53:21 -0000 Mailing-List: contact dev-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: "Commons Developers List" Delivered-To: mailing list dev@commons.apache.org Received: (qmail 37848 invoked by uid 99); 5 Dec 2008 01:53:21 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 04 Dec 2008 17:53:21 -0800 X-ASF-Spam-Status: No, hits=-0.0 required=10.0 tests=SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (athena.apache.org: domain of phil.steitz@gmail.com designates 209.85.221.17 as permitted sender) Received: from [209.85.221.17] (HELO mail-qy0-f17.google.com) (209.85.221.17) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 05 Dec 2008 01:51:51 +0000 Received: by qyk10 with SMTP id 10so7781590qyk.18 for ; Thu, 04 Dec 2008 17:51:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from :user-agent:mime-version:to:subject:references:in-reply-to :content-type:content-transfer-encoding; bh=tchJ8BXULMuiO9m7j8fRP6K/WRevw9MquO8AMuXSd4c=; b=dHr/4rGENxA0mjG9XAeRTdTxw2aUOSL62y4UG+rORn5ua93XQh5n3EyD8H9I+xDsQb dEhSdGrdFqKonIWUDgmn1I2+JhZYAL6cKtTwQLTE3lK2e0FiC1jklZmLWFzB/Ttz582z JR4ge9Ncpa0W1Jtesa3At54lZHWGdIEAVzLcM= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:user-agent:mime-version:to:subject:references :in-reply-to:content-type:content-transfer-encoding; b=WnJw/61DcSNmeD7ZVx4HjMHWHlHjM+3uO8HthNIaYhz0j8RadqM1J2ACFXhrVf2xQE /lGW7tGyNVO1rk++MY2/RYrtJXpiHpbFQSZ+MhvIy2600rfaba1EMrqr63G5zmjRPsZt nH16xT79fyqMXKTKlUKK0P0a+3+GN8XNwnSP0= Received: by 10.214.9.5 with SMTP id 5mr15870608qai.233.1228441897218; Thu, 04 Dec 2008 17:51:37 -0800 (PST) Received: from phil-steitzs-macbook-pro.local (pool-98-114-70-58.phlapa.east.verizon.net [98.114.70.58]) by mx.google.com with ESMTPS id 4sm10182323yxq.9.2008.12.04.17.51.35 (version=SSLv3 cipher=RC4-MD5); Thu, 04 Dec 2008 17:51:36 -0800 (PST) Message-ID: <49388926.9070108@gmail.com> Date: Thu, 04 Dec 2008 20:51:34 -0500 From: Phil Steitz User-Agent: Thunderbird 2.0.0.18 (Macintosh/20081105) MIME-Version: 1.0 To: Commons Developers List Subject: Re: [math] Matrix decomposition API References: <4931D57D.9020003@gmail.com> <4935A1DB.2020300@free.fr> <4935AD4C.4050609@free.fr> <4935E42D.5090208@gmail.com> <49386EAA.2070205@free.fr> In-Reply-To: <49386EAA.2070205@free.fr> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 8bit X-Virus-Checked: Checked by ClamAV on apache.org 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