gt:             new XMLSyntaxRule[] {
context: /*
   * MarkovJumpsTreeLikelihoodParser.java
   *
   * Copyright (c) 2002-2016 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.evomodelxml.treelikelihood;
  
  import dr.evolution.tree.MutableTreeModel;
  import dr.evomodel.branchmodel.BranchModel;
  import dr.evomodel.siteratemodel.GammaSiteRateModel;
  import dr.evomodel.substmodel.FrequencyModel;
  import dr.evomodel.substmodel.SubstitutionModel;
  import dr.evomodel.treelikelihood.BeagleTreeLikelihood;
  import dr.evomodel.treelikelihood.MarkovJumpsBeagleTreeLikelihood;
  import dr.evomodel.treelikelihood.PartialsRescalingScheme;
  import dr.evolution.alignment.PatternList;
  import dr.evolution.datatype.DataType;
  import dr.evolution.util.TaxonList;
  import dr.evomodel.branchratemodel.BranchRateModel;
  import dr.evomodel.tipstatesmodel.TipStatesModel;
  import dr.inference.markovjumps.MarkovJumpsRegisterAcceptor;
  import dr.inference.markovjumps.MarkovJumpsType;
  import dr.inference.model.Parameter;
  import dr.xml.*;
  
  import java.util.Map;
  import java.util.Set;
  
  /**
   * @author Marc Suchard
   */
  
  public class MarkovJumpsTreeLikelihoodParser extends AncestralStateTreeLikelihoodParser {
  
      public static final String MARKOV_JUMP_TREE_LIKELIHOOD = "markovJumpsTreeLikelihood";
      public static final String JUMP_TAG = "jumps";
      public static final String JUMP_TAG_NAME = "jumpTagName";
      public static final String COUNTS = MarkovJumpsType.COUNTS.getText();
      public static final String REWARDS = MarkovJumpsType.REWARDS.getText();
      public static final String SCALE_REWARDS = "scaleRewardsByTime";
      public static final String USE_UNIFORMIZATION = "useUniformization";
      public static final String SAVE_HISTORY = "saveCompleteHistory";
      public static final String LOG_HISTORY = "logCompleteHistory";
      public static final String COMPACT_HISTORY = "compactHistory";
      public static final String NUMBER_OF_SIMULANTS = "numberOfSimulants";
      public static final String REPORT_UNCONDITIONED_COLUMNS = "reportUnconditionedValues";
  
  
      public String getParserName() {
          return MARKOV_JUMP_TREE_LIKELIHOOD;
      }
  
      protected BeagleTreeLikelihood createTreeLikelihood(PatternList patternList, MutableTreeModel treeModel,
                                                          BranchModel branchModel,
                                                          GammaSiteRateModel siteRateModel,
                                                          BranchRateModel branchRateModel,
                                                          TipStatesModel tipStatesModel,
                                                          boolean useAmbiguities, PartialsRescalingScheme scalingScheme,
                                                          boolean delayScaling,
                                                          Map<Set<String>, Parameter> partialsRestrictions,
                                                          XMLObject xo) throws XMLParseException {
  
          DataType dataType = branchModel.getRootSubstitutionModel().getDataType();
  
          String stateTag = xo.getAttribute(RECONSTRUCTION_TAG_NAME,RECONSTRUCTION_TAG);
          String jumpTag = xo.getAttribute(JUMP_TAG_NAME, JUMP_TAG);
  
          boolean scaleRewards = xo.getAttribute(SCALE_REWARDS,true);
  
          boolean useMAP = xo.getAttribute(MAP_RECONSTRUCTION, false);
          boolean useMarginalLogLikelihood = xo.getAttribute(MARGINAL_LIKELIHOOD, true);
          boolean conditionalProbabilitiesInLogSpace = xo.getAttribute(CONDITIONAL_PROBABILITIES_IN_LOG_SPACE, false);
  
  
          boolean useUniformization = xo.getAttribute(USE_UNIFORMIZATION, false);
          boolean reportUnconditionedColumns = xo.getAttribute(REPORT_UNCONDITIONED_COLUMNS, false);
          int nSimulants = xo.getAttribute(NUMBER_OF_SIMULANTS, 1);
  
          if (patternList.areUnique()) {
              throw new XMLParseException("Markov Jumps reconstruction cannot be used with compressed (unique) patterns.");
          }
  
          MarkovJumpsBeagleTreeLikelihood treeLikelihood = new MarkovJumpsBeagleTreeLikelihood(
                  patternList,
                  treeModel,
                  branchModel,
                  siteRateModel,
                  branchRateModel,
                  tipStatesModel,
                  useAmbiguities,
                  scalingScheme,
                  delayScaling,
                  partialsRestrictions,
                  dataType,
                  stateTag,
                  useMAP,
                  useMarginalLogLikelihood,
                  useUniformization,
                  reportUnconditionedColumns,
                  nSimulants,
                  conditionalProbabilitiesInLogSpace
          );
  
          int registersFound = parseAllChildren(xo, treeLikelihood, dataType.getStateCount(), jumpTag,
                  MarkovJumpsType.COUNTS, false); // For backwards compatibility
  
          XMLObject cxo = xo.getChild(COUNTS);
          if (cxo != null) {
              registersFound += parseAllChildren(cxo, treeLikelihood, dataType.getStateCount(), jumpTag,
                      MarkovJumpsType.COUNTS, false);
          }
  
          cxo = xo.getChild(REWARDS);
          if (cxo != null) {
              registersFound += parseAllChildren(cxo, treeLikelihood, dataType.getStateCount(), jumpTag,
                      MarkovJumpsType.REWARDS, scaleRewards);
          }
  
          if (registersFound == 0) { // Some default values for testing
  //            double[] registration = new double[dataType.getStateCount()*dataType.getStateCount()];
  //            MarkovJumpsCore.fillRegistrationMatrix(registration,dataType.getStateCount()); // Count all transitions
  //            Parameter registerParameter = new Parameter.Default(registration);
  //            registerParameter.setId(jumpTag);
  //            treeLikelihood.addRegister(registerParameter,
  //                                       MarkovJumpsType.COUNTS,
  //                                       false);
              // Do nothing, should run the same as AncestralStateBeagleTreeLikelihood
          }
  
          boolean saveCompleteHistory = xo.getAttribute(SAVE_HISTORY, false);
          if (saveCompleteHistory) {
              Parameter allCounts = new Parameter.Default(dataType.getStateCount() * dataType.getStateCount());
              for (int i = 0; i < dataType.getStateCount(); ++i) {
                  for (int j = 0; j < dataType.getStateCount(); ++j) {
                      if (j == i) {
                          allCounts.setParameterValue(i * dataType.getStateCount() + j, 0.0);
                      } else {
                          allCounts.setParameterValue(i * dataType.getStateCount() + j, 1.0);
                      }
                  }
              }
              allCounts.setId(MarkovJumpsBeagleTreeLikelihood.TOTAL_COUNTS);
              treeLikelihood.setLogHistories(xo.getAttribute(LOG_HISTORY, false));
              treeLikelihood.setUseCompactHistory(xo.getAttribute(COMPACT_HISTORY, false));
              treeLikelihood.addRegister(allCounts, MarkovJumpsType.HISTORY, false);
          }
  
          return treeLikelihood;
      }
  
      public static int parseAllChildren(XMLObject xo,
                                         MarkovJumpsRegisterAcceptor acceptor,
                                         int stateCount,
                                         String jumpTag,
                                         MarkovJumpsType type,
                                         boolean scaleRewards) throws XMLParseException {
          int registersFound = 0;
          for(int i = 0; i < xo.getChildCount(); i++) {
              Object obj = xo.getChild(i);
              if (obj instanceof Parameter) {
                  Parameter registerParameter = (Parameter) obj;
                  if (type == MarkovJumpsType.COUNTS &&
                          registerParameter.getDimension() != stateCount * stateCount) {
                      if (registerParameter. getDimension() == 1) {
                          // if the dimension hasn't been set then default to counting all jumps
                          registerParameter.setDimension(stateCount * stateCount);
                          for (int j = 0; j < stateCount; j++) {
                              for (int k = 0; k < stateCount; k++) {
                                  registerParameter.setParameterValueQuietly((j * stateCount) + k,  (j == k ? 0.0 : 1.0));
                              }
                          }
                      } else {
                          throw new XMLParseException("Markov Jumps register parameter " + registerParameter.getId() + " is of the wrong dimension");
                      }
                  }
                  if (type == MarkovJumpsType.REWARDS &&
                          registerParameter.getDimension() != stateCount) {
                      if (registerParameter.getDimension() == 1) {
                          // if the dimension hasn't been set then default to getting rewards for all states
                          registerParameter.setDimension(stateCount);
                          for (int j = 0; j < stateCount; j++) {
                              registerParameter.setParameterValueQuietly(j, 1.0);
                          }
                      } else {
                          throw new XMLParseException("Markov Rewards register parameter " + registerParameter.getId() + " is of the wrong dimension");
                      }
                  }
  
                  if (registerParameter.getId() == null) {
                      registerParameter.setId(jumpTag+(registersFound+1));
                  }
                  acceptor.addRegister(registerParameter, type, scaleRewards);
                  registersFound++;
              }
          }
          return registersFound;
      }
  
      public static XMLSyntaxRule[]  rules =
  