/* * ModelOptions.java * * Copyright (c) 2002-2015 Alexei Drummond, Andrew Rambaut and Marc Suchard * * This file is part of BEAST. * See the NOTICE file distributed with this work for additional * information regarding copyright ownership and licensing. * * BEAST is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * BEAST is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with BEAST; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ package dr.app.beauti.options; import dr.app.beauti.components.ComponentFactory; import dr.app.beauti.types.OperatorType; import dr.app.beauti.types.PriorScaleType; import dr.app.beauti.types.PriorType; import dr.evolution.util.TaxonList; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @author Alexei Drummond * @author Andrew Rambaut */ public abstract class ModelOptions implements Serializable { private static final long serialVersionUID = 6199011531067286245L; protected final Map<String, Parameter> parameters = new HashMap<String, Parameter>(); protected final Map<String, Operator> operators = new HashMap<String, Operator>(); protected final Map<TaxonList, Parameter> statistics = new HashMap<TaxonList, Parameter>(); public static final double demoTuning = 0.75; public static final double demoWeights = 3.0; protected static final double branchWeights = 30.0; protected static final double treeWeights = 15.0; protected static final double rateWeights = 3.0; private final List<ComponentOptions> components = new ArrayList<ComponentOptions>(); //+++++++++++++++++++ Abstract Methods ++++++++++++++++++++++++++++++++ public abstract void initModelParametersAndOpererators(); public abstract List<Parameter> selectParameters(List<Parameter> params); public abstract List<Operator> selectOperators(List<Operator> ops); public abstract String getPrefix(); //+++++++++++++++++++ Create Parameter ++++++++++++++++++++++++++++++++ public Parameter createParameter(String name, String description) { return new Parameter.Builder(name, description).build(parameters); } public Parameter createParameter(String name, String description, double initial) { return new Parameter.Builder(name, description).initial(initial).isFixed(true).build(parameters); } public Parameter createZeroOneParameter(String name, String description, double initial) { return new Parameter.Builder(name, description) .initial(initial).isZeroOne(true).build(parameters); } public Parameter createZeroOneParameterUniformPrior(String name, String description, double initial) { return createZeroOneParameterUniformPrior(name, description, initial, false); } public Parameter createZeroOneParameterUniformPrior(String name, String description, double initial, boolean amtk) { return new Parameter.Builder(name, description).prior(PriorType.UNIFORM_PRIOR) .initial(initial).isZeroOne(true).isAdaptiveMultivariateCompatible(amtk).build(parameters); } public Parameter createNonNegativeParameterDirichletPrior(String name, String description, PartitionOptions options, double maintainedSum, boolean amtk) { return new Parameter.Builder(name, description).prior(PriorType.DIRICHLET_PRIOR) .isNonNegative(true).maintainedSum(maintainedSum) .isAdaptiveMultivariateCompatible(amtk) .partitionOptions(options).build(parameters); } public Parameter createNonNegativeParameterDirichletPrior(String name, String description, PartitionOptions options, PriorScaleType scaleType, double maintainedSum, boolean amtk) { return new Parameter.Builder(name, description).scaleType(scaleType).prior(PriorType.DIRICHLET_PRIOR) .isNonNegative(true).maintainedSum(maintainedSum) .isAdaptiveMultivariateCompatible(amtk) .partitionOptions(options).build(parameters); } public Parameter createNonNegativeParameterInfinitePrior(String name, String description, PriorScaleType scaleType, double initial) { return createNonNegativeParameterInfinitePrior(name, description, null, scaleType, initial, false); } public Parameter createNonNegativeParameterInfinitePrior(String name, String description, PriorScaleType scaleType, double initial, boolean amtk) { return createNonNegativeParameterInfinitePrior(name, description, null, scaleType, initial, amtk); } public Parameter createNonNegativeParameterInfinitePrior(String name, String description, PartitionOptions options, PriorScaleType scaleType, double initial, boolean amtk) { return new Parameter.Builder(name, description).scaleType(scaleType).prior(PriorType.NONE_IMPROPER).isNonNegative(true) .partitionOptions(options).initial(initial).isAdaptiveMultivariateCompatible(amtk).build(parameters); } public Parameter createNonNegativeParameterUniformPrior(String name, String description, PriorScaleType scaleType, double initial, double uniformLower, double uniformUpper) { return new Parameter.Builder(name, description).scaleType(scaleType).prior(PriorType.UNIFORM_PRIOR).isNonNegative(true) .initial(initial).uniformLower(uniformLower).uniformUpper(uniformUpper).build(parameters); } public Parameter createParameterUniformPrior(String name, String description, PriorScaleType scaleType, double initial, double uniformLower, double uniformUpper) { return new Parameter.Builder(name, description).scaleType(scaleType).prior(PriorType.UNIFORM_PRIOR) .initial(initial).uniformLower(uniformLower).uniformUpper(uniformUpper).build(parameters); } public Parameter createParameterGammaPrior(String name, String description, PriorScaleType scaleType, double initial, double shape, double scale, boolean priorFixed) { return createParameterGammaPrior(name, description, scaleType, initial, shape, scale, priorFixed, false); } public Parameter createParameterGammaPrior(String name, String description, PriorScaleType scaleType, double initial, double shape, double scale, boolean priorFixed, boolean amtk) { return new Parameter.Builder(name, description).scaleType(scaleType).prior(PriorType.GAMMA_PRIOR) .initial(initial).shape(shape).scale(scale).isNonNegative(true).isPriorFixed(priorFixed). isAdaptiveMultivariateCompatible(amtk) .build(parameters); } public Parameter createCachedGammaPrior(String name, String description, PriorScaleType scaleType, double initial, double shape, double scale, boolean priorFixed) { return new Parameter.Builder(name, description).scaleType(scaleType).prior(PriorType.GAMMA_PRIOR).initial(initial) .shape(shape).scale(scale).isNonNegative(true).isPriorFixed(priorFixed).isCached(true).build(parameters); } public Parameter createParameterOneOverXPrior(String name, String description, PriorScaleType scaleType, double initial) { return new Parameter.Builder(name, description).scaleType(scaleType).prior(PriorType.ONE_OVER_X_PRIOR) .initial(initial).isNonNegative(true).build(parameters); } public Parameter createParameterExponentialPrior(String name, String description, PriorScaleType scaleType, double initial, double mean, double offset) { return createParameterExponentialPrior(name, description, scaleType, initial, mean, offset, false); } public Parameter createParameterExponentialPrior(String name, String description, PriorScaleType scaleType, double initial, double mean, double offset, boolean amtk) { return new Parameter.Builder(name, description).scaleType(scaleType).prior(PriorType.EXPONENTIAL_PRIOR) .initial(initial).mean(mean).offset(offset).isNonNegative(true).isAdaptiveMultivariateCompatible(amtk).build(parameters); } public Parameter createParameterLognormalPrior(String name, String description, PriorScaleType scaleType, double initial, double mean, double stdev, double offset) { return createParameterLognormalPrior(name, description, scaleType, initial, mean, stdev, offset, false); } public Parameter createParameterLognormalPrior(String name, String description, PriorScaleType scaleType, double initial, double mean, double stdev, double offset, boolean amtk) { return new Parameter.Builder(name, description).scaleType(scaleType).prior(PriorType.LOGNORMAL_PRIOR) .initial(initial).mean(mean).stdev(stdev).offset(offset).isNonNegative(true) .isAdaptiveMultivariateCompatible(amtk) .build(parameters); } public Parameter createParameterNormalPrior(String name, String description, PriorScaleType scaleType, double initial, double mean, double stdev, double offset) { return createParameterNormalPrior(name, description, scaleType, initial, mean, stdev, offset, false); } public Parameter createParameterNormalPrior(String name, String description, PriorScaleType scaleType, double initial, double mean, double stdev, double offset, boolean amtk) { return new Parameter.Builder(name, description).scaleType(scaleType).prior(PriorType.NORMAL_PRIOR) .initial(initial).mean(mean).stdev(stdev).offset(offset).isAdaptiveMultivariateCompatible(amtk) .build(parameters); } public Parameter createParameterLaplacePrior(String name, String description, PriorScaleType scaleType, double initial, double mean, double scale) { return new Parameter.Builder(name, description).scaleType(scaleType).prior(PriorType.LAPLACE_PRIOR) .initial(initial).mean(mean).scale(scale).build(parameters); } public Parameter createParameterBetaDistributionPrior(String name, String description, double initial, double shape, double shapeB, double offset) { return new Parameter.Builder(name, description).prior(PriorType.BETA_PRIOR).initial(initial) .isZeroOne(true).shape(shape).shapeB(shapeB).offset(offset).build(parameters); } public Parameter createDuplicate(String name, String description, Parameter source) { return new Parameter.Builder(name, description).duplicate(source).build(parameters); } //+++++++++++++++++++ Create Statistic ++++++++++++++++++++++++++++++++ public Parameter createDiscreteStatistic(String name, String description) { // Poisson Prior return new Parameter.Builder(name, description).isDiscrete(true).isStatistic(true) .prior(PriorType.POISSON_PRIOR).mean(Math.log(2)).build(parameters); } protected Parameter createStatistic(String name, String description) { return new Parameter.Builder(name, description).isStatistic(true).prior(PriorType.NONE_STATISTIC).build(parameters); } protected Parameter createNonNegativeStatistic(String name, String description) { return new Parameter.Builder(name, description).isStatistic(true).prior(PriorType.NONE_STATISTIC).isNonNegative(true).build(parameters); } //+++++++++++++++++++ Create Operator ++++++++++++++++++++++++++++++++ public Operator createOperator(String parameterName, OperatorType type, double tuning, double weight) { Parameter parameter = getParameter(parameterName); return new Operator.Builder(parameterName, parameterName, parameter, type, tuning, weight) .build(operators); } public Operator createOperator(String parameterName, OperatorType type, double tuning, double weight, boolean autoOptimize) { Parameter parameter = getParameter(parameterName); return new Operator.Builder(parameterName, parameterName, parameter, type, tuning, weight) .autoOptimize(autoOptimize) .build(operators); } public Operator createScaleOperator(String parameterName, double tuning, double weight) { Parameter parameter = getParameter(parameterName); String description; if (parameter.getDescription() == null) { description = parameterName; } else { description = parameter.getDescription(); } return new Operator.Builder(parameterName, description, parameter, OperatorType.SCALE, tuning, weight). build(operators); } public Operator createScaleOperator(String parameterName, String description, double tuning, double weight) { Parameter parameter = getParameter(parameterName); return new Operator.Builder(parameterName, description, parameter, OperatorType.SCALE, tuning, weight).build(operators); } // public void createScaleAllOperator(String parameterName, double tuning, double weight) { // tuning = 0.75 // Parameter parameter = getParameter(parameterName); // new Operator.Builder(parameterName, parameterName, parameter, OperatorType.SCALE_ALL, tuning, weight).build(operators); // } public Operator createOperator(String key, String name, String description, String parameterName, OperatorType type, double tuning, double weight) { Parameter parameter = null; if (parameterName != null) { parameter = getParameter(parameterName); } return operators.put(key, new Operator.Builder(name, description, parameter, type, tuning, weight).build()); // key != name } public Operator createOperatorUsing2Parameters(String key, String name, String description, String parameterName1, String parameterName2, OperatorType type, double tuning, double weight) { Parameter parameter1 = getParameter(parameterName1); Parameter parameter2 = getParameter(parameterName2); return operators.put(key, new Operator.Builder(name, description, parameter1, type, tuning, weight).parameter2(parameter2).build()); } public Operator createUpDownOperator(String key, String name, String description, Parameter parameter1, Parameter parameter2, OperatorType type, boolean isPara1Up, double tuning, double weight) { if (isPara1Up) { return operators.put(key, new Operator.Builder(name, description, parameter1, type, tuning, weight) .parameter2(parameter2).build()); } else { return operators.put(key, new Operator.Builder(name, description, parameter2, type, tuning, weight) .parameter2(parameter1).build()); } } public Operator createBitFlipInSubstitutionModelOperator(String key, String name, String description, Parameter parameter, PartitionOptions options, double tuning, double weight) { // Parameter parameter = getParameter(parameterName); return operators.put(key, new Operator.Builder(name, description, parameter, OperatorType.BITFIP_IN_SUBST, tuning, weight) .partitionOptions(options).build()); } public Operator createUpDownAllOperator(String paraName, String opName, String description, double tuning, double weight) { final Parameter parameter = new Parameter.Builder(paraName, description).build(); return operators.put(paraName, new Operator.Builder(opName, description, parameter, OperatorType.UP_DOWN_ALL_RATES_HEIGHTS, tuning, weight).build()); }//TODO a switch like createUpDownOperator? public Operator createDuplicate(String name, String description, Parameter parameter, Operator source) { return new Operator.Builder(name, description, parameter, source.getOperatorType(), source.getTuning(), source.getWeight()).build(operators); } //+++++++++++++++++++ Methods ++++++++++++++++++++++++++++++++ public Parameter getParameter(String name) { Parameter parameter = parameters.get(name); if (parameter == null) { for (String key : parameters.keySet()) { System.err.println(key); } throw new IllegalArgumentException("Parameter with name, " + name + ", is unknown"); } return parameter; } public boolean parameterExists(String name) { Parameter parameter = parameters.get(name); return parameter != null; } public Parameter getStatistic(TaxonList taxonList) { Parameter parameter = statistics.get(taxonList); if (parameter == null) { for (TaxonList key : statistics.keySet()) { System.err.println("Taxon list: " + key.getId()); } throw new IllegalArgumentException("Statistic for taxon list, " + taxonList.getId() + ", is unknown"); } return parameter; } public Operator getOperator(String name) { Operator operator = operators.get(name); if (operator == null) { throw new IllegalArgumentException("Operator with name, " + name + ", is unknown"); } return operator; } protected void addComponent(ComponentOptions component) { components.add(component); component.createParameters(this); } protected boolean hasComponent(ComponentFactory factory) { for (ComponentOptions component : components) { if (factory.getOptionsClass().isAssignableFrom(component.getClass())) { return true; } } return false; } public ComponentOptions getComponentOptions(Class<?> theClass) { for (ComponentOptions component : components) { if (theClass.isAssignableFrom(component.getClass())) { return component; } } throw new IllegalArgumentException("A component options of class, " + theClass.toString() + ", has not been registered"); } protected void selectComponentParameters(ModelOptions options, List<Parameter> params) { for (ComponentOptions component : components) { component.selectParameters(options, params); } } protected void selectComponentStatistics(ModelOptions options, List<Parameter> stats) { for (ComponentOptions component : components) { component.selectStatistics(options, stats); } } protected void selectComponentOperators(ModelOptions options, List<Operator> ops) { for (ComponentOptions component : components) { component.selectOperators(options, ops); } } public Map<String, Parameter> getParameters() { return parameters; } public Map<TaxonList, Parameter> getStatistics() { return statistics; } public Map<String, Operator> getOperators() { return operators; } public String noDuplicatedPrefix(String a , String b) { if (a.equals(b)) { return a; } else { return a + b; } } }