/* Copyright 2009 by Marcin Szubert Licensed under the Academic Free License version 3.0 */ package cecj.archive; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import cecj.interaction.InteractionResult; import cecj.utils.EquivalenceComparator; import ec.EvolutionState; import ec.Individual; import ec.util.Parameter; /** * The simplest type of candidate-test archive. * * During the first step of the submit method, new candidates and tests are added to * corresponding archives; then duplicate candidate solutions are eliminated (two individuals are * considered equal if for each test in the archive they have identical outcomes). After sorting * candidates by number of solved tests, the best archive-size individuals are kept in * the archive. The last step is elimination of unsolved and duplicated (with respect to the * outcomes against archival candidates) tests. * * Since duplicates removal is a common task, a purpose-built EquivalenceComparator * interface is used for defining custom equivalence criteria. * * @author Marcin Szubert * */ public class MaxSolveArchive extends CandidateTestArchive { private static final String P_ARCHIVE_SIZE = "archive-size"; private int archiveSize; @Override public void setup(EvolutionState state, Parameter base) { super.setup(state, base); Parameter archiveSizeParameter = base.push(P_ARCHIVE_SIZE); archiveSize = state.parameters.getInt(archiveSizeParameter, null, 1); if (archiveSize <= 0) { state.output.fatal("Archive size must be > 0\n"); } } @Override protected void submit(EvolutionState state, List candidates, List cArchive, List tests, List tArchive) { cArchive.addAll(candidates); tArchive.addAll(tests); eliminateDuplicates(cArchive, new CandidateEquivalenceComparator(state, tArchive)); Map numSolved = countSolved(state, cArchive, tArchive); Collections.sort(cArchive, new NumberSolvedComparator(numSolved)); if (cArchive.size() > archiveSize) { cArchive.subList(archiveSize, cArchive.size()).clear(); } eliminateUnsolvedTests(state, cArchive, tArchive); eliminateDuplicates(tArchive, new TestEquivalenceComparator(state, cArchive)); } private void eliminateDuplicates(List archive, EquivalenceComparator comparator) { for (int ind1 = 0; ind1 < archive.size(); ind1++) { for (int ind2 = archive.size(); ind2 > ind1; ind2--) { if (comparator.equal(archive.get(ind1), archive.get(ind2))) { archive.remove(ind2); } } } } private void eliminateUnsolvedTests(EvolutionState state, List cArchive, List tArchive) { for (int test = 0; test < tArchive.size(); test++) { if (!isSolved(state, tArchive.get(test), cArchive)) { tArchive.remove(test); } } } private boolean isSolved(EvolutionState state, Individual test, List candidates) { for (Individual candidate : candidates) { if (problem.solves(state, candidate, test)) { return true; } } return false; } private Map countSolved(EvolutionState state, List candidates, List tests) { Map result = new HashMap(); for (Individual candidate : candidates) { int countTest = 0; for (Individual test : tests) { if (problem.solves(state, candidate, test)) { countTest++; } } result.put(candidate, countTest); } return result; } private class NumberSolvedComparator implements Comparator { private Map solved; public NumberSolvedComparator(Map solved) { this.solved = solved; } public int compare(Individual o1, Individual o2) { if (solved.get(o1) > solved.get(o2)) { return -1; } else if (solved.get(o1) > solved.get(o2)) { return 1; } else { return 0; } } } private class CandidateEquivalenceComparator implements EquivalenceComparator { private EvolutionState state; private List tests; public CandidateEquivalenceComparator(EvolutionState state, List tests) { this.state = state; this.tests = tests; } public boolean equal(Individual o1, Individual o2) { for (Individual test : tests) { InteractionResult result1 = problem.test(state, o1, test).first; InteractionResult result2 = problem.test(state, o2, test).first; if (!result1.equals(result2)) { return false; } } return false; } } private class TestEquivalenceComparator implements EquivalenceComparator { private EvolutionState state; private List candidates; public TestEquivalenceComparator(EvolutionState state, List candidates) { this.state = state; this.candidates = candidates; } public boolean equal(Individual o1, Individual o2) { for (Individual candidate : candidates) { InteractionResult result1 = problem.test(state, candidate, o2).second; InteractionResult result2 = problem.test(state, candidate, o2).second; if (!result1.equals(result2)) { return false; } } return false; } } }