/* Copyright 2009 by Marcin Szubert Licensed under the Academic Free License version 3.0 */ package cecj.archive; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import ec.EvolutionState; import ec.Individual; import ec.util.Parameter; /** * Layered Pareto-Coevolution Archive. * * This archive is a modified version of the IPCA archive. While the original one can grow * indefinitely (tests are never removed from the archive), this type of archive limits the maximum * number of stored individuals. However, this goal is achieved for the price of reducing the * reliability of the algorithm. After appending non-dominated candidate solutions and useful tests * to appropriate archives, maintainLayers and updateTestArchive methods * are invoked in order to decrease the amount of used memory. The first one checks which candidate * solutions belong to the first num-layers Pareto layers and keeps them in the * archive. The second retains only these tests which make distinctions between neighboring layers. * * @author Marcin Szubert * */ public class LAPCArchive extends ParetoCoevolutionArchive { private static final String P_NUM_LAYERS = "num-layers"; private int numLayers; private List> layers; @Override public void setup(EvolutionState state, Parameter base) { super.setup(state, base); Parameter numLayersParameter = base.push(P_NUM_LAYERS); numLayers = state.parameters.getInt(numLayersParameter, null, 1); if (numLayers <= 0) { state.output.fatal("Number of LAPCA layers must be > 0.\n"); } layers = new ArrayList>(numLayers); } /* * It is implemented in a IPCA-like way. Another method is to extend both existing archives by * new individuals, then find first n layers of candidates with respect to all tests in the * archive and in the population and finally select necessary tests making distinctions between * layers. */ @Override protected void submit(EvolutionState state, List candidates, List cArchive, List tests, List tArchive) { List testsCopy = new ArrayList(tests); List usefulTests; for (Individual candidate : candidates) { if (isUseful(state, candidate, cArchive, tArchive, testsCopy)) { usefulTests = findUsefulTests(state, candidate, cArchive, tArchive, testsCopy); cArchive.add(candidate); tArchive.addAll(usefulTests); testsCopy.removeAll(usefulTests); } } maintainLayers(state, cArchive, tArchive); updateTestArchive(state, tArchive); } private void updateTestArchive(EvolutionState state, List tArchive) { Set tset = new HashSet(); tset.addAll(findDistinguishingTests(state, layers.get(0), layers.get(0), tArchive)); for (int l = 1; l < numLayers; l++) { tset.addAll(findDistinguishingTests(state, layers.get(l - 1), layers.get(l), tArchive)); } tArchive.clear(); tArchive.addAll(tset); } private List findDistinguishingTests(EvolutionState state, List layer1, List layer2, List tests) { List distinguishingTests = new ArrayList(); for (Individual candidate1 : layer1) { for (Individual candidate2 : layer2) { if (candidate1.equals(candidate2)) continue; Individual test = findUsefulTest(state, candidate1, candidate2, tests); if ((test != null) && (!distinguishingTests.contains(test))) { distinguishingTests.add(test); } } } return distinguishingTests; } private void maintainLayers(EvolutionState state, List cArchive, List tArchive) { List cArchiveCopy = new ArrayList(cArchive); for (int layer = 0; layer < numLayers; layer++) { List frontPareto = findNonDominatedCandidates(state, cArchiveCopy, tArchive); layers.set(layer, frontPareto); cArchiveCopy.removeAll(frontPareto); } cArchive.removeAll(cArchiveCopy); } private List findNonDominatedCandidates(EvolutionState state, List cArchive, List tArchive) { List result = new ArrayList(); for (Individual candidate : cArchive) { if (!isDominated(state, candidate, cArchive, tArchive)) { result.add(candidate); } } return result; } }