/*
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;
}
}
}