Skip to content

Commit 596bd68

Browse files
committed
Implement a demo for dynamic double lambda with ternary search in intervals.
1 parent 4acf482 commit 596bd68

File tree

1 file changed

+153
-0
lines changed

1 file changed

+153
-0
lines changed
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
package com.github.mbuzdalov.oll
2+
3+
import java.io.{FileOutputStream, PrintWriter}
4+
import java.util.concurrent.{Callable, ScheduledThreadPoolExecutor}
5+
6+
import com.github.mbuzdalov.util.MathEx
7+
8+
object BestDynamicDoubleLambda {
9+
class Evaluator(ollComputation: OLLComputation, nonCachingComputation: OLLComputation, output: Option[String]) {
10+
private val n = ollComputation.n
11+
private val lambdas: Array[Double] = Array.ofDim(n + 1)
12+
private val runtimes: Array[Double] = Array.ofDim(n + 1)
13+
14+
val totalRuntime: Double = {
15+
runtimes(n) = 0.0
16+
17+
val pool = new ScheduledThreadPoolExecutor(Runtime.getRuntime.availableProcessors())
18+
val pw = output.map(name => new PrintWriter(new FileOutputStream(name), true))
19+
pw.foreach(ollComputation.logConfiguration)
20+
pw.foreach(_.println("fitness,best-lambda,runtime-to-optimum"))
21+
22+
val eps = 1e-8
23+
24+
var x = n
25+
while (x > 0) {
26+
x -= 1
27+
// Choosing best discrete lambda
28+
var bestLambda = 0.0
29+
var bestValue = Double.PositiveInfinity
30+
31+
val tasks = new java.util.ArrayList[Callable[Double]](n)
32+
33+
def smallestLambda(popSize: Int): Double = math.max(1, popSize - 0.5)
34+
def largestLambda(popSize: Int): Double = math.min(n, math.nextDown(popSize + 0.5))
35+
36+
for (popSize <- 1 to n) {
37+
val smallest = smallestLambda(popSize)
38+
val largest = largestLambda(popSize)
39+
tasks.add(() => ollComputation.findRuntime(parentFitness = x, lambda = smallest, populationSize = popSize, runtimes = runtimes))
40+
tasks.add(() => ollComputation.findRuntime(parentFitness = x, lambda = smallest + eps, populationSize = popSize, runtimes = runtimes))
41+
tasks.add(() => ollComputation.findRuntime(parentFitness = x, lambda = largest - eps, populationSize = popSize, runtimes = runtimes))
42+
tasks.add(() => ollComputation.findRuntime(parentFitness = x, lambda = largest, populationSize = popSize, runtimes = runtimes))
43+
}
44+
val futures = pool.invokeAll(tasks)
45+
tasks.clear()
46+
47+
for (popSize <- 1 to n) {
48+
val smallest = smallestLambda(popSize)
49+
val largest = largestLambda(popSize)
50+
val value0 = futures.get(4 * (popSize - 1) + 0).get()
51+
val value1 = futures.get(4 * (popSize - 1) + 1).get()
52+
val value2 = futures.get(4 * (popSize - 1) + 2).get()
53+
val value3 = futures.get(4 * (popSize - 1) + 3).get()
54+
55+
if (value1 < value0 && value2 < value3) {
56+
var left = smallest
57+
var right = largest
58+
var myBestLambda = -1.0
59+
var myBestValue = Double.PositiveInfinity
60+
val pieces = math.max(2, Runtime.getRuntime.availableProcessors())
61+
var iteration = 100
62+
var changed = true
63+
while (iteration > 0 && changed) {
64+
changed = false
65+
iteration -= 1
66+
for (t <- 0 until pieces) {
67+
val thisLambda = (left * (pieces - t) + right * (t + 1)) / (pieces + 1)
68+
tasks.add(() => nonCachingComputation.findRuntime(parentFitness = x, lambda = thisLambda, populationSize = popSize, runtimes = runtimes))
69+
}
70+
val ternaryFutures = pool.invokeAll(tasks)
71+
tasks.clear()
72+
var smallestIdx = 0
73+
for (t <- 1 until ternaryFutures.size()) {
74+
if (ternaryFutures.get(t).get() < ternaryFutures.get(smallestIdx).get()) {
75+
smallestIdx = t
76+
}
77+
}
78+
val smallestValue = ternaryFutures.get(smallestIdx).get()
79+
val smallestLambda = (left * (pieces - smallestIdx) + right * (smallestIdx + 1)) / (pieces + 1)
80+
val newLeft = (left * (pieces - smallestIdx + 1) + right * smallestIdx) / (pieces + 1)
81+
val newRight = (left * (pieces - smallestIdx - 1) + right * (smallestIdx + 2)) / (pieces + 1)
82+
if (smallestValue < myBestValue) {
83+
myBestValue = smallestValue
84+
myBestLambda = smallestLambda
85+
}
86+
changed = (left != newLeft) || (right != newRight)
87+
left = newLeft
88+
right = newRight
89+
}
90+
assert(myBestValue <= value0 && myBestValue <= value1 && myBestValue <= value2 && myBestValue <= value3)
91+
println(s"[warning] x=$x, popSize=$popSize: special minimum needed! $value0, $value1, $value2, $value3. Lambdas are $smallest and $largest. $myBestLambda => $myBestValue")
92+
if (myBestValue < bestValue) {
93+
bestValue = myBestValue
94+
bestLambda = myBestLambda
95+
}
96+
} else if (value0 < value3 && value1 < value0 || value3 < value0 && value2 < value3) {
97+
println(s"[ERROR] x=$x, popSize=$popSize: Some serious non-monotone shit happens! $value0, $value1, $value2, $value3")
98+
} else {
99+
if (value0 < bestValue) {
100+
bestValue = value0
101+
bestLambda = smallest
102+
}
103+
if (value3 < bestValue) {
104+
bestValue = value3
105+
bestLambda = largest
106+
}
107+
}
108+
}
109+
runtimes(x) = bestValue
110+
lambdas(x) = bestLambda
111+
112+
pw.foreach(_.println(s"$x,$bestLambda,$bestValue"))
113+
}
114+
115+
pw.foreach(_.close())
116+
pool.shutdown()
117+
MathEx.expectedRuntimeOnBitStrings(n, runtimes)
118+
}
119+
}
120+
121+
def main(args: Array[String]): Unit = {
122+
val n = args(0).toInt
123+
val cmd = new CommandLineArgs(args)
124+
val printSummary = cmd.getBoolean("print-summary")
125+
val t0 = System.nanoTime()
126+
127+
val nonCachingCrossoverComputation = CrossoverComputation.findMathCapableImplementation(cmd, "crossover-math")
128+
val crossoverComputation = new InMemoryCostPrioritizingCrossoverCache(
129+
maxCacheByteSize = cmd.getLong("max-cache-byte-size"),
130+
delegate = nonCachingCrossoverComputation,
131+
verbose = true)
132+
133+
val nonCachingOLLComputation = new OLLComputation(n,
134+
neverMutateZeroBits = cmd.getBoolean("never-mutate-zero-bits"),
135+
includeBestMutantInComparison = cmd.getBoolean("include-best-mutant"),
136+
ignoreCrossoverParentDuplicates = cmd.getBoolean("ignore-crossover-parent-duplicates"),
137+
crossoverComputation = nonCachingCrossoverComputation)
138+
139+
val ollComputation = new OLLComputation(n,
140+
neverMutateZeroBits = cmd.getBoolean("never-mutate-zero-bits"),
141+
includeBestMutantInComparison = cmd.getBoolean("include-best-mutant"),
142+
ignoreCrossoverParentDuplicates = cmd.getBoolean("ignore-crossover-parent-duplicates"),
143+
crossoverComputation = crossoverComputation)
144+
145+
val evaluator = new Evaluator(ollComputation, nonCachingOLLComputation, output = cmd.getStringOption("output"))
146+
147+
crossoverComputation.clear()
148+
if (printSummary) {
149+
println(s"Total runtime: ${evaluator.totalRuntime}")
150+
println(s"Time consumed: ${(System.nanoTime() - t0) * 1e-9} s")
151+
}
152+
}
153+
}

0 commit comments

Comments
 (0)