Skip to content

Commit

Permalink
Implement successor lookahead
Browse files Browse the repository at this point in the history
  • Loading branch information
jedlimlx committed May 15, 2024
1 parent 1c97b38 commit 9b9540d
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 43 deletions.
70 changes: 41 additions & 29 deletions src/commonMain/kotlin/search/cfind/CFind.kt
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ class CFind(
if (symmetry != ShipSymmetry.GLIDE || direction != Coordinate(1, 1)) {
// Compute the offsets
var initialCount = 0
for (i in 0 ..<k) {
for (i in 0 ..<2*k) {
var count = initialCount
val lst = arrayListOf(initialCount)
while (count < period * k) {
Expand Down Expand Up @@ -273,7 +273,7 @@ class CFind(

// Initialising the transposition table
@OptIn(ExperimentalUnsignedTypes::class)
val equivalentStates: LRUCache<Int, UShortArray> = LRUCache(transpositionTableSize)
val equivalentStates: HashMap<Int, UShortArray> = HashMap(transpositionTableSize)

// Computing the rows that should be used in computing the next state
val indices = Array(period) { phase ->
Expand Down Expand Up @@ -345,30 +345,39 @@ class CFind(
}.toList()
val lookaheadDepth = maxLookaheadDepth.map { minOf(lookaheadDepth, it) }

val successorLookaheadDepth = tempIndices.map { it[0].last() }.indexOf(0) + 1
// val successorLookahead = (0..<period).map { phase ->
// val lst = tempIndices.map { it[phase] }
// lst.map {
// val target = it[0] - indices[0][0]
// val known = setOf(0) //+ lookaheadIndices.subList(0, lookaheadDepth[phase]).map { it[phase][0] - indices[phase][0] }.toSet()
// for (i in lst) {
// if (i.indexOf(target) == i.size - 1 && lst[indexToRowMap[centralHeight] - 1] in known) {
// return@map
// }
// }

// -1
// }
// }

val successorLookahead = this.lookaheadDepth.map {
it > 0 && (successorLookaheadDepth == it + 1 || tempIndices[0][1].last() == 0)
val successorLookahead = (0..<period).map { phase ->
val lst = (listOf(indices) + tempIndices).map { it[phase] }
var count = 0
lst.subList(0, this.lookaheadDepth.max() + 1).map {
val target = it[0] - indices[0][0]
val known = setOf(0) + tempIndices.subList(0, count++).map { it[phase][0] - indices[phase][0] }.toSet()
for (i in lst.indices) {
if (lst[i].indexOf(target) == lst[i].size - 1) {
val centralRow = lst[i][indexToRowMap[centralHeight] - 1]
if (centralRow in known || centralRow > 0)
return@map i
}
}

-1
}
}
val successorLookaheadIndices = successorLookahead.mapIndexed { phase, lst ->
lst.filter { it > 0 }.map { tempIndices[it - 1][phase] }
}
val successorLookaheadIndex = successorLookahead.map { lst ->
var count = 0
lst.filter { it > 0 }.map { this.lookaheadDepth.max() + count++ }
}

val lookaheadIndices = if (this.lookaheadDepth.max() == 0) listOf() else tempIndices.subList(
0, if (successorLookahead.count { it } > 0) maxOf(successorLookaheadDepth, this.lookaheadDepth.max())
else this.lookaheadDepth.max()
)
val lookaheadIndices = if (this.lookaheadDepth.max() == 0) listOf()
else tempIndices.subList(0, this.lookaheadDepth.max()) + Array(successorLookaheadIndices.map { it.size }.max()) { depth ->
Array(period) { phase ->
if (depth < successorLookaheadIndices[phase].size)
successorLookaheadIndices[phase][depth]
else successorLookaheadIndices[phase].last()
}
}.toList()

val rawAdditionalDepth: Int = when (indices[0].indexOf(indices[0].min())) {
0 -> {
Expand Down Expand Up @@ -720,7 +729,7 @@ class CFind(
println((bold("Reverse Backoff Table: ") + "${fwdOff.toList()}"), verbosity = 1)
println((bold("Background: ") + "${background.toList()}"), verbosity = 1)
println((bold("Maximum Lookahead Depth: ") + "$maxLookaheadDepth"), verbosity = 1)
println((bold("Successor Lookahead: ") + "$successorLookaheadDepth / $successorLookahead"), verbosity = 1)
println((bold("Successor Lookahead: ") + "$successorLookahead"), verbosity = 1)
println((bold("Approximate Lookahead: ") + "$approximateLookahead"), verbosity = 1)
println((bold("Additional Depth (for lookahead): ") + "${additionalDepthArray.toList()}"), verbosity = 1)
println((bold("Lookahead Depth: ") + "$lookaheadDepth"), verbosity = 1)
Expand Down Expand Up @@ -1302,7 +1311,10 @@ class CFind(
val grid = row.toGrid(period, symmetry)
grid.rule = rule

println(brightRed(bold("\nShip found at depth ${row.depth}!")))
var predecessor = row.getPredecessor((height - 1) * period)!!
while (predecessor.hash != 0) predecessor = predecessor.predecessor!!

println(brightRed(bold("\nShip found at depth ${row.depth}, starting at ${predecessor.depth}!")))
printRLE(grid, style=brightBlue + bold)

searchResults.add(Spaceship(0, k, period, grid))
Expand Down Expand Up @@ -1370,7 +1382,7 @@ class CFind(
val phase = (row.depth + 1).mod(period)
return Pair(
indices[phase].map { row.getPredecessor(it - 1)!! }.toList(),
lookaheadIndices.subList(0, this.lookaheadDepth[phase]).map {
lookaheadIndices.map {
it[phase].map { row.getPredecessor(it - 1) }.toList()
}
)
Expand Down Expand Up @@ -1517,8 +1529,8 @@ class CFind(
val possibleSuccessorMemo = IntArray(width) { -1 }
fun possibleSuccessors(it: Int): Int {
if (possibleSuccessorMemo[it] == -1) {
if (successorLookahead[originalPhase] && lookaheadDepth == 0) {
val row = lookaheadRows.last()
if (successorLookahead[originalPhase][lookaheadDepth] > 0) {
val row = lookaheadRows[successorLookaheadIndex[originalPhase][lookaheadDepth] - lookaheadDepth]
val invert = symmetry != ShipSymmetry.GLIDE ||
(period.mod(2) == 0 && rows.last().phase == 0)
if (invert) return 3 // TODO fix this optimisation for glide-symmetric rules
Expand Down
2 changes: 1 addition & 1 deletion src/commonMain/kotlin/search/cfind/Row.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class Row(

// unique id for each row
val id = counter++
val depthPeriod = search!!.spacing
val depthPeriod = 1//search!!.spacing

val hash = run {
if (hash == null) {
Expand Down
43 changes: 30 additions & 13 deletions src/jvmMain/kotlin/Main.jvm.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import search.cfind.ShipSymmetry
import simulation.*
import java.io.File
import kotlin.random.Random
import patterns.Oscillator

actual fun main() {
// val rule = HROT("R2,C2,S6-9,14-20,B7-8,15-24,NM")
Expand Down Expand Up @@ -75,27 +76,43 @@ actual fun main() {
// "x = 0, y = 0, rule = ${it.ruleRange!!.first}\n${it.canonPhase}"
// }.joinToString("\n\n"))

val transitions: MutableList<List<Int>> = arrayListOf()
val weights = arrayOf(3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2)
for (i in 0..<(1 shl 12)) {
val string = i.toString(2).padStart(12, '0')
val cells = string.map { it.digitToInt() }
// val transitions: MutableList<List<Int>> = arrayListOf()
// val weights = arrayOf(3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2)
// for (i in 0..<(1 shl 12)) {
// val string = i.toString(2).padStart(12, '0')
// val cells = string.map { it.digitToInt() }

val sum = cells.mapIndexed { index, it -> weights[index] * it }.sum()
if (sum in 9 .. 11 || sum == 4)
transitions.add(cells)
}
// val sum = cells.mapIndexed { index, it -> weights[index] * it }.sum()
// if (sum in 9 .. 11 || sum == 4)
// transitions.add(cells)
// }

// println(R2VonNeumannINT(transitions).transitionString)

println(R2VonNeumannINT(transitions).transitionString)
// val pattern = "b3o\$2o2bo\$2o2bo\$b4o\$2b2o9\$2b2o\$b4o\$2o2bo\$2o2bo\$b3o!"
// val ship = SparseGrid("b3o\$2o2bo\$2o2bo\$b4o\$2b2o!", HROT("R2,C2,S6-9,B7-8,NM")).identify()!!

// var count = 0
// val range = ship.ruleRange!!.first as HROT .. ship.ruleRange!!.second as HROT
// //println("${range.size} rules to search.")
// for (i in range.randomSequence()) {
// val test = DenseGrid(pattern, i)
// val output = test.identify(200)
// if (output != null && (output as Spaceship).period > 1)
// println("$i, ${output}")

// if ((count++).mod(1000) == 0)
// println("Searched $count...")
// }

//val ruletable = ruletableFromFile("SoManyShips3.rule")

// B2-ei3cjkr4cektyz5-cnr6-ik78/S01e2-ae3cnqry4cqrtwyz5-ain6ekn7e
// HROT("R2,C2,S6-11,B4,9-11,NW0020003330230320333000200")
val search = CFind(
HROT("R3,C2,S2,B3,N+"), 4, 3, 8, ShipSymmetry.ODD,
verbosity = 1, searchStrategy = SearchStrategy.PRIORITY_QUEUE, lookaheadDepth = 0,
direction = Coordinate(1, 1), numThreads = 8
HROT("R2,C2,S0,B2,N+"), 2, 1, 8, ShipSymmetry.ODD,
verbosity = 1, searchStrategy = SearchStrategy.HYBRID_BFS, //lookaheadDepth = 1, //stdin = true,
direction = Coordinate(1, 1), numThreads = 8, lookaheadDepth = 2
)
search.search()

Expand Down

0 comments on commit 9b9540d

Please sign in to comment.