-
Notifications
You must be signed in to change notification settings - Fork 95
Standard Genetic Algorithm #1079
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
d5f37fa
Implement Genetic Algorithm
amidgol f38c5ff
Implement crossover
amidgol f10cd0e
refactored with parametererized tests
arcuri82 eaecfbb
Modify GA and make it pass the test
amidgol e228941
Implement monotonic GA
amidgol f52bcc4
Inherit Monotonic from Wts
amidgol 7498a14
Add SteadyState GA
amidgol 23c6887
Remove redundant GeneticAlgorithm
amidgol 206fa10
Merge branch 'master' into feat-steadyStateGA
amidgol 308de02
Add StandardGA
amidgol 3d94fe4
Implement Elitism in StandardGA
amidgol 2d3a8eb
Add elitesCount to EMConfig
amidgol 12575f0
Fix forming the next population
amidgol a24653d
Assert if the best solution's fitness does not decrease
amidgol f2c889e
Keep the Standard GA
amidgol 60fcd2b
Address some issues
amidgol 2681001
Implement tournament selection inside standard GA
amidgol e052e19
Add a todo
amidgol d0cbc6c
Add AbstractGA
amidgol 3442144
Update StandardGeneticAlgorithm
amidgol 9c86ac9
Fix issue in StandardGA's name
amidgol 343b2d6
Update AbstractGeneticAlgorithm.kt
amidgol aa48470
Change mutation strategy
amidgol c8212ec
Add an incomplete test for Standard GA
amidgol 77ef833
Merge branch 'master' into feat-standardGA
amidgol 64f1079
Update StandardGeneticAlgorithmTest.kt
amidgol 8787bbf
improved test readability
arcuri82 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -169,3 +169,4 @@ Migrations/ | |
/e2e-tests/emb-json/target/ | ||
/process_data/ | ||
/e2e-tests/spring-rest-multidb/target/ | ||
.DS_Store |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
109 changes: 109 additions & 0 deletions
109
core/src/main/kotlin/org/evomaster/core/search/algorithms/AbstractGeneticAlgorithm.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
package org.evomaster.core.search.algorithms | ||
|
||
import org.evomaster.core.search.Individual | ||
import org.evomaster.core.search.algorithms.wts.WtsEvalIndividual | ||
import org.evomaster.core.search.service.SearchAlgorithm | ||
|
||
abstract class AbstractGeneticAlgorithm<T>: SearchAlgorithm<T>() where T : Individual { | ||
|
||
private val population: MutableList<WtsEvalIndividual<T>> = mutableListOf() | ||
|
||
override fun setupBeforeSearch() { | ||
population.clear() | ||
|
||
initPopulation() | ||
} | ||
|
||
protected open fun initPopulation() { | ||
|
||
val n = config.populationSize | ||
|
||
for (i in 1..n) { | ||
population.add(sampleSuite()) | ||
|
||
if (!time.shouldContinueSearch()) { | ||
break | ||
} | ||
} | ||
} | ||
|
||
protected fun formTheNextPopulation(population: MutableList<WtsEvalIndividual<T>>): MutableList<WtsEvalIndividual<T>> { | ||
|
||
val nextPop: MutableList<WtsEvalIndividual<T>> = mutableListOf() | ||
|
||
if (config.elitesCount > 0 && population.isNotEmpty()) { | ||
var sortedPopulation = population.sortedByDescending { it.calculateCombinedFitness() } | ||
|
||
var elites = sortedPopulation.take(config.elitesCount) | ||
|
||
nextPop.addAll(elites) | ||
} | ||
|
||
return nextPop | ||
} | ||
|
||
protected fun mutate(wts: WtsEvalIndividual<T>) { | ||
|
||
val op = randomness.choose(listOf("del", "add", "mod")) | ||
val n = wts.suite.size | ||
when (op) { | ||
"del" -> if (n > 1) { | ||
val i = randomness.nextInt(n) | ||
wts.suite.removeAt(i) | ||
} | ||
"add" -> if (n < config.maxSearchSuiteSize) { | ||
ff.calculateCoverage(sampler.sample(), modifiedSpec = null)?.run { | ||
archive.addIfNeeded(this) | ||
wts.suite.add(this) | ||
} | ||
} | ||
"mod" -> { | ||
val i = randomness.nextInt(n) | ||
val ind = wts.suite[i] | ||
|
||
getMutatator().mutateAndSave(ind, archive) | ||
?.let { wts.suite[i] = it } | ||
} | ||
} | ||
} | ||
|
||
protected fun xover(x: WtsEvalIndividual<T>, y: WtsEvalIndividual<T>) { | ||
|
||
val nx = x.suite.size | ||
val ny = y.suite.size | ||
|
||
val splitPoint = randomness.nextInt(Math.min(nx, ny)) | ||
|
||
(0..splitPoint).forEach { | ||
val k = x.suite[it] | ||
x.suite[it] = y.suite[it] | ||
y.suite[it] = k | ||
} | ||
} | ||
|
||
protected fun tournamentSelection(): WtsEvalIndividual<T>{ | ||
val selectedIndividuals = randomness.choose(population, config.tournamentSize) | ||
val bestIndividual = selectedIndividuals.maxByOrNull { it.calculateCombinedFitness() } | ||
return bestIndividual ?: randomness.choose(population) | ||
} | ||
|
||
private fun sampleSuite(): WtsEvalIndividual<T> { | ||
|
||
val n = 1 + randomness.nextInt(config.maxSearchSuiteSize) | ||
|
||
val suite = WtsEvalIndividual<T>(mutableListOf()) | ||
|
||
for (i in 1..n) { | ||
ff.calculateCoverage(sampler.sample(), modifiedSpec = null)?.run { | ||
archive.addIfNeeded(this) | ||
suite.suite.add(this) | ||
} | ||
|
||
if (!time.shouldContinueSearch()) { | ||
break | ||
} | ||
} | ||
|
||
return suite | ||
} | ||
} |
57 changes: 57 additions & 0 deletions
57
core/src/main/kotlin/org/evomaster/core/search/algorithms/StandardGeneticAlgorithm.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package org.evomaster.core.search.algorithms | ||
|
||
import org.evomaster.core.EMConfig | ||
import org.evomaster.core.search.Individual | ||
import org.evomaster.core.search.algorithms.wts.WtsEvalIndividual | ||
|
||
/** | ||
* An implementation of the Standard Genetic algorithm, | ||
*/ | ||
open class StandardGeneticAlgorithm<T> : AbstractGeneticAlgorithm<T>() where T : Individual { | ||
|
||
|
||
private val population: MutableList<WtsEvalIndividual<T>> = mutableListOf() | ||
|
||
override fun getType(): EMConfig.Algorithm { | ||
return EMConfig.Algorithm.STANDARD_GA | ||
} | ||
|
||
override fun searchOnce() { | ||
|
||
val n = config.populationSize | ||
|
||
val nextPop = formTheNextPopulation(population) | ||
|
||
while (nextPop.size < n) { | ||
|
||
val sizeBefore = nextPop.size | ||
|
||
val x = tournamentSelection() | ||
val y = tournamentSelection() | ||
|
||
if (randomness.nextBoolean(config.xoverProbability)) { | ||
xover(x, y) | ||
} | ||
|
||
if(randomness.nextBoolean(config.fixedRateMutation)){ | ||
mutate(x) | ||
} | ||
|
||
if(randomness.nextBoolean(config.fixedRateMutation)){ | ||
mutate(y) | ||
} | ||
|
||
nextPop.add(x) | ||
nextPop.add(y) | ||
|
||
assert(nextPop.size == sizeBefore + 2) | ||
|
||
if (!time.shouldContinueSearch()) { | ||
break | ||
} | ||
} | ||
|
||
population.clear() | ||
population.addAll(nextPop) | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,7 +19,7 @@ import org.evomaster.core.search.service.SearchAlgorithm | |
* of search algorithms, and not really something to | ||
* use regularly in EvoMaster | ||
*/ | ||
class WtsAlgorithm<T> : SearchAlgorithm<T>() where T : Individual { | ||
open class WtsAlgorithm<T> : SearchAlgorithm<T>() where T : Individual { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. have we clarified the difference between StandardGA and WTS? let's discuss it in meeting, with pseudo-code from paper |
||
|
||
|
||
private val population: MutableList<WtsEvalIndividual<T>> = mutableListOf() | ||
|
49 changes: 49 additions & 0 deletions
49
core/src/test/kotlin/org/evomaster/core/search/algorithms/StandardGeneticAlgorithmTest.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package org.evomaster.core.search.algorithms | ||
|
||
import com.google.inject.Injector | ||
import com.google.inject.Key | ||
import com.google.inject.Module | ||
import com.google.inject.TypeLiteral | ||
import com.netflix.governator.guice.LifecycleInjector | ||
import org.evomaster.core.BaseModule | ||
import org.evomaster.core.EMConfig | ||
import org.evomaster.core.TestUtils | ||
import org.evomaster.core.search.algorithms.onemax.OneMaxIndividual | ||
import org.evomaster.core.search.algorithms.onemax.OneMaxModule | ||
import org.evomaster.core.search.algorithms.onemax.OneMaxSampler | ||
import org.evomaster.core.search.service.ExecutionPhaseController | ||
import org.junit.jupiter.api.Test | ||
|
||
import org.junit.jupiter.api.Assertions.* | ||
|
||
class StandardGeneticAlgorithmTest { | ||
|
||
val injector: Injector = LifecycleInjector.builder() | ||
.withModules(* arrayOf<Module>(OneMaxModule(), BaseModule())) | ||
.build().createInjector() | ||
|
||
@Test | ||
fun testStandardGeneticAlgorithm() { | ||
TestUtils.handleFlaky { | ||
val standardGeneticAlgorithm = injector.getInstance( | ||
Key.get( | ||
object : TypeLiteral<StandardGeneticAlgorithm<OneMaxIndividual>>() {}) | ||
) | ||
|
||
val config = injector.getInstance(EMConfig::class.java) | ||
config.maxEvaluations = 10000 | ||
config.stoppingCriterion = EMConfig.StoppingCriterion.ACTION_EVALUATIONS | ||
|
||
val epc = injector.getInstance(ExecutionPhaseController::class.java) | ||
epc.startSearch() | ||
|
||
val solution = standardGeneticAlgorithm.search() | ||
|
||
epc.finishSearch() | ||
|
||
assertTrue(solution.individuals.size == 1) | ||
assertEquals(OneMaxSampler.DEFAULT_N.toDouble(), solution.overall.computeFitnessScore(), 0.001) | ||
} | ||
} | ||
|
||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.