Skip to content

Commit

Permalink
Merge pull request #808 from kusumotolab/introduce-stop-first
Browse files Browse the repository at this point in the history
StopFirstを実装した
  • Loading branch information
shinsuke-mat authored Dec 9, 2020
2 parents c5c26ce + bf5912a commit 2bb09a5
Show file tree
Hide file tree
Showing 27 changed files with 458 additions and 116 deletions.
12 changes: 9 additions & 3 deletions src/main/java/jp/kusumotolab/kgenprog/CUILauncher.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
import jp.kusumotolab.kgenprog.ga.crossover.FirstVariantSelectionStrategy;
import jp.kusumotolab.kgenprog.ga.crossover.SecondVariantSelectionStrategy;
import jp.kusumotolab.kgenprog.ga.mutation.Mutation;
import jp.kusumotolab.kgenprog.ga.mutation.SimpleMutation;
import jp.kusumotolab.kgenprog.ga.mutation.selection.CandidateSelection;
import jp.kusumotolab.kgenprog.ga.mutation.selection.RouletteStatementAndConditionSelection;
import jp.kusumotolab.kgenprog.ga.selection.DefaultVariantSelection;
import jp.kusumotolab.kgenprog.ga.selection.VariantSelection;
import jp.kusumotolab.kgenprog.ga.validation.DefaultCodeValidation;
Expand Down Expand Up @@ -40,8 +43,10 @@ public ExitStatus launch(final Configuration config) {
final FaultLocalization faultLocalization = config.getFaultLocalization()
.initialize();
final Random random = new Random(config.getRandomSeed());
final Mutation mutation = config.getMutationType()
.initialize(config.getMutationGeneratingCount(), random, config.getScope());
final CandidateSelection candidateSelection =
new RouletteStatementAndConditionSelection(random);
final Mutation mutation = new SimpleMutation(config.getMutationGeneratingCount(), random,
candidateSelection, config.getRequiredSolutionsCount(), config.getScope());
final FirstVariantSelectionStrategy firstVariantSelectionStrategy =
config.getFirstVariantSelectionStrategy()
.initialize(random);
Expand All @@ -50,7 +55,8 @@ public ExitStatus launch(final Configuration config) {
.initialize(random);
final Crossover crossover = config.getCrossoverType()
.initialize(random, firstVariantSelectionStrategy,
secondVariantSelectionStrategy, config.getCrossoverGeneratingCount());
secondVariantSelectionStrategy, config.getCrossoverGeneratingCount(),
config.getRequiredSolutionsCount());
final SourceCodeGeneration sourceCodeGeneration = new DefaultSourceCodeGeneration();
final SourceCodeValidation sourceCodeValidation = new DefaultCodeValidation();
final VariantSelection variantSelection = new DefaultVariantSelection(config.getHeadcount(),
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/jp/kusumotolab/kgenprog/KGenProgMain.java
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ private ExitStatus execGALoop(final VariantStore variantStore, final StopWatch s

// 変異プログラムを生成
final List<Variant> variantsByMutation = mutation.exec(variantStore);
final List<Variant> variantsByCrossover = crossover.exec(variantStore);
variantStore.addGeneratedVariants(variantsByMutation);
final List<Variant> variantsByCrossover = crossover.exec(variantStore);
variantStore.addGeneratedVariants(variantsByCrossover);

// 世代別サマリの出力
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ public class CascadeCrossover extends CrossoverAdaptor {
/**
* @param firstStrategy 1つ目の親を選ぶためのアルゴリズム
* @param secondStrategy 2つ目の親を選ぶためのアルゴリズム
* @param requiredSolutions 生成する必要がある修正プログラムの数
*/
public CascadeCrossover(final FirstVariantSelectionStrategy firstStrategy,
final SecondVariantSelectionStrategy secondStrategy) {
super(firstStrategy, secondStrategy, 2);
final SecondVariantSelectionStrategy secondStrategy, final int requiredSolutions) {
super(firstStrategy, secondStrategy, 2, requiredSolutions);
}


Expand Down
18 changes: 11 additions & 7 deletions src/main/java/jp/kusumotolab/kgenprog/ga/crossover/Crossover.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,16 @@ enum Type {
* @param firstVariantSelectionStrategy 1つ目の親を選ぶためのアルゴリズム
* @param secondVariantSelectionStrategy 2つ目の親を選ぶためのアルゴリズム
* @param generatingCount 一世代の交叉処理で生成する個体の数
* @param requiredSolutions 生成する必要がある修正プログラムの数
* @return 交叉を行うインスタンス
*/
@Override
public Crossover initialize(final Random random,
final FirstVariantSelectionStrategy firstVariantSelectionStrategy,
final SecondVariantSelectionStrategy secondVariantSelectionStrategy,
final int generatingCount) {
final int generatingCount, final int requiredSolutions) {
return new RandomCrossover(random, firstVariantSelectionStrategy,
secondVariantSelectionStrategy, generatingCount);
secondVariantSelectionStrategy, generatingCount, requiredSolutions);
}
},

Expand All @@ -89,15 +90,16 @@ public Crossover initialize(final Random random,
* @param firstVariantSelectionStrategy 1つ目の親を選ぶためのアルゴリズム
* @param secondVariantSelectionStrategy 2つ目の親を選ぶためのアルゴリズム
* @param generatingCount 一世代の交叉処理で生成する個体の数
* @param requiredSolutions 生成する必要がある修正プログラムの数
* @return 交叉を行うインスタンス
*/
@Override
public Crossover initialize(final Random random,
final FirstVariantSelectionStrategy firstVariantSelectionStrategy,
final SecondVariantSelectionStrategy secondVariantSelectionStrategy,
final int generatingCount) {
final int generatingCount, final int requiredSolutions) {
return new SinglePointCrossover(random, firstVariantSelectionStrategy,
secondVariantSelectionStrategy, generatingCount);
secondVariantSelectionStrategy, generatingCount, requiredSolutions);
}
},

Expand All @@ -117,15 +119,16 @@ public Crossover initialize(final Random random,
* @param firstVariantSelectionStrategy 1つ目の親を選ぶためのアルゴリズム
* @param secondVariantSelectionStrategy 2つ目の親を選ぶためのアルゴリズム
* @param generatingCount 一世代の交叉処理で生成する個体の数
* @param requiredSolutions 生成する必要がある修正プログラムの数
* @return 交叉を行うインスタンス
*/
@Override
public Crossover initialize(final Random random,
final FirstVariantSelectionStrategy firstVariantSelectionStrategy,
final SecondVariantSelectionStrategy secondVariantSelectionStrategy,
final int generatingCount) {
final int generatingCount, final int requiredSolutions) {
return new UniformCrossover(random, firstVariantSelectionStrategy,
secondVariantSelectionStrategy, generatingCount);
secondVariantSelectionStrategy, generatingCount, requiredSolutions);
}
};

Expand All @@ -136,11 +139,12 @@ public Crossover initialize(final Random random,
* @param firstVariantSelectionStrategy 1つ目の親を選ぶためのアルゴリズム
* @param secondVariantSelectionStrategy 2つ目の親を選ぶためのアルゴリズム
* @param generatingCount 一世代の交叉処理で生成する個体の数
* @param requiredSolutions 生成する必要がある修正プログラムの数
* @return 交叉を行うインスタンス
*/
public abstract Crossover initialize(final Random random,
final FirstVariantSelectionStrategy firstVariantSelectionStrategy,
final SecondVariantSelectionStrategy secondVariantSelectionStrategy,
final int generatingCount);
final int generatingCount, final int requiredSolutions);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jp.kusumotolab.kgenprog.ga.variant.Variant;
Expand All @@ -23,20 +22,23 @@ public abstract class CrossoverAdaptor implements Crossover {
private final FirstVariantSelectionStrategy firstVariantSelectionStrategy;
private final SecondVariantSelectionStrategy secondVariantSelectionStrategy;
private final int generatingCount;
private final int requiredSolutions;

/**
* コンストラクタ.交叉に必要な情報を全て引数として渡す必要あり.
*
* @param firstVariantSelectionStrategy 1つ目の親を選ぶためのアルゴリズム
* @param secondVariantSelectionStrategy 2つ目の親を選ぶためのアルゴリズム
* @param generatingCount 一世代の交叉処理で生成する個体の数
* @param requiredSolutions 生成する必要がある修正プログラムの数
*/
public CrossoverAdaptor(final FirstVariantSelectionStrategy firstVariantSelectionStrategy,
final SecondVariantSelectionStrategy secondVariantSelectionStrategy,
final int generatingCount) {
final int generatingCount, final int requiredSolutions) {
this.firstVariantSelectionStrategy = firstVariantSelectionStrategy;
this.secondVariantSelectionStrategy = secondVariantSelectionStrategy;
this.generatingCount = generatingCount;
this.requiredSolutions = requiredSolutions;
}

/**
Expand Down Expand Up @@ -69,26 +71,53 @@ public SecondVariantSelectionStrategy getSecondVariantSelectionStrategy() {
*/
@Override
public List<Variant> exec(final VariantStore variantStore) {

int foundSolutions = variantStore.getFoundSolutionsNumber()
.get();

// すでに必要な数の修正プログラムがある場合は何もせずにこのメソッドを抜ける
if (requiredSolutions <= foundSolutions) {
return Collections.emptyList();
}

final List<Variant> validVariants = filter(variantStore.getCurrentVariants());
final List<Variant> variants = new ArrayList<>();

// filteredVariantsの要素数が2に満たない場合は交叉しない
if (validVariants.size() < 2) {
return Collections.emptyList();
}

try {
// generatingCountを超えるまでバリアントを作りづづける
while (variants.size() < generatingCount) {
final List<Variant> variants = generateVariants(variantStore, validVariants);
return variants;
}

private List<Variant> generateVariants(final VariantStore variantStore,
final List<Variant> validVariants) {

final List<Variant> generatedVariants = new ArrayList<>();
int foundSolutions = variantStore.getFoundSolutionsNumber()
.get();

while (generatedVariants.size() < generatingCount) {
try {
final List<Variant> newVariants = makeVariants(validVariants, variantStore);
variants.addAll(newVariants);

// 新しい修正プログラムが生成された場合,必要数に達しているかを調べる
// 達している場合はそこで処理を終える
for (final Variant newVariant : newVariants) {
generatedVariants.add(newVariant);
if (newVariant.isCompleted()) {
foundSolutions++;
}
if (requiredSolutions <= foundSolutions) {
return generatedVariants;
}
}
} catch (final CrossoverInfeasibleException e) {
log.debug(e.getMessage());
}
} catch (final CrossoverInfeasibleException e) {
log.debug(e.getMessage());
}

// バリアントを作りすぎた場合はそれを除いてリターン
return variants.subList(0, generatingCount);
return generatedVariants;
}

protected abstract List<Variant> makeVariants(List<Variant> variants, VariantStore variantStore)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,15 @@ public class RandomCrossover extends CrossoverAdaptor {
* @param firstVariantSelectionStrategy 1つ目の親を選ぶためのアルゴリズム
* @param secondVariantSelectionStrategy 2つ目の親を選ぶためのアルゴリズム
* @param generatingCount 一世代の交叉処理で生成する個体の数
* @param requiredSolutions 生成する必要がある修正プログラムの数
* @return 交叉を行うインスタンス
*/
public RandomCrossover(final Random random,
final FirstVariantSelectionStrategy firstVariantSelectionStrategy,
final SecondVariantSelectionStrategy secondVariantSelectionStrategy,
final int generatingCount) {
super(firstVariantSelectionStrategy, secondVariantSelectionStrategy, generatingCount);
final int generatingCount, final int requiredSolutions) {
super(firstVariantSelectionStrategy, secondVariantSelectionStrategy, generatingCount,
requiredSolutions);
this.random = random;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ public class SinglePointCrossover extends CrossoverAdaptor {
* @param firstVariantSelectionStrategy 1つ目の親を選ぶためのアルゴリズム
* @param secondVariantSelectionStrategy 2つ目の親を選ぶためのアルゴリズム
* @param generatingCount 一世代の交叉処理で生成する個体の数
* @param requiredSolutions 生成する必要がある修正プログラムの数
* @return 交叉を行うインスタンス
*/
public SinglePointCrossover(final Random random,
final FirstVariantSelectionStrategy firstVariantSelectionStrategy,
final SecondVariantSelectionStrategy secondVariantSelectionStrategy,
final int generatingCount) {
super(firstVariantSelectionStrategy, secondVariantSelectionStrategy, generatingCount);
final int generatingCount, final int requiredSolutions) {
super(firstVariantSelectionStrategy, secondVariantSelectionStrategy, generatingCount,
requiredSolutions);
this.random = random;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ public class UniformCrossover extends CrossoverAdaptor {
* @param firstVariantSelectionStrategy 1つ目の親を選ぶためのアルゴリズム
* @param secondVariantSelectionStrategy 2つ目の親を選ぶためのアルゴリズム
* @param generatingCount 一世代の交叉処理で生成する個体の数
* @param requiredSolutions 生成する必要がある修正プログラムの数
* @return 交叉を行うインスタンス
*/
public UniformCrossover(final Random random,
final FirstVariantSelectionStrategy firstVariantSelectionStrategy,
final SecondVariantSelectionStrategy secondVariantSelectionStrategy,
final int generatingCount) {
super(firstVariantSelectionStrategy, secondVariantSelectionStrategy, generatingCount);
final int generatingCount, final int requiredSolutions) {
super(firstVariantSelectionStrategy, secondVariantSelectionStrategy, generatingCount,
requiredSolutions);
this.random = random;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@ public class HeuristicMutation extends Mutation {
* @param mutationGeneratingCount 各世代で生成する Variant の数
* @param random 乱数生成器
* @param candidateSelection 再利用候補の行を選択するクラス
* @param requiredSolutions 生成する必要がある修正プログラムの数
* @param scopeType 再利用するスコープのタイプ
*/
public HeuristicMutation(final int mutationGeneratingCount, final Random random,
final CandidateSelection candidateSelection, final Scope.Type scopeType) {
super(mutationGeneratingCount, random, candidateSelection);
final CandidateSelection candidateSelection, final int requiredSolutions,
final Scope.Type scopeType) {
super(mutationGeneratingCount, random, candidateSelection, requiredSolutions);
this.scopeType = scopeType;

operationGenerators = Lists.newArrayList(
Expand Down
34 changes: 30 additions & 4 deletions src/main/java/jp/kusumotolab/kgenprog/ga/mutation/Mutation.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package jp.kusumotolab.kgenprog.ga.mutation;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.function.Function;
Expand Down Expand Up @@ -29,19 +30,22 @@ public abstract class Mutation {
protected final Random random;
protected final int mutationGeneratingCount;
protected final CandidateSelection candidateSelection;
protected final int requiredSolutions;

/**
* コンストラクタ
*
* @param mutationGeneratingCount 各世代で生成する個体数
* @param random 乱数生成器
* @param candidateSelection 再利用する候補を選択するオブジェクト
* @param requiredSolutions 生成する必要がある修正プログラムの数
*/
public Mutation(final int mutationGeneratingCount, final Random random,
final CandidateSelection candidateSelection) {
final CandidateSelection candidateSelection, final int requiredSolutions) {
this.random = random;
this.mutationGeneratingCount = mutationGeneratingCount;
this.candidateSelection = candidateSelection;
this.requiredSolutions = requiredSolutions;
}

/**
Expand All @@ -67,6 +71,14 @@ public void setInitialCandidates(final Variant variant) {
*/
public List<Variant> exec(final VariantStore variantStore) {

int foundSolutions = variantStore.getFoundSolutionsNumber()
.get();

// すでに必要な数の修正プログラムがある場合は何もせずにこのメソッドを抜ける
if (requiredSolutions <= foundSolutions) {
return Collections.emptyList();
}

final List<Variant> generatedVariants = new ArrayList<>();

final List<Variant> currentVariants = variantStore.getCurrentVariants();
Expand All @@ -92,7 +104,17 @@ public List<Variant> exec(final VariantStore variantStore) {
final Base base = makeBase(suspiciousness);
final Gene gene = makeGene(variant.getGene(), base);
final HistoricalElement element = new MutationHistoricalElement(variant, base);
generatedVariants.add(variantStore.createVariant(gene, element));
final Variant newVariant = variantStore.createVariant(gene, element);
generatedVariants.add(newVariant);

// 新しい修正プログラムが生成された場合,必要数に達しているかを調べる
// 達している場合はこれ以上の変異プログラムは生成しない
if (newVariant.isCompleted()) {
foundSolutions++;
}
if (requiredSolutions <= foundSolutions) {
break;
}
}

return generatedVariants;
Expand All @@ -115,25 +137,29 @@ public enum Type {
Simple {
@Override
public Mutation initialize(final int mutationGeneratingCount, final Random random,
final int requiredSolutions,
final Scope.Type scopeType) {
final CandidateSelection candidateSelection =
new RouletteStatementAndConditionSelection(random);
return new SimpleMutation(mutationGeneratingCount, random, candidateSelection, scopeType);
return new SimpleMutation(mutationGeneratingCount, random, candidateSelection,
requiredSolutions, scopeType);
}
},

Heuristic {
@Override
public Mutation initialize(final int mutationGeneratingCount, final Random random,
final int requiredSolutions,
final Scope.Type scopeType) {
final CandidateSelection candidateSelection =
new HeuristicStatementSelection(random);
return new HeuristicMutation(mutationGeneratingCount, random, candidateSelection,
requiredSolutions,
scopeType);
}
};

public abstract Mutation initialize(final int mutationGeneratingCount, final Random random,
final Scope.Type scopeType);
final int requiredSolutions, final Scope.Type scopeType);
}
}
Loading

0 comments on commit 2bb09a5

Please sign in to comment.