Re: Problem applying generics to my code. Is there a better solution?
- From: "Daniel Pitts" <googlegroupie@xxxxxxxxxxxxx>
- Date: 4 Apr 2007 22:15:26 -0700
Lucas wrote:
Anytime that you find yourself using a chain of "instanceof" checks onHow about this:
public static <T, P> Distribution<P> posterior(List<Double> data,
NormalDistribution<T> likelihood, NormalDistribution<P> prior)
{
return normalNormalPosterior(data, likelihood, prior );
}
public static <T, P> Distribution<P> posterior(List<Integer> data,
PoissonDistribution<T> likelihood, GammaDistribution<P> prior)
{
return normalNormalPosterior(data, likelihood, prior);
}
Why have one method that does two things?
Oops. That was a typo on my part. That code path should be
public static <T, P> Distribution<P> posterior(List<Integer> data,
PoissonDistribution<T> likelihood, GammaDistribution<P> prior)
{
return poissonGammaPosterior(data, likelihood, prior);
}
You might even want to make PoissonDistribution implement a method
posterior which takes a List<Integer> data, GammaDistribution<P>
prior), and likewise on the NormalDistribution.
My motivation for the original choice was that, as a user of the
package, I want to manipulate generic Distribution<T> objects and let
the library decide if there is an efficient way of giving a
posterior. There are always numerical methods to fall back on. Also,
there can be multiple conjugate priors for the same likelihood.
Here's an example of how I want to interface to these methods
import static my.package.Conjugate.*;
public static void foo()
{
Distribution<Double> distn1 = new NormalDistribution( mu, sigma );
Distribution<Double> distn2 = new NormalDistribution( 0, tau );
Distribution<Double> post = posterior( distn1, distn2 );
}
So, the underlying problem I'm trying to solve is to dispatch based on
the most specific type of the object. Per your suggestion, I could
get around this by adding a posterior() method that would be
implemented along the lines of
public class NormalDistribution implements Distribution<Double>
{
public Distribution<Double> posterior( List<Double> data,
Distribution<Double> prior )
{
if ( prior instanceof NormalDistibution ) return
normalNormalPosterior( data, this, prior );
if ( prior instanceof GammaDistribution ) return
normalGammaPosterior( data, this, prior );
}
}
classes which you control, its time to look into using polymorphism
instead... You're particular problem may be best solved through a
Visitor pattern.
Here's an example, I'm removing the generics, as they're not necessary
for my point.
abstract class Distribution {
Distribution posterior(List list, Distribution prior) {
prior.visit(this);
}
protected Distribution posteriorList list, Normal prior) {
throw new IllegalArgumentException("Not valid");
}
protected Distribution posterior(List list, Normal prior) {
throw new IllegalArgumentException("Not valid");
}
public abstract Distribution visit(List list, Distribution d);
}
class Normal {
protected Distribution posterior(List list, Normal prior) {
return normalNormaPosterior(list, this, prior);
}
protected Distribution posterior(List list, Gamma prior) {
return normalGammaPosterior(list, this, prior);
}
public Distribution visit(List list, Distribution d) {
return d.posterior(list, this);
}
}
class Gamma {
protected Distribution posterior(List list, Normal prior) {
return gammaNormaPosterior(list, this, prior);
}
protected Distribution posterior(List list, Gamma prior) {
return gammaGammaPosterior(list, this, prior);
}
public Distribution visit(List list, Distribution d) {
return d.posterior(list, this);
}
}
or should I just create separate methods for each type of supported
prior distribution and force the caller to call the posterior() method
with an concrete type and not the generic Distribution<> type?
That might not be a bad idea, but a "visitor pattern" might be more
appropriate... Alternatively, you might look for algorithms that are
distribution type agnostic. I would probably go for the visitor
approach, google it :-)
I actually don't know much about the problem domain your solving. I'm
I'm going to ramble on a bit here and point out that the library have
a ConditionalDistribution class which would probably be the most
appropriate vehicle for your suggestion since a NormalDistribution
class itself does not have any unbound parameters. To replicate the
last example
public class NormalDistributionWithUnknownMean extends
NormalDistribution implements ConditionalDistribution<Double, Double>
{
public NormalDistribution conjugate( List<Double> data,
NormalDistribution prior )
{
return normalNormalPosterior( data, this, prior );
}
}
public class NormalDistributionWithUnknownVariance extends
NormalDistribution implements ConditionalDistribution<Double, Double>
{
public NormalDistribution conjugate( List<Double> data,
GammaDistribution prior )
{
return normalGammaPosterior( data, this, prior );
}
}
Thank you for the discussion.
guessing statistics? (The one math I haven't studied much) :-)
Anyway, I hope I've been able to help.
.
- Follow-Ups:
- References:
- Prev by Date: Re: getting the width and height of a String to draw a rectangle around it
- Next by Date: Re: Quick way to initialize array with all zeros
- Previous by thread: Re: Problem applying generics to my code. Is there a better solution?
- Next by thread: Re: Problem applying generics to my code. Is there a better solution?
- Index(es):
Relevant Pages
|