Skip to content

Commit 0ee3a23

Browse files
committed
changes to LIPSAlgorithm.kt
1 parent 2455f5a commit 0ee3a23

File tree

1 file changed

+75
-10
lines changed

1 file changed

+75
-10
lines changed

core/src/main/kotlin/org/evomaster/core/search/algorithms/LIPSAlgorithm.kt

Lines changed: 75 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,38 @@ import org.evomaster.core.search.algorithms.wts.WtsEvalIndividual
1717
class LIPSAlgorithm<T> : AbstractGeneticAlgorithm<T>() where T : Individual {
1818

1919
private var currentTarget: Int? = null
20+
private val budgetLeftPerTarget: MutableMap<Int, Int> = mutableMapOf()
2021

2122
override fun getType(): EMConfig.Algorithm = EMConfig.Algorithm.LIPS
2223

24+
override fun initPopulation() {
25+
population.clear()
26+
27+
// 1) Generate i
28+
val i = sampleSuite()
29+
30+
// 2) Compute uncovered
31+
val uncovered = archive.notCoveredTargets()
32+
if (uncovered.isEmpty()) {
33+
return
34+
}
35+
36+
// 3) Select current target b
37+
val target = uncovered.last()
38+
currentTarget = target
39+
frozenTargets = setOf(target)
40+
41+
// 4) initialize per-target budget
42+
val perTarget = calculatePerTargetBudget(uncovered.size)
43+
budgetLeftPerTarget.putIfAbsent(target, perTarget)
44+
45+
// 5) P <- RandomPopulation(ps-1) ∪ {i}
46+
population.add(i)
47+
while (population.size < config.populationSize) {
48+
population.add(sampleSuite())
49+
}
50+
}
51+
2352
override fun searchOnce() {
2453
beginGeneration()
2554

@@ -36,16 +65,20 @@ class LIPSAlgorithm<T> : AbstractGeneticAlgorithm<T>() where T : Individual {
3665
}
3766

3867
// Focus scoring on the single selected target
39-
frozenTargets = setOf(currentTarget!!)
40-
41-
// Ensure population exists
42-
if (population.isEmpty()) {
43-
initPopulation()
44-
}
68+
frozenTargets = setOf(currentTarget)
4569

4670
val n = config.populationSize
4771
val nextPop: MutableList<WtsEvalIndividual<T>> = formTheNextPopulation(population)
4872

73+
// record budget usage for this generation
74+
val startActions = time.evaluatedActions
75+
val startSeconds = time.getElapsedSeconds()
76+
77+
val t = currentTarget!!
78+
val targetBudgetLeft = budgetLeftPerTarget.getOrPut(t) {
79+
calculatePerTargetBudget(uncovered.size)
80+
}
81+
4982
while (nextPop.size < n) {
5083
beginStep()
5184

@@ -69,8 +102,14 @@ class LIPSAlgorithm<T> : AbstractGeneticAlgorithm<T>() where T : Individual {
69102
val a = if (score(o1) >= score(o2)) o1 else o2
70103
nextPop.add(a)
71104

72-
// Stop if time is up
73-
if (!time.shouldContinueSearch()) {
105+
// Stop if global budget or target budget is up
106+
val usedForTarget = when (config.stoppingCriterion) {
107+
EMConfig.StoppingCriterion.ACTION_EVALUATIONS -> time.evaluatedActions - startActions
108+
EMConfig.StoppingCriterion.TIME -> time.getElapsedSeconds() - startSeconds
109+
else -> 0
110+
}
111+
112+
if (!time.shouldContinueSearch() || usedForTarget >= targetBudgetLeft) {
74113
endStep()
75114
break
76115
}
@@ -80,14 +119,40 @@ class LIPSAlgorithm<T> : AbstractGeneticAlgorithm<T>() where T : Individual {
80119
population.clear()
81120
population.addAll(nextPop)
82121

83-
// If target got covered (score 1 for any in pop), refresh target next time
122+
// Update budget usage for this target
123+
currentTarget?.let { target ->
124+
val usedForTarget = when (config.stoppingCriterion) {
125+
EMConfig.StoppingCriterion.ACTION_EVALUATIONS -> time.evaluatedActions - startActions
126+
EMConfig.StoppingCriterion.TIME -> time.getElapsedSeconds() - startSeconds
127+
else -> 0
128+
}
129+
budgetLeftPerTarget[target] = (budgetLeftPerTarget[target] ?: 0) - usedForTarget
130+
}
131+
132+
// Check if target is covered or out of budget
84133
val coveredNow = population.any { score(it) >= 1.0 }
85-
if (coveredNow) {
134+
val outOfBudget = currentTarget?.let { (budgetLeftPerTarget[it] ?: 1) <= 0 } ?: false
135+
136+
if (coveredNow || outOfBudget) {
86137
currentTarget = null
87138
}
88139

89140
endGeneration()
90141
}
142+
143+
/**
144+
* Calculate per-target budget based on the current stopping criterion.
145+
* Returns the fair share: total budget divided by number of uncovered targets.
146+
*/
147+
private fun calculatePerTargetBudget(uncoveredSize: Int): Int {
148+
return when (config.stoppingCriterion) {
149+
EMConfig.StoppingCriterion.ACTION_EVALUATIONS ->
150+
config.maxEvaluations / uncoveredSize
151+
EMConfig.StoppingCriterion.TIME ->
152+
config.timeLimitInSeconds() / uncoveredSize
153+
else -> Int.MAX_VALUE
154+
}
155+
}
91156
}
92157

93158

0 commit comments

Comments
 (0)