gt:             return new String[]{
context: /*
   * ARGPartitioningOperator.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.evomodel.arg.operators;
  
  import dr.evomodel.arg.ARGModel;
  import dr.inference.model.CompoundParameter;
  import dr.inference.model.Parameter;
  import dr.inference.operators.OperatorFailedException;
  import dr.inference.operators.SimpleMCMCOperator;
  import dr.math.MathUtils;
  import dr.xml.*;
  
  import java.util.ArrayList;
  import java.util.logging.Logger;
  
  public class ARGPartitioningOperator extends SimpleMCMCOperator {
  
      private final CompoundParameter partitioningParameters;
      private final ARGModel arg;
  
      public final static String OPERATOR_NAME = "argPartitionOperator";
      public static final String TOSS_SIZE = "tossSize";
      public static final String TOSS_ALL = "tossAll";
  
      private final boolean tossAll;
      private final boolean isRecombination;
      private final int tossSize;
  
      public ARGPartitioningOperator(ARGModel arg, int tossSize, int weight, boolean tossAll) {
          super.setWeight(weight);
  
          this.arg = arg;
          this.partitioningParameters = arg.getPartitioningParameters();
          this.tossSize = tossSize;
          this.isRecombination = arg.isRecombinationPartitionType();
          
          this.tossAll = tossAll;
      }
  
      /**
       * @return the parameter this operator acts on.
       */
      public Parameter getParameter() {
          return partitioningParameters;
      }
  
  
      public final double doOperation() throws OperatorFailedException {
          double logq = 0;
  
          final int len = partitioningParameters.getParameterCount();
  
          if (len == 0) {
              return 0;
          }
  
          boolean[] updatePartition = new boolean[arg.getNumberOfPartitions()];
  
          if(tossAll){
          	for(int i = 0 ; i < len; i++){
          		logq += doFlip(i,updatePartition);
              }	
          }else{
          	logq = doFlip(MathUtils.nextInt(len),updatePartition);
          }
  
          arg.fireModelChanged(new PartitionChangedEvent(partitioningParameters, updatePartition));
          return logq;
      }
      
      private double doFlip(int i, boolean[] updatePartition) throws OperatorFailedException {
      	if (isRecombination) {
              return doRecombination(partitioningParameters.getParameter(i),updatePartition);
          } 
          
      	return doReassortment(partitioningParameters.getParameter(i),updatePartition);
          
      }
  
  
      private double doRecombination(Parameter partition, boolean[] updatePartition) throws OperatorFailedException {
  
          assert checkValidRecombinationPartition(partition);
  
          int currentBreakLocation = 0;
          for (int i = 0, n = arg.getNumberOfPartitions(); i < n; i++) {
              if (partition.getParameterValue(i) == 1) {
                  currentBreakLocation = i;
                  break;
              }
          }
  
          assert currentBreakLocation > 0;
  
          if (MathUtils.nextBoolean()) {
              //Move break right 1
              partition.setParameterValueQuietly(currentBreakLocation, 0.0);
              updatePartition[currentBreakLocation] = true;
          } else {
              partition.setParameterValueQuietly(currentBreakLocation - 1, 1.0);
              updatePartition[currentBreakLocation-1] = true;
          }
  
          if (!checkValidRecombinationPartition(partition)) {
              throw new OperatorFailedException("");
          }
  
  
          return 0;
      }
  
      public static boolean checkValidRecombinationPartition(Parameter partition) {
          int l = partition.getDimension();
  //        if ((partition.getParameterValue(0) == 0 && partition.getParameterValue(l - 1) == 1))
  //            return true;
  //
  //        return false;
          return (partition.getParameterValue(0) == 0 && partition.getParameterValue(l - 1) == 1);
      }
  
  
      private double doReassortment(Parameter partition, boolean[] updatePartition) throws OperatorFailedException {
  
          assert checkValidReassortmentPartition(partition);
  
          ArrayList<Integer> list = new ArrayList<Integer>(tossSize);
  
          while (list.size() < tossSize) {
              int a = MathUtils.nextInt(arg.getNumberOfPartitions() - 1) + 1;
              if (!list.contains(a)) {
                  list.add(a);
              }
          }
  
  
          for (int a : list) {
              if (partition.getParameterValue(a) == 0) {
                  partition.setParameterValueQuietly(a, 1);
              } else {
                  partition.setParameterValueQuietly(a, 0);
              }
              updatePartition[a] = true;            
          }
          
          
          if (!checkValidReassortmentPartition(partition)) {
              throw new OperatorFailedException("");
          }
  
          return 0;
      }
  
      public static boolean checkValidReassortmentPartition(Parameter partition) {
          if (partition.getParameterValue(0) != 0)
              return false;
  
          double[] a = partition.getParameterValues();
  
          double sum = 0;
  
          for (double b : a)
              sum += b;
  
  //        if (sum == 0 || sum == a.length)
  //            return false;
  //
  //        return true;
          return !(sum == 0 || sum == a.length);
  
      }
  
      @Override
      public String getOperatorName() {
          return OPERATOR_NAME;
      }
  
      public String getPerformanceSuggestion() {
          return null;
      }
  
      public class PartitionChangedEvent {
          Parameter partitioning;
          boolean[] updatePartition;
  
          public PartitionChangedEvent(Parameter partitioning, boolean[] updatePartition) {
              this.partitioning = partitioning;
              this.updatePartition = updatePartition;
          }
  
          public Parameter getParameter() {
              return partitioning;
          }
  
          public boolean[] getUpdatedPartitions() {
              return updatePartition;
          }
      }
  
      public static dr.xml.XMLObjectParser PARSER = new dr.xml.AbstractXMLObjectParser() {
  
          public String getParserName() {
              return OPERATOR_NAME;
          }
  
          public String[] getParserNames() {
  