Return-Path: X-Original-To: apmail-commons-dev-archive@www.apache.org Delivered-To: apmail-commons-dev-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 6B51E106C3 for ; Wed, 14 Aug 2013 22:35:24 +0000 (UTC) Received: (qmail 43478 invoked by uid 500); 14 Aug 2013 22:35:23 -0000 Delivered-To: apmail-commons-dev-archive@commons.apache.org Received: (qmail 43364 invoked by uid 500); 14 Aug 2013 22:35:23 -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 43356 invoked by uid 99); 14 Aug 2013 22:35:23 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 14 Aug 2013 22:35:23 +0000 X-ASF-Spam-Status: No, hits=-0.7 required=5.0 tests=RCVD_IN_DNSWL_LOW,SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (athena.apache.org: local policy) Received: from [193.74.71.28] (HELO sif.is.scarlet.be) (193.74.71.28) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 14 Aug 2013 22:35:18 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=scarlet.be; s=scarlet; t=1376519696; bh=60PXh9HGFRBH/NDuVXTShmZnpwT6c5szOiAG+JRkDp0=; h=MIME-Version:Content-Type:Content-Transfer-Encoding:Date:From:To: Subject:In-Reply-To:References:Message-ID; b=wsx54mDEIQdJPYh2/jfkJ+OZ7DTZrQ25GwxsOyZzP4E7bWr8r638pvIGZAgSyAHlR hJRGIvm3gnAnxxvvw6JZVXthLGtl9iDG6+TTOcg27uRRjRB6gWc1eU4PF09d0xe7/d x2QJSDw4DDR8WpyLri+gPSMlUfB06UKzLgsHSTZ0= Received: from webmail.scarlet.be (gresham.is.scarlet.be [193.74.71.215]) by sif.is.scarlet.be (8.14.5/8.14.5) with ESMTP id r7EMYtH2031776 for ; Thu, 15 Aug 2013 00:34:56 +0200 X-Scarlet: d=1376519696 c=193.74.71.215 Received: from ip-213-49-231-28.dsl.scarlet.be ([213.49.231.28]) via ip-213-49-231-28.dsl.scarlet.be ([213.49.231.28]) by webmail.scarlet.be with HTTP (HTTP/1.1 POST); Thu, 15 Aug 2013 00:34:55 +0200 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Date: Thu, 15 Aug 2013 00:34:55 +0200 From: Gilles To: Subject: Re: [Math] Fluent API, inheritance and immutability In-Reply-To: <520BF62C.8000207@nrl.navy.mil> References: <5202C477.7000805@nrl.navy.mil> <4bce809bf25424df26ac7c785e62e671@scarlet.be> <520350D8.8040806@spaceroots.org> <32c015fcad3340ed67a0a17dab5c2b82@scarlet.be> <5203A4FC.6090400@nrl.navy.mil> <06f3ad8c07d6ada845ba4f8937c90efa@scarlet.be> <5203DBE0.1070500@nrl.navy.mil> <52058C7C.6030105@gmail.com> <52090785.2090009@nrl.navy.mil> <52090B10.1040208@gmail.com> <5209219D.3000300@nrl.navy.mil> <520AA966.4070009@nrl.navy.mil> <520BF62C.8000207@nrl.navy.mil> Message-ID: <7d9f072992c9493823f5d3b2a6c9adcf@scarlet.be> X-Sender: gilles@harfang.homelinux.org User-Agent: Scarlet Webmail X-DCC-scarlet.be-Metrics: sif; whitelist X-Virus-Scanned: clamav-milter 0.97.1-exp at sif X-Virus-Status: Clean X-Virus-Checked: Checked by ClamAV on apache.org Hi. > > [...] > > Since the iteration counter was incremented explicitly I thought it > made > sense to increment the evaluation counter explicitly. It's indeed cleaner to have the two counters handled in a similar fashion. Actually, the iteration counter was an afterthought: Driven by my current usage (where an evaluation is much more time consuming than the optimization algorithm book-keeping), I assumed that the evaluation counter was a more objective way to limit the effort. But if your proposal is amenable to create customized instances of "LeastSquaresProblem" that use one or the other (or both), it starts to look definitely interesting. > With the interface > based design it would be easy to create a wrapper to track > evaluations > to keep the original semantics: > > public static LeastSquareProblem countEvaluations(final > LeastSquaresProblem lsp, final Incrementor counter){ > return new LeastSquaresProblem(){ > /* delegate all other methods to lsp */ > > public Evaluation evaluate(double[] point){ > counter.increment(); > return lsp.evaluate(point); > } > }; > } With this ... > [...] > I think the weights are definitely part of the "problem". I hesitate > if > there should be a getWeights() method in the API. It seems to me that > the weights could just be applied to the residuals and Jacobian and > the > algorithm wouldn't know the difference. (Maybe this is naive.) The > weight functionality could be added to the "problem" using > composition > (a wrapper class) and not though explicit API support. For example, > remove getWeigts() from LeastSquaresProblem and use the composition: > > static LeastSquaresProblem weight(LeastSquaresProblem lsp, RealMatrix > weights) { > return new LeastSquaresProblem(){ > /* delegation, apply weights ... */ > }; > } ... and this, I now start to see the advantage of the "LeastSquaresProblem" interface. It seems then that instances should indeed be created using a "Builder" pattern; it would ultimately return a "read-only" instances as you suggest. > > The common case of a diagonal weight matrix could have its own, > possible > more efficient, composition. If those customizations can be set up in a "LSP" factory, that would be quite fine. >>> - Should the LeastSquaresProblem interface include mutators? I >>> think >>> it makes sense to only include the methods that the optimization >>> algorithm needs to "read". That would keep the API smaller and not >>> tie >>> the users to a particular implementation. >> >> Hmm, do you suggest here that we drop the fluent API (whose purpose >> is >> indeed to mutate fields)? > > I suggest that the interface only include the "get" and "evaluate" > methods. This is all the information the optimization algorithm > needs. > It also makes composition easier. The LeastSquaresProblemImpl class > could implement a fluent API. Then the user use new > LeastSquaresProblemImpl().withXxx() and the LeastSquaresProblem > interface wouldn't place more requirements than necessary on all > implementations. I also agree with that. > [...] > >> Could we create an "o.a.c.m.experimental" sub-package, and put >> "competing" designs inside it: e.g. >> o.a.c.m.experimental.evan >> o.a.c.m.experimental.gilles >> for people to test with 3.3, and postpone a decision until we can >> see >> better the differences? Maybe this would allow to pick all the >> better >> features from each and merge them in a final design... >> > > I agree it definitely needs more testing and polishing. Let me think > about the two development lines idea. I would hate for us to > duplicate > our work and then "throw away" one person's work at the end. At this point, I'd tend to think that creating a copy of trunk in the Commons's "sandbox" part of the repository will be more productive. There, we can both directly modify the code to make a point and converge to a design while incrementally ensure that every features turn out as imagined. So, for me, the selling point would be the "LSP" customisation process i.e. (unless the devil appears in the details) abstract away from the core optimizer everything that is a user decision: counting evaluations and/or iterations (and what to do when the counter is exhausted), apply weights, set up callbacks (beyond the convergence checker) that would allow to e.g. track the optimizer's search path, ... Regards, Gilles --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org For additional commands, e-mail: dev-help@commons.apache.org