/* Copyright (C) 2009 Diego Darriba This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package es.uvigo.darwin.prottest.util.collection; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Properties; import pal.alignment.Alignment; import pal.tree.Tree; import es.uvigo.darwin.prottest.model.Model; import es.uvigo.darwin.prottest.util.comparator.ModelWeightComparator; /** * A complex implementation of model collection, which is able to * distribute whole set of substitution models amongst a certain * number of groups, generally amongst the number of processors. * * This class is a composition of model collections, that will have * disjunction and completeness properties. */ public class ParallelModelCollection extends ModelCollection { /** The serialVersionUID. */ private static final long serialVersionUID = 20090903L; /** The list of model collections. */ private List<ModelCollection> modelCollections; /** The number of groups. */ private int groups; /** Defines if the current distribution is valid. */ private boolean validDistribution = false; /** The heuristic algorithm to compare models. */ private ModelWeightComparator comparator; /** * Instantiates a new parallel model collection. * * @param allModels the whole set of models * @param groups the number of groups, typically the size of the MPJ communicator */ public ParallelModelCollection(Model[] allModels, int groups, ModelWeightComparator comparator, Alignment alignment) { super(alignment); ArrayList<Model> models = new ArrayList<Model>(Arrays.asList(allModels)); this.comparator = comparator; Collections.sort(models, comparator); initialize(models, groups); } /** * Instantiates a new parallel model collection. * * @param allModels the whole set of models. * @param groups the number of groups, typically the size of the MPJ communicator */ public ParallelModelCollection(ModelCollection allModels, int groups, ModelWeightComparator comparator) { super(allModels.getAlignment()); List<Model> models = new ArrayList<Model>(allModels); this.comparator = comparator; Collections.sort(models, comparator); initialize(models, groups); } /** * Initialize. * * @param allModels the whole set of models * @param groups the number of groups, typically the size of the MPJ communicator */ private void initialize(List<Model> allModels, int groups) { this.allModels = allModels; this.groups = groups; modelCollections = new ArrayList<ModelCollection>(); distributeModels(this.allModels, this.groups); } /** * Distribute models amongst groups. This method grants completeness * and disjunction of single collections. * * @param allModels the whole set of models. * @param groups the number of groups to distribute models into */ private void distributeModels(List<Model> allModels, int groups) { modelCollections.clear(); // initialize for (int i = 0; i < groups; i++) modelCollections.add(new SingleModelCollection(getAlignment())); int maxWeight = 1; int currentGroup = 0; boolean modelAdded = false; for (Model model : allModels) { modelAdded = false; ModelCollection minModelGroup = modelCollections.get(0); for (currentGroup = 0; currentGroup < groups; currentGroup++) { ModelCollection currentModelGroup = modelCollections.get(currentGroup); if (currentModelGroup.getWeight(comparator) + comparator.getWeight(model) <= maxWeight) { modelAdded = currentModelGroup.addModel(model); maxWeight = currentModelGroup.getWeight(comparator); break; } else if (currentModelGroup.getWeight(comparator) < minModelGroup.getWeight(comparator)) minModelGroup = currentModelGroup; } if (!modelAdded) { minModelGroup.addModel(model); maxWeight = minModelGroup.getWeight(comparator); } } validDistribution = true; } /** * Gets a single model collection. This method will return null * if the group parameter is out of rank. * * @param group the group * * @return the model iterator */ public ModelCollection getModelCollection(int group) { if (!validDistribution) distributeModels(this.allModels, this.groups); if (group < 0 || group > groups) return null; return modelCollections.get(group); } /* (non-Javadoc) * @see java.util.List#add(int, java.lang.Object) */ @Override public void add(int index, Model element) { validDistribution = false; super.add(index, element); } /* (non-Javadoc) * @see es.uvigo.darwin.prottest.util.collection.ModelCollection#add(es.uvigo.darwin.prottest.model.Model) */ @Override public boolean add(Model e) { validDistribution = false; return super.add(e); } /* (non-Javadoc) * @see es.uvigo.darwin.prottest.util.collection.ModelCollection#addModel(java.lang.String, int, java.util.Properties) */ @Override public boolean addModel(String matrix, int distribution, Properties modelProperties, Alignment alignment, Tree tree, int ncat) { validDistribution = false; return super.addModel(matrix, distribution, modelProperties, alignment, tree, ncat); } /* (non-Javadoc) * @see es.uvigo.darwin.prottest.util.collection.ModelCollection#addModel(es.uvigo.darwin.prottest.model.Model) */ @Override public boolean addModel(Model model) { validDistribution = false; return super.addModel(model); } /* (non-Javadoc) * @see es.uvigo.darwin.prottest.util.collection.ModelCollection#addModelCartesian(java.util.Collection, java.util.Collection, java.util.Properties) */ @Override public boolean addModelCartesian(Collection<String> matrices, Collection<Integer> distributions, Properties modelProperties, Alignment alignment, Tree tree, int ncat) { validDistribution = false; return super.addModelCartesian(matrices, distributions, modelProperties, alignment, tree, ncat); } /* (non-Javadoc) * @see es.uvigo.darwin.prottest.util.collection.ModelCollection#addAll(java.util.Collection) */ @Override public boolean addAll(Collection<? extends Model> c) { validDistribution = false; return super.addAll(c); } /* (non-Javadoc) * @see es.uvigo.darwin.prottest.util.collection.ModelCollection#addAll(int, java.util.Collection) */ @Override public boolean addAll(int index, Collection<? extends Model> c) { validDistribution = false; return super.addAll(index, c); } /* (non-Javadoc) * @see es.uvigo.darwin.prottest.util.collection.ModelCollection#clear() */ @Override public void clear() { validDistribution = false; super.clear(); } /* (non-Javadoc) * @see es.uvigo.darwin.prottest.util.collection.ModelCollection#remove(java.lang.Object) */ @Override public boolean remove(Object o) { validDistribution = false; return super.remove(o); } /* (non-Javadoc) * @see es.uvigo.darwin.prottest.util.collection.ModelCollection#remove(int) */ @Override public Model remove(int index) { validDistribution = false; return super.remove(index); } /* (non-Javadoc) * @see es.uvigo.darwin.prottest.util.collection.ModelCollection#removeAll(java.util.Collection) */ @Override public boolean removeAll(Collection<?> c) { validDistribution = false; return super.removeAll(c); } /* (non-Javadoc) * @see es.uvigo.darwin.prottest.util.collection.ModelCollection#set(int, es.uvigo.darwin.prottest.model.Model) */ @Override public Model set(int index, Model element) { validDistribution = false; return super.set(index, element); } }