Java tutorial
/******************************************************************************* * Copyright (C) 2006-2014 AITIA International, Inc. * * 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 3 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, see <http://www.gnu.org/licenses/>. ******************************************************************************/ package ai.aitia.meme.paramsweep.intellisweepPlugin; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import javax.swing.JPanel; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.MutableTreeNode; import org.apache.commons.math3.random.MersenneTwister; import org.jgap.Chromosome; import org.jgap.Configuration; import org.jgap.FitnessEvaluator; import org.jgap.FitnessFunction; import org.jgap.Gene; import org.jgap.Genotype; import org.jgap.IChromosome; import org.jgap.InvalidConfigurationException; import org.jgap.Population; import org.jgap.RandomGenerator; import org.jgap.impl.DefaultConfiguration; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Text; import ai.aitia.meme.Logger; import ai.aitia.meme.paramsweep.batch.IParameterSweepResultReader; import ai.aitia.meme.paramsweep.batch.ReadingException; import ai.aitia.meme.paramsweep.batch.ResultValueInfo; import ai.aitia.meme.paramsweep.batch.output.RecordableInfo; import ai.aitia.meme.paramsweep.batch.param.ParameterTree; import ai.aitia.meme.paramsweep.generator.WizardSettingsManager; import ai.aitia.meme.paramsweep.gui.info.MasonChooserParameterInfo; import ai.aitia.meme.paramsweep.gui.info.ParameterInfo; import ai.aitia.meme.paramsweep.gui.info.RecordableElement; import ai.aitia.meme.paramsweep.gui.info.ResultInfo; import ai.aitia.meme.paramsweep.intellisweepPlugin.jgap.GASearchPanel; import ai.aitia.meme.paramsweep.intellisweepPlugin.jgap.GASearchPanelModel; import ai.aitia.meme.paramsweep.intellisweepPlugin.jgap.IntelliBreeder; import ai.aitia.meme.paramsweep.intellisweepPlugin.jgap.configurator.BestChromosomeSelectorConfigurator; import ai.aitia.meme.paramsweep.intellisweepPlugin.jgap.configurator.CrossoverOperatorConfigurator; import ai.aitia.meme.paramsweep.intellisweepPlugin.jgap.configurator.GeneAveragingCrossoverOperatorConfigurator; import ai.aitia.meme.paramsweep.intellisweepPlugin.jgap.configurator.IGAOperatorConfigurator; import ai.aitia.meme.paramsweep.intellisweepPlugin.jgap.configurator.IGASelectorConfigurator; import ai.aitia.meme.paramsweep.intellisweepPlugin.jgap.configurator.MutationOperatorConfigurator; import ai.aitia.meme.paramsweep.intellisweepPlugin.jgap.configurator.TournamentSelectorConfigurator; import ai.aitia.meme.paramsweep.intellisweepPlugin.jgap.configurator.WeightedRouletteSelectorConfigurator; import ai.aitia.meme.paramsweep.intellisweepPlugin.jgap.gene.IIdentifiableGene; import ai.aitia.meme.paramsweep.intellisweepPlugin.jgap.gene.IdentifiableBooleanGene; import ai.aitia.meme.paramsweep.intellisweepPlugin.jgap.gene.IdentifiableDoubleGene; import ai.aitia.meme.paramsweep.intellisweepPlugin.jgap.gene.IdentifiableListGene; import ai.aitia.meme.paramsweep.intellisweepPlugin.jgap.gene.IdentifiableLongGene; import ai.aitia.meme.paramsweep.intellisweepPlugin.jgap.gene.ParameterOrGene; import ai.aitia.meme.paramsweep.intellisweepPlugin.jgap.operator.StandardPostSelectorFixed; import ai.aitia.meme.paramsweep.intellisweepPlugin.utils.ga.GeneInfo; import ai.aitia.meme.paramsweep.internal.platform.InfoConverter; import ai.aitia.meme.paramsweep.plugin.IIntelliContext; import ai.aitia.meme.paramsweep.plugin.IIntelliDynamicMethodPlugin; import ai.aitia.meme.paramsweep.utils.WizardLoadingException; public class JgapGAPlugin implements IIntelliDynamicMethodPlugin, GASearchPanelModel { //==================================================================================================== // members private static final long serialVersionUID = 2516082442494840822L; private static final String GA_SETTINGS = "ga_settings"; private static final String POPULATION_SIZE = "population_size"; private static final String POPULATION_RANDOM_SEED = "population_random_seed"; private static final String FIX_NUMBER_OF_GENERATIONS = "fix_number_of_generations"; private static final String NUMBER_OF_GENERATIONS = "number_of_generations"; private static final String FITNESS_LIMIT_CRITERION = "fitness_limit"; private static final String OPTIMIZATION_DIRECTION = "optimization_direction"; private static final String FITNESS_FUNCTION = "fitness_function"; private static final String SELECTORS = "selectors"; private static final String SELECTOR = "selector"; private static final String PROPERTY = "property"; private static final String KEY = "key"; private static final String GENETIC_OPERATORS = "genetic_operators"; private static final String GENETIC_OPERATOR = "genetic_operator"; private static final String CHROMOSOME = "chromosome"; private static final String GENE = "gene"; private static final String IS_INTEGER = "is_integer"; private static final String MIN_VALUE = "min_value"; private static final String MAX_VALUE = "max_value"; private static final String LIST_VALUE = "list_value"; private static final String PARAMETER = "parameter"; protected static final String ext = ".txt"; protected static final String bckExt = ".bak"; private IIntelliContext context; private int populationSize = 12; private int populationGenerationSeed = 1; private int numberOfGenerations = 12; private double fitnessLimitCriterion = 0; private boolean fixNumberOfGenerations = true; private FitnessFunctionDirection optimizationDirection = FitnessFunctionDirection.MINIMIZE; private RecordableInfo selectedFunction; private final List<IGASelectorConfigurator> selectedSelectionOperators = new ArrayList<IGASelectorConfigurator>(); private final List<IGAOperatorConfigurator> selectedGeneticOperators = new ArrayList<IGAOperatorConfigurator>(); private DefaultConfiguration gaConfiguration; /** * The available selection operators. */ private List<IGASelectorConfigurator> selectors; /** * The available genetic operators. */ private List<IGAOperatorConfigurator> geneticOperators; /** * The list of fitness functions. */ private final List<RecordableInfo> fitnessFunctions = new ArrayList<RecordableInfo>(); private final String populationFileName = "population"; private DefaultTreeModel chromosomeTree; private List<GeneInfo> genes = null; private int iterationCounter = 1; private boolean reachFitnessLimit = false; private Genotype genotype; private List<ParameterInfo> paramList; private File workspace; private transient List<ModelListener> listeners = new ArrayList<GASearchPanelModel.ModelListener>(); private transient String readyStatusDetail; private transient GASearchPanel content = null; //==================================================================================================== // methods //---------------------------------------------------------------------------------------------------- public JgapGAPlugin() { selectors = Arrays.asList(new TournamentSelectorConfigurator(), new WeightedRouletteSelectorConfigurator(), new BestChromosomeSelectorConfigurator()); geneticOperators = Arrays.asList(new GeneAveragingCrossoverOperatorConfigurator(), new CrossoverOperatorConfigurator(), new MutationOperatorConfigurator()); init(); } //---------------------------------------------------------------------------------------------------- public String getLocalizedName() { return "Genetic Algorithm"; } public int getMethodType() { return DYNAMIC_METHOD; } public boolean isImplemented() { return true; } //---------------------------------------------------------------------------------------------------- public String getDescription() { return "The method uses genetic algorithms to find the optimal parameter settings."; } //---------------------------------------------------------------------------------------------------- private void init() { populationSize = 12; populationGenerationSeed = 1; numberOfGenerations = 12; fitnessLimitCriterion = 0; fixNumberOfGenerations = true; optimizationDirection = FitnessFunctionDirection.MINIMIZE; selectedFunction = new RecordableInfo("Please select a function!", Object.class, "Please select a function!"); selectedSelectionOperators.clear(); selectedGeneticOperators.clear(); gaConfiguration = null; fitnessFunctions.clear(); iterationCounter = 1; reachFitnessLimit = false; genotype = null; paramList = null; fitnessFunctions.add(selectedFunction); selectedSelectionOperators.add(selectors.get(2)); selectedGeneticOperators.add(geneticOperators.get(0)); selectedGeneticOperators.add(geneticOperators.get(2)); } //---------------------------------------------------------------------------------------------------- private void removeAllFitnessFunctions() { fitnessFunctions.clear(); fitnessFunctions .add(new RecordableInfo("Please select a function!", Object.class, "Please select a function!")); if (listeners != null) { for (final ModelListener listener : listeners) listener.fitnessFunctionsRemoved(); } } //---------------------------------------------------------------------------------------------------- public List<IGASelectorConfigurator> getSelectionOperators() { return selectors; } public List<RecordableInfo> getFitnessFunctions() { return fitnessFunctions; } public List<IGAOperatorConfigurator> getGeneticOperators() { return geneticOperators; } public int getPopulationSize() { return populationSize; } public int getPopulationRandomSeed() { return populationGenerationSeed; } public int getNumberOfGenerations() { return numberOfGenerations; } public double getFitnessLimitCriterion() { return fitnessLimitCriterion; } public FitnessFunctionDirection getFitnessFunctionDirection() { return optimizationDirection; } public RecordableInfo getSelectedFitnessFunction() { return selectedFunction; } public List<IGAOperatorConfigurator> getSelectedGeneticOperators() { return selectedGeneticOperators; } public List<IGASelectorConfigurator> getSelectedSelectionOperators() { return selectedSelectionOperators; } public boolean isFixNumberOfGenerations() { return fixNumberOfGenerations; } //---------------------------------------------------------------------------------------------------- public void setPopulationSize(final int populationSize) { this.populationSize = populationSize; } public void setPopulationRandomSeed(final int seed) { this.populationGenerationSeed = seed; } public void setNumberOfGenerations(final int numberOfGenerations) { this.numberOfGenerations = numberOfGenerations; } public void setFitnessLimitCriterion(final double fitnessLimit) { this.fitnessLimitCriterion = fitnessLimit; } public void setFitnessFunctionDirection(final FitnessFunctionDirection direction) { this.optimizationDirection = direction; } public void setSelectedFitnessFunction(final RecordableInfo fitnessFunction) { this.selectedFunction = fitnessFunction; } public void setFixNumberOfGenerations(final boolean fixNumberOfGenerations) { this.fixNumberOfGenerations = fixNumberOfGenerations; } //---------------------------------------------------------------------------------------------------- public DefaultTreeModel getChromosomeTree() { if (chromosomeTree == null) chromosomeTree = new DefaultTreeModel(new DefaultMutableTreeNode()); return chromosomeTree; } //---------------------------------------------------------------------------------------------------- public void setSelectedSelectionOperator(final IGASelectorConfigurator operator) { if (operator != null && !selectedSelectionOperators.contains(operator)) selectedSelectionOperators.add(operator); } //---------------------------------------------------------------------------------------------------- public boolean unsetSelectedSelectionOperator(final IGASelectorConfigurator operator) { return selectedSelectionOperators.remove(operator); } //---------------------------------------------------------------------------------------------------- public void setSelectedGeneticOperator(final IGAOperatorConfigurator operator) { if (operator != null && !selectedGeneticOperators.contains(operator)) selectedGeneticOperators.add(operator); } //---------------------------------------------------------------------------------------------------- public boolean unsetSelectedGeneticOperator(final IGAOperatorConfigurator operator) { return selectedGeneticOperators.remove(operator); } //---------------------------------------------------------------------------------------------------- public boolean addModelListener(final ModelListener listener) { if (listeners == null) { listeners = new ArrayList<>(); } return listeners.add(listener); } //---------------------------------------------------------------------------------------------------- public boolean removeModelListener(final ModelListener listener) { if (listeners == null) { listeners = new ArrayList<>(); } return listeners.remove(listener); } //---------------------------------------------------------------------------------------------------- private void addParameter(final ParameterOrGene parameterOrGene) { if (chromosomeTree == null) { chromosomeTree = new DefaultTreeModel(new DefaultMutableTreeNode()); genes = null; } final DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(parameterOrGene); final DefaultMutableTreeNode root = (DefaultMutableTreeNode) chromosomeTree.getRoot(); chromosomeTree.insertNodeInto(newNode, root, root.getChildCount()); if (listeners != null) { for (final ModelListener listener : listeners) listener.parameterAdded(); } } //---------------------------------------------------------------------------------------------------- private void removeAllParameters() { if (chromosomeTree == null) chromosomeTree = new DefaultTreeModel(new DefaultMutableTreeNode()); else chromosomeTree.setRoot(new DefaultMutableTreeNode()); genes = null; if (listeners != null) { for (final ModelListener listener : listeners) listener.parametersRemoved(); } } //---------------------------------------------------------------------------------------------------- private String[] checkGAModel() { final List<String> errors = new ArrayList<String>(); final RecordableInfo invalid = new RecordableInfo("Please select a function!", Object.class, "Please select a function!"); if (selectedFunction.equals(invalid)) errors.add("Please select a valid fitness function!"); if (selectedSelectionOperators.isEmpty()) errors.add("Please select at least one selector!"); if (selectedGeneticOperators.isEmpty()) errors.add("Please select at least one genetic operator!"); if (calculateNumberOfGenes() == 0) errors.add("Please specify at least one gene!"); return errors.size() == 0 ? null : errors.toArray(new String[0]); } //---------------------------------------------------------------------------------------------------- public int getNumberOfIterations() { if (fixNumberOfGenerations) return numberOfGenerations; else return Integer.MAX_VALUE; } //---------------------------------------------------------------------------------------------------- public int getCurrentIteration() { return iterationCounter; } //---------------------------------------------------------------------------------------------------- public boolean noMoreIteration() { if (fixNumberOfGenerations) return iterationCounter > getNumberOfGenerations(); else return reachFitnessLimit; } //---------------------------------------------------------------------------------------------------- public ParameterTree getNextParameterTree(final IParameterSweepResultReader reader) { if (iterationCounter == 1) // first time initPopFile(); iterationCounter++; ((ResultFileFitnessFunction) gaConfiguration.getFitnessFunction()).setCurrentReader(reader); printPopulation(iterationCounter - 1); if (!fixNumberOfGenerations) { final IChromosome fittestChromosome = genotype.getFittestChromosome(); final double fitnessValue = gaConfiguration.getFitnessFunction().getFitnessValue(fittestChromosome); reachFitnessLimit = optimizationDirection == FitnessFunctionDirection.MINIMIZE ? fitnessValue <= fitnessLimitCriterion : fitnessValue >= fitnessLimitCriterion; if (reachFitnessLimit) return null; } if (iterationCounter > getNumberOfGenerations()) return null; genotype.evolve(); final ParameterTree nextTree = new ParameterTree(); // this filters out duplicate chromosomes @SuppressWarnings("rawtypes") final List chromosomes = genotype.getPopulation().getChromosomes(); @SuppressWarnings("unchecked") final Set<IChromosome> descendants = new HashSet<IChromosome>(chromosomes); for (int i = 0; i < paramList.size(); ++i) { final ParameterInfo paramInfo = paramList.get(i); paramInfo.setRuns(1); // Run is always 1 final List<Object> values = new ArrayList<Object>(); final int genIdx = whichGene(paramInfo.getName()); // here we assume that the set iterates through the entries in deterministic order for (final IChromosome chromosome : descendants) { if (chromosome.getFitnessValueDirectly() == -1.0D) { // the default fitness value if (genIdx >= 0) { final String strValue = String.valueOf(chromosome.getGene(genIdx).getAllele()); values.add(ParameterInfo.getValue(strValue, paramInfo.getJavaType())); paramInfo.setDefinitionType(ParameterInfo.LIST_DEF); } else { values.add(paramInfo.getValue()); paramInfo.setDefinitionType(ParameterInfo.CONST_DEF); } } } paramInfo.setValues(values); nextTree.addNode(InfoConverter.parameterInfo2ParameterInfo(paramInfo)); } return nextTree; } //---------------------------------------------------------------------------------------------------- public boolean alterParameterTree(final IIntelliContext ctx) { // create initial population final DefaultMutableTreeNode root = ctx.getParameterTreeRootNode(); final DefaultMutableTreeNode newRoot = getAlteredParameterTreeRootNode(ctx); if (root != null) { root.removeAllChildren(); final int count = newRoot.getChildCount(); for (int i = 0; i < count; ++i) root.add((DefaultMutableTreeNode) newRoot.getChildAt(0)); } return true; } //---------------------------------------------------------------------------------------------------- protected DefaultMutableTreeNode getAlteredParameterTreeRootNode(final IIntelliContext ctx) { genotype = generateInitialPopulation(ctx); final Population descendants = genotype.getPopulation(); final DefaultMutableTreeNode root = new DefaultMutableTreeNode("Parameter file"); paramList = ctx.getParameters(); for (int i = 0; i < paramList.size(); ++i) { final ParameterInfo paramInfo = paramList.get(i); paramInfo.setRuns(1); // Run is always 1 final List<Object> values = new ArrayList<Object>(); final int genIdx = whichGene(paramInfo.getName()); if (genIdx >= 0) { for (int j = 0; j < populationSize; ++j) { final String strValue = String .valueOf(descendants.getChromosome(j).getGene(genIdx).getAllele()); values.add(ParameterInfo.getValue(strValue, paramInfo.getJavaType())); paramInfo.setDefinitionType(ParameterInfo.LIST_DEF); } } else { values.add(paramInfo.getValue()); paramInfo.setDefinitionType(ParameterInfo.CONST_DEF); } paramInfo.setValues(values); // add the node root.add(new DefaultMutableTreeNode(paramInfo)); } return root; } //---------------------------------------------------------------------------------------------------- /** * Searches the selected genes list for the specified parameter, and returns * its index. * * @param name * the parameter's name that is searched in the selected genes list * @return the index of the gene that represents the given parameter, or -1 * if the parameter is not selected as a gene */ private int whichGene(final String name) { for (int i = 0; i < genes.size(); i++) { final GeneInfo geneInfo = genes.get(i); if (geneInfo.getName().equals(name)) return i; } return -1; } //---------------------------------------------------------------------------------------------------- private List<GeneInfo> getSelectedGenes() { if (genes == null) { genes = new ArrayList<GeneInfo>(); final DefaultMutableTreeNode root = (DefaultMutableTreeNode) chromosomeTree.getRoot(); @SuppressWarnings("rawtypes") final Enumeration nodes = root.preorderEnumeration(); nodes.nextElement(); while (nodes.hasMoreElements()) { final DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodes.nextElement(); final ParameterOrGene userObj = (ParameterOrGene) node.getUserObject(); if (userObj.isGene()) { convertGeneName(userObj); genes.add(userObj.getGeneInfo()); } } } return genes; } //---------------------------------------------------------------------------------------------------- private void convertGeneName(final ParameterOrGene param) { ParameterInfo info = param.getInfo(); param.getGeneInfo().setName(info.getName()); } //---------------------------------------------------------------------------------------------------- @SuppressWarnings("serial") protected Genotype generateInitialPopulation(final IIntelliContext context) { try { iterationCounter = 1; genes = null; Configuration.reset(); gaConfiguration = new DefaultConfiguration(); Configuration.reset(); gaConfiguration.removeNaturalSelectors(true); gaConfiguration.removeNaturalSelectors(false); gaConfiguration.getGeneticOperators().clear(); gaConfiguration.setAlwaysCaculateFitness(false); gaConfiguration.setPreservFittestIndividual(true); gaConfiguration.setKeepPopulationSizeConstant(false); gaConfiguration.setFitnessEvaluator(new FitnessEvaluator() { //==================================================================================================== // methods //---------------------------------------------------------------------------------------------------- @Override public boolean isFitter(final IChromosome a_chrom1, final IChromosome a_chrom2) { return isFitter(a_chrom1.getFitnessValue(), a_chrom2.getFitnessValue()); } //---------------------------------------------------------------------------------------------------- @Override public boolean isFitter(final double a_fitness_value1, final double a_fitness_value2) { return optimizationDirection == FitnessFunctionDirection.MINIMIZE ? a_fitness_value1 < a_fitness_value2 : a_fitness_value1 > a_fitness_value2; } }); gaConfiguration.setFitnessFunction(new ResultFileFitnessFunction()); gaConfiguration.setRandomGenerator(new RandomGenerator() { //==================================================================================================== // members private static final long serialVersionUID = 1L; final MersenneTwister randomGenerator = new MersenneTwister(populationGenerationSeed); //==================================================================================================== // methods //---------------------------------------------------------------------------------------------------- public long nextLong() { return randomGenerator.nextLong(); } //---------------------------------------------------------------------------------------------------- public int nextInt(final int a_ceiling) { return randomGenerator.nextInt(a_ceiling); } //---------------------------------------------------------------------------------------------------- public int nextInt() { return randomGenerator.nextInt(); } //---------------------------------------------------------------------------------------------------- public float nextFloat() { return randomGenerator.nextFloat(); } //---------------------------------------------------------------------------------------------------- public double nextDouble() { return randomGenerator.nextDouble(); } //---------------------------------------------------------------------------------------------------- public boolean nextBoolean() { return randomGenerator.nextBoolean(); } }); final Gene[] initialGenes = new Gene[getSelectedGenes().size()]; int i = 0; for (final GeneInfo geneInfo : getSelectedGenes()) { if (GeneInfo.INTERVAL.equals(geneInfo.getValueType())) { if (geneInfo.isIntegerVals()) { initialGenes[i] = new IdentifiableLongGene(geneInfo.getName(), gaConfiguration, geneInfo.getMinValue().longValue(), geneInfo.getMaxValue().longValue()); } else { initialGenes[i] = new IdentifiableDoubleGene(geneInfo.getName(), gaConfiguration, geneInfo.getMinValue().doubleValue(), geneInfo.getMaxValue().doubleValue()); } } else if (GeneInfo.LIST.equals(geneInfo.getValueType())) { final IdentifiableListGene listGene = new IdentifiableListGene(geneInfo.getName(), gaConfiguration); final List<Object> values = geneInfo.getValueRange(); for (final Object value : values) { listGene.addAllele(value); } listGene.setAllele(values.get(0)); initialGenes[i] = listGene; } else { initialGenes[i] = new IdentifiableBooleanGene(geneInfo.getName(), gaConfiguration); } i++; } gaConfiguration.setMinimumPopSizePercent(100); gaConfiguration.setBreeder(new IntelliBreeder()); final Chromosome sampleChromosome = new Chromosome(gaConfiguration, initialGenes); gaConfiguration.setSampleChromosome(sampleChromosome); gaConfiguration.setPopulationSize(populationSize); for (final IGAOperatorConfigurator operator : selectedGeneticOperators) gaConfiguration.addGeneticOperator(operator.getConfiguredOperator(gaConfiguration)); for (final IGASelectorConfigurator selectorConfig : selectedSelectionOperators) gaConfiguration.addNaturalSelector(selectorConfig.getSelector(gaConfiguration), true); gaConfiguration.addNaturalSelector(new StandardPostSelectorFixed(gaConfiguration), false); final Genotype initialGenotype = Genotype.randomInitialGenotype(gaConfiguration); return initialGenotype; } catch (final InvalidConfigurationException e) { Logger.logException(e); throw new RuntimeException(e); } } //---------------------------------------------------------------------------------------------------- /** * Prints the header of the population file. */ protected void initPopFile() { if (workspace == null) { workspace = new File("."); } // create backup file when file already exists final File file = new File(workspace, populationFileName + ext); if (file.exists()) { for (int i = 1; i <= 1000; ++i) { final File newFile = new File(workspace, populationFileName + bckExt + i + ext); if (!newFile.exists() || i == 1000) { file.renameTo(newFile); break; } } } try { final PrintWriter popWriter = new PrintWriter(new FileWriter(file, true)); popWriter.print("#pop"); for (int i = 0; i < genes.size(); ++i) popWriter.print(";" + genes.get(i).getName()); popWriter.print(";fitness"); popWriter.println(); popWriter.close(); } catch (final IOException e) { Logger.logExceptionCallStack("Cannot print population to file:\n", e); } } //---------------------------------------------------------------------------------------------------- protected void printPopulation(final int iteration) { try { final PrintWriter popWriter = new PrintWriter( new FileWriter(new File(workspace, populationFileName + ext), true)); final Population population = genotype.getPopulation(); for (int i = 0; i < population.size(); ++i) { popWriter.print(iteration); for (int j = 0; j < population.getChromosome(i).size(); ++j) popWriter.print(";" + population.getChromosome(i).getGene(j).getAllele().toString()); popWriter.print(";" + population.getChromosome(i).getFitnessValue()); popWriter.println(); } popWriter.close(); } catch (final IOException e) { Logger.logExceptionCallStack("Cannot print population to file.", e); } } //---------------------------------------------------------------------------------------------------- private int calculateNumberOfGenes() { int count = 0; final DefaultMutableTreeNode root = (DefaultMutableTreeNode) chromosomeTree.getRoot(); @SuppressWarnings("rawtypes") final Enumeration nodes = root.breadthFirstEnumeration(); nodes.nextElement(); while (nodes.hasMoreElements()) { final DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodes.nextElement(); final ParameterOrGene userObj = (ParameterOrGene) node.getUserObject(); if (userObj.isGene()) count++; } return count; } //---------------------------------------------------------------------------------------------------- public void setRecordableVariables(final DefaultMutableTreeNode root) { final List<RecordableInfo> newList = new ArrayList<RecordableInfo>(); if (root.getChildCount() > 0) { final DefaultMutableTreeNode recorder = (DefaultMutableTreeNode) root.getChildAt(0); final ResultInfo resultInfo = (ResultInfo) recorder.getFirstLeaf().getUserObject(); workspace = new File(resultInfo.getFile()).getParentFile(); //first two children contains recorder meta data for (int j = 2; j < recorder.getChildCount(); ++j) { final RecordableElement re = (RecordableElement) ((DefaultMutableTreeNode) recorder.getChildAt(j)) .getUserObject(); final RecordableInfo recInfo = new RecordableInfo( re.getAlias() != null ? re.getAlias() : re.getInfo().getName(), re.getInfo().getJavaType(), re.getInfo().getName()); if (!newList.contains(recInfo) && re.getInfo().isNumeric()) { newList.add(recInfo); } } } final RecordableInfo oldSelectedFunction = selectedFunction; removeAllFitnessFunctions(); fitnessFunctions.addAll(newList); if (listeners != null) { for (final ModelListener listener : listeners) { listener.fitnessFunctionAdded(); } } if (oldSelectedFunction != null) { RecordableInfo selectedFunctionInTheList = null; for (final RecordableInfo ri : fitnessFunctions) { if (ri.equals(oldSelectedFunction)) { // accessible name equality selectedFunctionInTheList = ri; } } if (selectedFunctionInTheList != null) { selectedFunction = selectedFunctionInTheList; if (listeners != null) { for (final ModelListener listener : listeners) { listener.fitnessFunctionSelected(selectedFunction); } } } } } //---------------------------------------------------------------------------------------------------- public String settingsOK(final DefaultMutableTreeNode recorders) { return getReadyStatusDetail(); } //---------------------------------------------------------------------------------------------------- public void setParameterTreeRoot(final DefaultMutableTreeNode root) { // we don't use this method in this implementation } //---------------------------------------------------------------------------------------------------- public boolean getReadyStatus() { String[] errors = checkGAModel(); if (errors == null) { return true; } else { readyStatusDetail = errors[0]; return false; } } //---------------------------------------------------------------------------------------------------- public String getReadyStatusDetail() { return readyStatusDetail; } //---------------------------------------------------------------------------------------------------- public JPanel getSettingsPanel(final IIntelliContext ctx) { if (content == null) { context = ctx; content = new GASearchPanel(this, ctx.getNewParametersButton()); addParametersToChromosomeTree(); if (listeners != null) { for (final ModelListener listener : listeners) { listener.fitnessFunctionAdded(); // added before, now just inform the gui } } } return content; } //---------------------------------------------------------------------------------------------------- public void addParametersToChromosomeTree() { removeAllParameters(); for (final ParameterInfo parameterInfo : context.getParameters()) { addParameter(new ParameterOrGene(parameterInfo)); } } //---------------------------------------------------------------------------------------------------- public void save(final Node node) { final Document document = node.getOwnerDocument(); final Element pluginElement = (Element) node; pluginElement.setAttribute(WizardSettingsManager.CLASS, this.getClass().getName()); final Element gaSettingsElement = document.createElement(GA_SETTINGS); node.appendChild(gaSettingsElement); saveGeneralParameters(gaSettingsElement); saveSelectors(gaSettingsElement); saveOperators(gaSettingsElement); saveChromosome(gaSettingsElement); } //---------------------------------------------------------------------------------------------------- private void saveGeneralParameters(final Element gaSettingsElement) { final Document document = gaSettingsElement.getOwnerDocument(); Element element = document.createElement(POPULATION_SIZE); element.appendChild(document.createTextNode(String.valueOf(populationSize))); gaSettingsElement.appendChild(element); element = document.createElement(POPULATION_RANDOM_SEED); element.appendChild(document.createTextNode(String.valueOf(populationGenerationSeed))); gaSettingsElement.appendChild(element); element = document.createElement(FIX_NUMBER_OF_GENERATIONS); element.appendChild(document.createTextNode(String.valueOf(fixNumberOfGenerations))); gaSettingsElement.appendChild(element); if (fixNumberOfGenerations) { element = document.createElement(NUMBER_OF_GENERATIONS); element.appendChild(document.createTextNode(String.valueOf(numberOfGenerations))); gaSettingsElement.appendChild(element); } else { element = document.createElement(FITNESS_LIMIT_CRITERION); element.appendChild(document.createTextNode(String.valueOf(fitnessLimitCriterion))); gaSettingsElement.appendChild(element); } element = document.createElement(OPTIMIZATION_DIRECTION); element.appendChild(document.createTextNode(optimizationDirection.name())); gaSettingsElement.appendChild(element); element = document.createElement(FITNESS_FUNCTION); element.setAttribute(WizardSettingsManager.ALIAS, selectedFunction.getName()); element.appendChild(document.createTextNode(selectedFunction.getAccessibleName())); gaSettingsElement.appendChild(element); } //---------------------------------------------------------------------------------------------------- private void saveSelectors(final Element gaSettingsElement) { final Document document = gaSettingsElement.getOwnerDocument(); final Element selectorsElement = document.createElement(SELECTORS); gaSettingsElement.appendChild(selectorsElement); for (final IGASelectorConfigurator selectorOperator : selectedSelectionOperators) { final Element selectorElement = document.createElement(SELECTOR); selectorsElement.appendChild(selectorElement); selectorElement.setAttribute(WizardSettingsManager.TYPE, selectorOperator.getName()); for (final Entry<String, String> entry : selectorOperator.getConfiguration().entrySet()) { final Element propertyElement = document.createElement(PROPERTY); propertyElement.setAttribute(KEY, entry.getKey()); propertyElement.appendChild(document.createTextNode(entry.getValue())); selectorElement.appendChild(propertyElement); } } } //---------------------------------------------------------------------------------------------------- private void saveOperators(final Element gaSettingsElement) { final Document document = gaSettingsElement.getOwnerDocument(); final Element geneticOperatorsElement = document.createElement(GENETIC_OPERATORS); gaSettingsElement.appendChild(geneticOperatorsElement); for (final IGAOperatorConfigurator geneticOperator : selectedGeneticOperators) { final Element operatorElement = document.createElement(GENETIC_OPERATOR); geneticOperatorsElement.appendChild(operatorElement); operatorElement.setAttribute(WizardSettingsManager.TYPE, geneticOperator.getName()); for (final Entry<String, String> entry : geneticOperator.getConfiguration().entrySet()) { final Element propertyElement = document.createElement(PROPERTY); propertyElement.setAttribute(KEY, entry.getKey()); propertyElement.appendChild(document.createTextNode(entry.getValue())); operatorElement.appendChild(propertyElement); } } } //---------------------------------------------------------------------------------------------------- private void saveChromosome(final Element gaSettingsElement) { final Document document = gaSettingsElement.getOwnerDocument(); final Element chromosomeElement = document.createElement(CHROMOSOME); gaSettingsElement.appendChild(chromosomeElement); @SuppressWarnings("rawtypes") final Enumeration nodes = ((DefaultMutableTreeNode) chromosomeTree.getRoot()).children(); while (nodes.hasMoreElements()) { final DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodes.nextElement(); saveParameterOrGene(node, chromosomeElement); } } //---------------------------------------------------------------------------------------------------- private void saveParameterOrGene(final DefaultMutableTreeNode node, final Element chromosomeElement) { final Document document = chromosomeElement.getOwnerDocument(); final ParameterOrGene userObj = (ParameterOrGene) node.getUserObject(); final ParameterInfo info = userObj.getInfo(); if (userObj.isGene()) { final GeneInfo geneInfo = userObj.getGeneInfo(); final Element geneElement = document.createElement(GENE); chromosomeElement.appendChild(geneElement); geneElement.setAttribute(WizardSettingsManager.NAME, info.getName()); geneElement.setAttribute(WizardSettingsManager.TYPE, geneInfo.getValueType()); if (GeneInfo.INTERVAL.equals(geneInfo.getValueType())) { geneElement.setAttribute(IS_INTEGER, String.valueOf(geneInfo.isIntegerVals())); geneElement.setAttribute(MIN_VALUE, String.valueOf(geneInfo.getMinValue())); geneElement.setAttribute(MAX_VALUE, String.valueOf(geneInfo.getMaxValue())); } else if (GeneInfo.LIST.equals(geneInfo.getValueType())) { for (final Object value : geneInfo.getValueRange()) { final Element element = document.createElement(LIST_VALUE); geneElement.appendChild(element); element.appendChild(document.createTextNode(String.valueOf(value))); } } } else { final Element paramElement = document.createElement(PARAMETER); chromosomeElement.appendChild(paramElement); paramElement.setAttribute(WizardSettingsManager.NAME, info.getName()); paramElement.appendChild(document.createTextNode(String.valueOf(info.getValue()))); } } //---------------------------------------------------------------------------------------------------- public void load(final IIntelliContext context, final Element element) throws WizardLoadingException { selectors = Arrays.asList(new TournamentSelectorConfigurator(), new WeightedRouletteSelectorConfigurator(), new BestChromosomeSelectorConfigurator()); geneticOperators = Arrays.asList(new GeneAveragingCrossoverOperatorConfigurator(), new CrossoverOperatorConfigurator(), new MutationOperatorConfigurator()); init(); selectedSelectionOperators.clear(); selectedGeneticOperators.clear(); readyStatusDetail = null; content = (GASearchPanel) getSettingsPanel(context); final NodeList nl = element.getElementsByTagName(GA_SETTINGS); if (nl != null && nl.getLength() > 0) { final Element gaSettingsElement = (Element) nl.item(0); loadGeneralParameters(gaSettingsElement); loadSelectors(gaSettingsElement); loadOperators(gaSettingsElement); loadChromosome(gaSettingsElement, context.getParameters()); content.reset(this); alterParameterTree(context); } else { throw new WizardLoadingException(true, "missing node: " + GA_SETTINGS); } } //---------------------------------------------------------------------------------------------------- private void loadGeneralParameters(final Element gaSettingsElement) throws WizardLoadingException { NodeList nl = gaSettingsElement.getElementsByTagName(POPULATION_SIZE); if (nl != null && nl.getLength() > 0) { final Element element = (Element) nl.item(0); final NodeList content = element.getChildNodes(); if (content == null || content.getLength() == 0) { throw new WizardLoadingException(true, "missing content at node: " + POPULATION_SIZE); } final String populationSizeStr = ((Text) content.item(0)).getNodeValue().trim(); try { populationSize = Integer.parseInt(populationSizeStr); } catch (final NumberFormatException e) { throw new WizardLoadingException(true, "invalid content (" + populationSizeStr + ") at node: " + POPULATION_SIZE + " (expected: integer number)"); } } else { throw new WizardLoadingException(true, "missing node: " + POPULATION_SIZE); } nl = gaSettingsElement.getElementsByTagName(POPULATION_RANDOM_SEED); if (nl != null && nl.getLength() > 0) { final Element element = (Element) nl.item(0); final NodeList content = element.getChildNodes(); if (content == null || content.getLength() == 0) { throw new WizardLoadingException(true, "missing content at node: " + POPULATION_RANDOM_SEED); } final String populationGenerationSeedStr = ((Text) content.item(0)).getNodeValue().trim(); try { populationGenerationSeed = Integer.parseInt(populationGenerationSeedStr); } catch (final NumberFormatException e) { throw new WizardLoadingException(true, "invalid content (" + populationGenerationSeedStr + ") at node: " + POPULATION_RANDOM_SEED + " (expected: integer number)"); } } else { throw new WizardLoadingException(true, "missing node: " + POPULATION_RANDOM_SEED); } nl = gaSettingsElement.getElementsByTagName(FIX_NUMBER_OF_GENERATIONS); if (nl != null && nl.getLength() > 0) { final Element element = (Element) nl.item(0); final NodeList content = element.getChildNodes(); if (content == null || content.getLength() == 0) { throw new WizardLoadingException(true, "missing content at node: " + FIX_NUMBER_OF_GENERATIONS); } final String fixNumberOfGenerationsStr = ((Text) content.item(0)).getNodeValue().trim(); fixNumberOfGenerations = Boolean.parseBoolean(fixNumberOfGenerationsStr); } else { throw new WizardLoadingException(true, "missing node: " + FIX_NUMBER_OF_GENERATIONS); } if (fixNumberOfGenerations) { nl = gaSettingsElement.getElementsByTagName(NUMBER_OF_GENERATIONS); if (nl != null && nl.getLength() > 0) { final Element element = (Element) nl.item(0); final NodeList content = element.getChildNodes(); if (content == null || content.getLength() == 0) { throw new WizardLoadingException(true, "missing content at node: " + NUMBER_OF_GENERATIONS); } final String numberOfGenerationsStr = ((Text) content.item(0)).getNodeValue().trim(); try { numberOfGenerations = Integer.parseInt(numberOfGenerationsStr); } catch (final NumberFormatException e) { throw new WizardLoadingException(true, "invalid content (" + numberOfGenerationsStr + ") at node: " + NUMBER_OF_GENERATIONS + " (expected: integer number)"); } } else { throw new WizardLoadingException(true, "missing node: " + NUMBER_OF_GENERATIONS); } } else { nl = gaSettingsElement.getElementsByTagName(FITNESS_LIMIT_CRITERION); if (nl != null && nl.getLength() > 0) { final Element element = (Element) nl.item(0); final NodeList content = element.getChildNodes(); if (content == null || content.getLength() == 0) { throw new WizardLoadingException(true, "missing content at node: " + FITNESS_LIMIT_CRITERION); } final String fitnessLimitCriterionStr = ((Text) content.item(0)).getNodeValue().trim(); try { fitnessLimitCriterion = Double.parseDouble(fitnessLimitCriterionStr); } catch (final NumberFormatException e) { throw new WizardLoadingException(true, "invalid content (" + fitnessLimitCriterionStr + ") at node: " + FITNESS_LIMIT_CRITERION + " (expected: real number)"); } } else { throw new WizardLoadingException(true, "missing node: " + FITNESS_LIMIT_CRITERION); } } nl = gaSettingsElement.getElementsByTagName(OPTIMIZATION_DIRECTION); if (nl != null && nl.getLength() > 0) { final Element element = (Element) nl.item(0); final NodeList content = element.getChildNodes(); if (content == null || content.getLength() == 0) { throw new WizardLoadingException(true, "missing content at node: " + OPTIMIZATION_DIRECTION); } final String optimizationDirectionStr = ((Text) content.item(0)).getNodeValue().trim(); try { optimizationDirection = FitnessFunctionDirection.valueOf(optimizationDirectionStr); } catch (final IllegalArgumentException e) { throw new WizardLoadingException(true, "invalid content (" + optimizationDirectionStr + ") at node: " + OPTIMIZATION_DIRECTION + " (expected: MINIMIZE or MAXIMIZE)"); } } else { throw new WizardLoadingException(true, "missing node: " + OPTIMIZATION_DIRECTION); } nl = gaSettingsElement.getElementsByTagName(FITNESS_FUNCTION); if (nl != null && nl.getLength() > 0) { final Element element = (Element) nl.item(0); String fitnessFunctionAlias = element.getAttribute(WizardSettingsManager.ALIAS); final NodeList content = element.getChildNodes(); if (content == null || content.getLength() == 0) { throw new WizardLoadingException(true, "missing content at node: " + FITNESS_FUNCTION); } final String fitnessFunctionStr = ((Text) content.item(0)).getNodeValue().trim(); fitnessFunctionAlias = (fitnessFunctionAlias != null && !fitnessFunctionAlias.trim().isEmpty()) ? fitnessFunctionAlias.trim() : fitnessFunctionStr; selectedFunction = new RecordableInfo(fitnessFunctionAlias, Double.TYPE, fitnessFunctionStr); // dummy object to store accessible name } else { throw new WizardLoadingException(true, "missing node: " + FITNESS_FUNCTION); } } //---------------------------------------------------------------------------------------------------- private void loadSelectors(final Element gaSettingsElement) throws WizardLoadingException { NodeList nl = gaSettingsElement.getElementsByTagName(SELECTORS); if (nl != null && nl.getLength() > 0) { final Element selectorsElement = (Element) nl.item(0); nl = selectorsElement.getElementsByTagName(SELECTOR); if (nl != null && nl.getLength() > 0) { for (int i = 0; i < nl.getLength(); ++i) { final Element selectorElement = (Element) nl.item(i); final String type = selectorElement.getAttribute(WizardSettingsManager.TYPE); if (type == null || type.trim().isEmpty()) { throw new WizardLoadingException(true, "missing '" + WizardSettingsManager.TYPE + "' attribute at node: " + SELECTOR); } final IGASelectorConfigurator configurator = findSelectorConfigurator(type.trim()); final Map<String, String> config = readProperties(selectorElement); configurator.setConfiguration(config); selectedSelectionOperators.add(configurator); } } } else { throw new WizardLoadingException(true, "missing node: " + SELECTORS); } } //---------------------------------------------------------------------------------------------------- private void loadOperators(final Element gaSettingsElement) throws WizardLoadingException { NodeList nl = gaSettingsElement.getElementsByTagName(GENETIC_OPERATORS); if (nl != null && nl.getLength() > 0) { final Element geneticOperatorsElement = (Element) nl.item(0); nl = geneticOperatorsElement.getElementsByTagName(GENETIC_OPERATOR); if (nl != null && nl.getLength() > 0) { for (int i = 0; i < nl.getLength(); ++i) { final Element goElement = (Element) nl.item(i); final String type = goElement.getAttribute(WizardSettingsManager.TYPE); if (type == null || type.trim().isEmpty()) { throw new WizardLoadingException(true, "missing '" + WizardSettingsManager.TYPE + "' attribute at node: " + GENETIC_OPERATOR); } final IGAOperatorConfigurator configurator = findOperatorConfigurator(type.trim()); final Map<String, String> config = readProperties(goElement); configurator.setConfiguration(config); selectedGeneticOperators.add(configurator); } } } else { throw new WizardLoadingException(true, "missing node: " + GENETIC_OPERATORS); } } //---------------------------------------------------------------------------------------------------- private void loadChromosome(final Element gaSettingsElement, final List<ParameterInfo> params) throws WizardLoadingException { final int childCount = getChromosomeTree().getChildCount(getChromosomeTree().getRoot()); if (childCount > 0) { final DefaultMutableTreeNode root = (DefaultMutableTreeNode) getChromosomeTree().getRoot(); for (int i = childCount - 1; i >= 0; --i) { final MutableTreeNode node = (MutableTreeNode) root.getChildAt(i); getChromosomeTree().removeNodeFromParent(node); } genes = null; } final DefaultMutableTreeNode root = (DefaultMutableTreeNode) getChromosomeTree().getRoot(); NodeList nl = gaSettingsElement.getElementsByTagName(CHROMOSOME); if (nl != null && nl.getLength() > 0) { final Element chromosomeElement = (Element) nl.item(0); nl = chromosomeElement.getElementsByTagName(GENE); loadGene(nl, params, root); nl = chromosomeElement.getElementsByTagName(PARAMETER); loadParameter(nl, params, root); } else { throw new WizardLoadingException(true, "missing node: " + CHROMOSOME); } } //---------------------------------------------------------------------------------------------------- private void loadGene(final NodeList geneList, final List<ParameterInfo> params, final DefaultMutableTreeNode root) throws WizardLoadingException { if (geneList != null) { for (int i = 0; i < geneList.getLength(); ++i) { final Element geneElement = (Element) geneList.item(i); final String geneName = geneElement.getAttribute(WizardSettingsManager.NAME); if (geneName == null || geneName.trim().isEmpty()) { throw new WizardLoadingException(true, "missing attribute '" + WizardSettingsManager.NAME + "' at node: " + GENE); } final ParameterInfo info = findParameterInfo(params, geneName.trim()); if (info != null) { final ParameterOrGene userObj = initializeUserObjectFromGene(geneElement, info); final DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(userObj); getChromosomeTree().insertNodeInto(newNode, root, root.getChildCount()); } else { throw new WizardLoadingException(false, "Unrecognized gene: " + geneName + " (ignored)"); } } } } //---------------------------------------------------------------------------------------------------- private void loadParameter(final NodeList parameterList, final List<ParameterInfo> params, final DefaultMutableTreeNode root) throws WizardLoadingException { if (parameterList != null) { for (int i = 0; i < parameterList.getLength(); ++i) { final Element parameterElement = (Element) parameterList.item(i); final String paramName = parameterElement.getAttribute(WizardSettingsManager.NAME); if (paramName == null || paramName.trim().isEmpty()) { throw new WizardLoadingException(true, "missing attribute '" + WizardSettingsManager.NAME + "' at node: " + PARAMETER); } final ParameterInfo info = findParameterInfo(params, paramName.trim()); if (info != null) { final NodeList content = parameterElement.getChildNodes(); if (content == null || content.getLength() == 0) { throw new WizardLoadingException(true, "missing content at node: " + PARAMETER); } final String parameterValue = ((Text) content.item(0)).getNodeValue().trim(); Object value; if (info.getType().equals("File") && parameterValue.isEmpty()) { value = new File(""); } else { value = ParameterInfo.getValue(parameterValue, info.getJavaType()); } info.setValue(value); final ParameterOrGene userObj = new ParameterOrGene(info); final DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(userObj); getChromosomeTree().insertNodeInto(newNode, root, root.getChildCount()); } else { throw new WizardLoadingException(false, "Unrecognized gene: " + paramName + " (ignored)"); } } } } //---------------------------------------------------------------------------------------------------- private ParameterOrGene initializeUserObjectFromGene(final Element geneElement, final ParameterInfo info) throws WizardLoadingException { final String geneType = geneElement.getAttribute(WizardSettingsManager.TYPE); if (geneType == null || geneType.trim().isEmpty()) { throw new WizardLoadingException(true, "missing attribute '" + WizardSettingsManager.TYPE + "' at node: " + GENE); } if (GeneInfo.INTERVAL.equals(geneType.trim())) { final String isIntegerStr = geneElement.getAttribute(IS_INTEGER); if (isIntegerStr == null || isIntegerStr.trim().isEmpty()) { throw new WizardLoadingException(true, "missing attribute '" + IS_INTEGER + "' at node: " + GENE); } final boolean isInteger = Boolean.parseBoolean(isIntegerStr.trim()); final String minStr = geneElement.getAttribute(MIN_VALUE); if (minStr == null || minStr.trim().isEmpty()) { throw new WizardLoadingException(true, "missing attribute '" + MIN_VALUE + "' at node: " + GENE); } final String maxStr = geneElement.getAttribute(MAX_VALUE); if (maxStr == null || maxStr.trim().isEmpty()) { throw new WizardLoadingException(true, "missing attribute '" + MAX_VALUE + "' at node: " + GENE); } if (isInteger) { long min = Long.MIN_VALUE; try { min = Long.parseLong(minStr); } catch (final NumberFormatException e) { throw new WizardLoadingException(true, "invalid attribute value (" + MIN_VALUE + "=" + minStr + ") at node: " + GENE + " (expected: integer number)"); } long max = Long.MAX_VALUE; try { max = Long.parseLong(maxStr); } catch (final NumberFormatException e) { throw new WizardLoadingException(true, "invalid attribute value (" + MAX_VALUE + "=" + maxStr + ") at node: " + GENE + " (expected: integer number)"); } return new ParameterOrGene(info, min, max); } else { double min = -Double.MAX_VALUE; try { min = Double.parseDouble(minStr); } catch (final NumberFormatException e) { throw new WizardLoadingException(true, "invalid attribute value (" + MIN_VALUE + "=" + minStr + ") at node: " + GENE + " (expected: real number)"); } double max = Double.MAX_VALUE; try { max = Double.parseDouble(maxStr); } catch (final NumberFormatException e) { throw new WizardLoadingException(true, "invalid attribute value (" + MAX_VALUE + "=" + maxStr + ") at node: " + GENE + " (expected: real number)"); } return new ParameterOrGene(info, min, max); } } else if (GeneInfo.LIST.equals(geneType.trim())) { final NodeList nl = geneElement.getElementsByTagName(LIST_VALUE); if (nl != null && nl.getLength() > 0) { final List<Object> valueList = new ArrayList<>(nl.getLength()); for (int i = 0; i < nl.getLength(); ++i) { final Element element = (Element) nl.item(i); final NodeList content = element.getChildNodes(); if (content == null || content.getLength() == 0) { throw new WizardLoadingException(true, "missing content at node: " + LIST_VALUE); } final String strValue = ((Text) content.item(0)).getNodeValue().trim(); if (info instanceof MasonChooserParameterInfo) { try { valueList.add(new Integer(strValue)); } catch (final NumberFormatException e) { throw new WizardLoadingException(true, "invalid content (" + strValue + ") at node: " + LIST_VALUE + " (expected: integer number)"); } } else { valueList.add(parseListElement(info.getJavaType(), strValue)); } } return new ParameterOrGene(info, valueList); } else { throw new WizardLoadingException(true, "missing node: " + LIST_VALUE); } } else if (GeneInfo.BOOLEAN.equals(geneType.trim())) { ParameterOrGene result = new ParameterOrGene(info); result.setBooleanGene(); return result; } else { throw new WizardLoadingException(true, "invalid attribute value (" + WizardSettingsManager.TYPE + "=" + geneType.trim() + ") at node: " + GENE); } } //---------------------------------------------------------------------------------------------------- @SuppressWarnings({ "unchecked", "rawtypes" }) private Object parseListElement(final Class<?> type, final String strValue) throws WizardLoadingException { if (String.class.equals(type)) { return strValue; } if (Enum.class.isAssignableFrom(type)) { final Class<? extends Enum> clazz = (Class<? extends Enum>) type; return Enum.valueOf(clazz, strValue); } if (type.equals(Double.class) || type.equals(Float.class) || type.equals(Double.TYPE) || type.equals(Float.TYPE)) { try { return Double.parseDouble(strValue); } catch (final NumberFormatException e) { throw new WizardLoadingException(true, "invalid content (" + strValue + ") at node: " + LIST_VALUE + " (expected: real number)"); } } try { return Long.parseLong(strValue); } catch (final NumberFormatException e) { throw new WizardLoadingException(true, "invalid content (" + strValue + ") at node: " + LIST_VALUE + " (expected: integer number)"); } } //---------------------------------------------------------------------------------------------------- private ParameterInfo findParameterInfo(final List<ParameterInfo> parameters, final String name) { for (final ParameterInfo info : parameters) { if (name.equals(info.getName())) return info; } return null; } //---------------------------------------------------------------------------------------------------- private IGASelectorConfigurator findSelectorConfigurator(final String selectorType) throws WizardLoadingException { for (final IGASelectorConfigurator configurator : selectors) { if (configurator.getName().equals(selectorType)) return configurator; } throw new WizardLoadingException(true, "Unrecognized selector: " + selectorType + "."); } //---------------------------------------------------------------------------------------------------- private IGAOperatorConfigurator findOperatorConfigurator(final String operatorType) throws WizardLoadingException { for (final IGAOperatorConfigurator configurator : geneticOperators) { if (configurator.getName().equals(operatorType)) return configurator; } throw new WizardLoadingException(true, "Unrecognized genetic operator: " + operatorType + "."); } //---------------------------------------------------------------------------------------------------- private Map<String, String> readProperties(final Node node) { final Map<String, String> prop = new HashMap<String, String>(); final NodeList nodes = node.getChildNodes(); if (nodes != null) { for (int i = 0; i < nodes.getLength(); ++i) { if (!(nodes.item(i) instanceof Element)) continue; final Element element = (Element) nodes.item(i); if (!element.getTagName().equals(PROPERTY)) continue; final String key = element.getAttribute(KEY); final Text text = (Text) element.getChildNodes().item(0); if (text == null) { prop.put(key.trim(), ""); } else { final String value = text.getNodeValue(); prop.put(key.trim(), value.trim()); } } } return prop; } //---------------------------------------------------------------------------------------------------- public void invalidatePlugin() { content = null; selectors = Arrays.asList(new TournamentSelectorConfigurator(), new WeightedRouletteSelectorConfigurator(), new BestChromosomeSelectorConfigurator()); geneticOperators = Arrays.asList(new GeneAveragingCrossoverOperatorConfigurator(), new CrossoverOperatorConfigurator(), new MutationOperatorConfigurator()); init(); } //==================================================================================================== // nested classes //---------------------------------------------------------------------------------------------------- @SuppressWarnings("serial") private class ResultFileFitnessFunction extends FitnessFunction { //==================================================================================================== // members private transient IParameterSweepResultReader currentReader; //==================================================================================================== // methods //---------------------------------------------------------------------------------------------------- public void setCurrentReader(final IParameterSweepResultReader currentReader) { this.currentReader = currentReader; } //---------------------------------------------------------------------------------------------------- protected double evaluate(final IChromosome a_subject) { if (currentReader == null) throw new IllegalStateException("Fitness function evaluation cannot access the results."); final List<ai.aitia.meme.paramsweep.batch.param.ParameterInfo<?>> combination = createCombinationFromChromosome( a_subject); try { final List<ResultValueInfo> infos = currentReader.getResultValueInfos(getSelectedFitnessFunction(), combination); if (infos == null || infos.size() == 0) { return getFitnessFunctionDirection() == FitnessFunctionDirection.MINIMIZE ? 1e19 : 0; } if (Double.isInfinite(getFitnessValue(infos).doubleValue())) { return Double.MAX_VALUE; } if (Double.isNaN(getFitnessValue(infos).doubleValue())) { return getFitnessFunctionDirection() == FitnessFunctionDirection.MINIMIZE ? 1e19 : 0; } return getFitnessValue(infos).doubleValue(); } catch (final ReadingException e) { throw new RuntimeException(e); } } //---------------------------------------------------------------------------------------------------- private List<ai.aitia.meme.paramsweep.batch.param.ParameterInfo<?>> createCombinationFromChromosome( final IChromosome a_subject) { final List<ai.aitia.meme.paramsweep.batch.param.ParameterInfo<?>> combination = new ArrayList<ai.aitia.meme.paramsweep.batch.param.ParameterInfo<?>>( a_subject.getGenes().length); for (int i = 0; i < a_subject.getGenes().length; ++i) { final IIdentifiableGene geneWithId = (IIdentifiableGene) a_subject.getGene(i); final GeneInfo geneInfo = genes.get(whichGene(geneWithId.getId())); final ParameterInfo info = new ParameterInfo(geneInfo.getName(), geneInfo.getType(), geneInfo.getJavaType()); final String strValue = String.valueOf(geneWithId.getAllele()); info.setValue(ParameterInfo.getValue(strValue, info.getJavaType())); combination.add((ai.aitia.meme.paramsweep.batch.param.ParameterInfo<?>) InfoConverter .parameterInfo2ParameterInfo(info)); } return combination; } //---------------------------------------------------------------------------------------------------- private Number getFitnessValue(final List<ResultValueInfo> candidates) { if (candidates == null || candidates.isEmpty()) return new Double(FitnessFunction.NO_FITNESS_VALUE); Collections.sort(candidates, new Comparator<ResultValueInfo>() { @Override public int compare(final ResultValueInfo info1, final ResultValueInfo info2) { final double tick1 = (Double) info1.getLabel(); final double tick2 = (Double) info2.getLabel(); return Double.compare(tick1, tick2); } }); final Object value = candidates.get(candidates.size() - 1).getValue(); return (Number) value; } } }