Skip to content

Commit

Permalink
performance improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
breandan committed Oct 19, 2023
1 parent b1f2224 commit 6d21e7c
Show file tree
Hide file tree
Showing 16 changed files with 69 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ fun Σᐩ.hasBalancedBrackets(brackets: Set<Char> = BRACKETS): Boolean =
stack.apply { if (isNotEmpty() && c.closes(peek())) pop() else push(c) }
}.isEmpty() && brackets.any { it in this }

fun Σᐩ.splitProd() = replaceFirst("->", "").split("").map { it.trim() }
fun Σᐩ.splitProd() = replaceFirst("->", "").split('').map { it.trim() }

fun List<Σᐩ>.formatAsGrid(cols: Int = -1): FreeMatrix<Σᐩ> {
fun Σᐩ.tok() = splitProd()
Expand Down Expand Up @@ -57,7 +57,7 @@ private fun <T> List<List<T>>.col(i: Int) = map { it[i] }
// https://en.wikipedia.org/wiki/Seam_carving
fun Σᐩ.carveSeams(toRemove: Regex = Regex("\\s{2,}")): Σᐩ =
replace(" | ", " ")
.lines().filter { it.isNotBlank() }.map { it.split("") }.let { toMerge ->
.lines().filter { it.isNotBlank() }.map { it.split('') }.let { toMerge ->
val minCols = toMerge.minOf { it.size }
val takeAway = (0 until minCols).map { toMerge.col(it).minOf { toRemove.find(it)!!.value.length } }
val subs = takeAway.map { List(it) { " " }.joinToString("") }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ private infix fun CFG.intersectLevFSAP(fsa: FSA): CFG {
fsa.Q.map { (q, a, r) -> "[$q,$a,$r]" to listOf(a) }

fun Triple<Σᐩ, Σᐩ, Σᐩ>.isValid(nts: Triple<Σᐩ, Σᐩ, Σᐩ>): Boolean {
fun Σᐩ.coords() =
substringAfter("_").split("/")
.let { (i, j) -> i.toInt() to j.toInt() }
fun Σᐩ.coords(): Pair<Int, Int> = drop(2).run {
(length / 2).let {substring(0,it).toInt() to substring(it + 1).toInt() }
}

fun Pair<Int, Int>.dominates(other: Pair<Int, Int>) =
first <= other.first && second <= other.second
Expand Down Expand Up @@ -151,7 +151,7 @@ infix fun CFG.intersect(fsa: FSA): CFG {
// Tracks the number of tokens a given nonterminal can represent
// e.g., a NT with a Parikh bound of 1..3 can parse { s: Σ* | |s| ∈ [1, 3] }
val CFG.parikhBounds: Map<Σᐩ, IntRange> by cache {
val epsFree = noEpsilonOrNonterminalStubs
val epsFree = noEpsilonOrNonterminalStubs.freeze()
val temp = List(20) { "_" }
val map =
epsFree.nonterminals.associateWith { -1..-1 }.toMutableMap()
Expand All @@ -166,4 +166,4 @@ val CFG.parikhBounds: Map<Σᐩ, IntRange> by cache {
}

map
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ fun Σᐩ.parseFSA(): FSA {
.map { it.split("->") }
.map { (lhs, rhs) ->
val src = lhs.tokenizeByWhitespace().first()
val dst = rhs.split("|").map { it.trim() }.toSet()
val dst = rhs.split('|').map { it.trim() }.toSet()
val sym = if ("-<" in lhs && lhs.endsWith(">"))
lhs.split("-<").last().dropLast(1) else ""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,19 @@ fun CFG.levenshteinRepair(maxDist: Int, unparseable: List<Σᐩ>, solver: CJL.(L
fun makeLevFSA(str: Σᐩ, dist: Int, alphabet: Set<Σᐩ>): FSA =
makeLevFSA(str.tokenizeByWhitespace(), dist, alphabet)

fun makeLevFSA(str: List<Σᐩ>, dist: Int, alphabet: Set<Σᐩ>): FSA =
(upArcs(str, dist, alphabet) +
diagArcs(str, dist, alphabet) +
str.mapIndexed { i, it -> rightArcs(i, dist, it) }.flatten() +
str.mapIndexed { i, it -> knightArcs(i, dist, it) }.flatten()).let { Q ->
val initialStates = setOf("q_0/0")
fun makeLevFSA(
str: List<Σᐩ>,
dist: Int,
alphabet: Set<Σᐩ>,
digits: Int = (str.size * dist).toString().length
): FSA =
(upArcs(str, dist, alphabet, digits) +
diagArcs(str, dist, alphabet, digits) +
str.mapIndexed { i, it -> rightArcs(i, dist, it, digits) }.flatten() +
str.mapIndexed { i, it -> knightArcs(i, dist, it, digits) }.flatten()).let { Q ->
val initialStates = setOf("q_" + pd(0, digits).let { "$it/$it" })
fun Σᐩ.unpackCoordinates() =
substringAfter("_").split("/")
substringAfter('_').split('/')
.let { (i, j) -> i.toInt() to j.toInt() }

val finalStates = mutableSetOf<String>()
Expand All @@ -69,23 +74,45 @@ fun makeLevFSA(str: List<Σᐩ>, dist: Int, alphabet: Set<Σᐩ>): FSA =
FSA(Q, initialStates, finalStates)
}

fun upArcs(str: List<Σᐩ>, dist: Int, alphabet: Set<Σᐩ>): TSA =
fun pd(i: Int, digits: Int) = i.toString().padStart(digits, '0')

fun upArcs(str: List<Σᐩ>, dist: Int, alphabet: Set<Σᐩ>, digits: Int): TSA =
((0..<str.size+dist).toSet() * (1..dist).toSet() * alphabet)
.filter { (i, _, s) -> str.size <= i || str[i] != s }
.filter { (i, j, _) -> i <= str.size || i - str.size < j }
.map { (i, j, s) -> "q_$i/${j-1}" to s to "q_$i/$j" }.toSet()
.map { (i, j, s) -> i to j-1 to s to i to j }
.map { (a, b, s, d, e) ->
pd(a, digits) to pd(b, digits) to s to pd(d, digits) to pd(e, digits)
}.map { (a, b, s, d, e) ->
"q_$a/$b" to s to "q_$d/$e"
}.toSet()

fun diagArcs(str: List<Σᐩ>, dist: Int, alphabet: Set<Σᐩ>): TSA =
fun diagArcs(str: List<Σᐩ>, dist: Int, alphabet: Set<Σᐩ>, digits: Int): TSA =
((1..<str.size+dist).toSet() * (1..dist).toSet() * alphabet)
.filter { (i, _, s) -> str.size <= i - 1 || str[i-1] != s }
.filter { (i, j, _) -> i <= str.size || i - str.size <= j }
.map { (i, j, s) -> "q_${i-1}/${j-1}" to s to "q_$i/$j" }.toSet()
.map { (i, j, s) -> i-1 to j-1 to s to i to j }
.map { (a, b, s, d, e) ->
pd(a, digits) to pd(b, digits) to s to pd(d, digits) to pd(e, digits)
}.map { (a, b, s, d, e) ->
"q_$a/$b" to s to "q_$d/$e"
}.toSet()

fun rightArcs(idx: Int, dist: Int, letter: Σᐩ): TSA =
fun rightArcs(idx: Int, dist: Int, letter: Σᐩ, digits: Int): TSA =
(setOf(idx + 1) * (0..dist).toSet() * setOf(letter))
.map { (i, j, s) -> "q_${i-1}/$j" to s to "q_$i/$j" }.toSet()
.map { (i, j, s) -> i-1 to j to s to i to j }
.map { (a, b, s, d, e) ->
pd(a, digits) to pd(b, digits) to s to pd(d, digits) to pd(e, digits)
}.map { (a, b, s, d, e) ->
"q_$a/$b" to s to "q_$d/$e"
}.toSet()

fun knightArcs(idx: Int, dist: Int, letter: Σᐩ): TSA =
fun knightArcs(idx: Int, dist: Int, letter: Σᐩ, digits: Int): TSA =
if (idx <= 1) setOf()
else (setOf(idx + 1) * (1..dist).toSet() * setOf(letter))
.map { (i, j, s) -> "q_${i-2}/${j-1}" to s to "q_$i/$j" }.toSet()
.map { (i, j, s) -> i-2 to j-1 to s to i to j }
.map { (a, b, s, d, e) ->
pd(a, digits) to pd(b, digits) to s to pd(d, digits) to pd(e, digits)
}.map { (a, b, s, d, e) ->
"q_$a/$b" to s to "q_$d/$e"
}.toSet()
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ fun CFG.generateNonterminalStubs(): CFG =
.map { it.LHS to listOf("<${it.LHS}>") }.toSet()).addEpsilonProduction()

fun Σᐩ.isSyntheticNonterminal() =
split(".").size != 1 || "ε" in this || this == "START"
split('.').size != 1 || "ε" in this || this == "START"
fun Σᐩ.isOrganicNonterminal() =
split(".").size == 1 && "ε" !in this && this != "START"
split('.').size == 1 && "ε" !in this && this != "START"

// Add start symbol if none are present (e.g., in case the user forgets)
private fun CFG.addGlobalStartSymbol(): CFG =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,8 @@ class PTree(val root: String = "ε", val branches: List<Π2A<PTree>> = listOf())

private fun decodeString(i: BigInteger): Pair<String, BigInteger> {
if (branches.isEmpty()) return (if ("ε" in root) "" else root) to i
val (quotient1, remainder) =
i.div(branches.size) to i.mod(branches.size.toBigInteger())
val (lb, rb) = shuffledBranches[remainder.toString().toInt()]
val (quotient1, remainder) = i.divrem(branches.size.toBigInteger())
val (lb, rb) = shuffledBranches[remainder.intValue()]
val (l, quotient2) = lb.decodeString(quotient1)
val (r, quotient3) = rb.decodeString(quotient2)
val concat = (if(l.isEmpty()) r else if(r.isEmpty()) l else "$l $r")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,13 @@ operator fun <T> Set<T>.contains(s: Set<T>) = containsAll(s)
flatMap { s.map(it::to) }

@JvmName("cartProdPair") operator fun <E: Π2<A, B>, A, B, Z> Set<E>.times(s: Set<Z>): Set<Π3<A, B, Z>> =
flatMap { s.map(it::to).toSet() }.toSet()
flatMap { s.map(it::to) }.toSet()

@JvmName("cartProdPairPair") operator fun <A, B, C, D> Set2<A, B>>.times(s: Set<Π2<C, D>>): Set<Π2<Π2<A, B>, Π2<C, D>>> =
flatMap { s.map(it::to).toSet() }.toSet()
flatMap { s.map(it::to) }.toSet()

@JvmName("cartProdTriple") operator fun <E: Π3<A, B, C>, A, B, C, Z> Set<E>.times(s: Set<Z>): Set<Π4<A, B, C, Z>> =
flatMap { s.map(it::to).toSet() }.toSet()
flatMap { s.map(it::to) }.toSet()

// IDK why the Kotlin stdlib provides these for Map but not Set
public inline fun <T> Set<T>.filter(noinline predicate: (T) -> Boolean): Set<T> =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ class BarHillelTest {
@Test
fun testPythonBarHillel() {
val gram = Grammars.seq2parsePythonCFG.noEpsilonOrNonterminalStubs
val toRepair = "NAME = ( NAME .".tokenizeByWhitespace()
val toRepair = "NAME = ( NAME . NAME ( NAME NEWLINE".tokenizeByWhitespace()
val levBall = makeLevFSA(toRepair, 3, gram.terminals)
val intGram = gram.intersectLevFSA(levBall)
// .also { println("LEV ∩ CFG grammar:\n${it.pretty}") }
Expand Down
2 changes: 1 addition & 1 deletion src/jsMain/kotlin/Client.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import kotlin.js.Promise
@OptIn(ExperimentalStdlibApi::class)
fun main() {
window.onhashchange = {
when (it.newURL.substringAfter("#")) {
when (it.newURL.substringAfter('#')) {
"prefattach" -> prefAttach()
"rewriter" -> rewriter()
"cfgparser" -> cfgParser()
Expand Down
2 changes: 1 addition & 1 deletion src/jsMain/kotlin/Valiant.kt
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ fun cfgParser(
val chunks = mutableList.mapIndexedNotNull { i, lbl ->
val aVert = last[{ it.label == lbl }].first()
val nonterminals =
last[{ it.label == lbl.substringAfter(":") }].first().neighbors
last[{ it.label == lbl.substringAfter(':') }].first().neighbors
if (nonterminals.isNotEmpty()) {
val mergeLabel = nonterminals.joinToString(",") { "$i:${it.label}" }
newList.add(mergeLabel)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ fun SATRubix.eliminateImpossibleDerivations(cfg: CFG, tokens: List<Σᐩ>): SATR

// Naming convention: HV_r::${r}_c::${c}..._f::${idx}
fun Variable.toRowColNT(cfg: CFG): Π3<Int, Int, String> {
val (r, c, idx) = name().split("_").let { it[1].substringAfter("r::").toInt() to
val (r, c, idx) = name().split('_').let { it[1].substringAfter("r::").toInt() to
it[2].substringAfter("c::").toInt() to it.last().substringAfter("f::").toInt() }
return Π(r, c, cfg.bindex[idx])
}
Expand Down
2 changes: 1 addition & 1 deletion src/jvmMain/kotlin/ai/hypergraph/markovian/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ fun <T> List<T>.allMasks(): List<List<T?>> =
}

fun String.execute() =
ProcessBuilder(also { println("Executing: $it") }.split(" ")).start().waitFor()
ProcessBuilder(also { println("Executing: $it") }.split(' ')).start().waitFor()
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ fun main() {
val isogram = ('a'..'z').shuffled().joinToString("")
val message = "meet me at secret location at noon on wednesday"
val ciphertext = encrypt(isogram, message)
val cipherwords = ciphertext.split(" ")
val cipherwords = ciphertext.split(' ')

val possibleWords = FastListMultimap.newMultimap<String, String>()
for (word in cipherwords)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class SATValiantBenchmarks {
fun List<Double>.stddev() = average().let { μ -> map { (it - μ).pow(2) } }.average().pow(0.5)

fun String.dropHoles(i: Int = 4, idxs: Set<Int> = indices.shuffled().take(i).toSet()) =
split(" ").mapIndexed { i, it -> if (i in idxs) "_" else it }.joinToString(" ")
split(' ').mapIndexed { i, it -> if (i in idxs) "_" else it }.joinToString(" ")

val numSamples = 20
var data = "holes, d1, d1err, d2, d2err, d3, d3err, d4, d4err"
Expand Down Expand Up @@ -57,7 +57,7 @@ class SATValiantBenchmarks {
average().let { μ -> map { (it - μ).pow(2) } }.average().pow(0.5)

fun String.makeError(i: Int = 4, idxs: Set<Int> = indices.shuffled().take(i).toSet()): String =
split(" ").mapIndexed { i, it -> if (i in idxs) "" else it }.joinToString(" ")
split(' ').mapIndexed { i, it -> if (i in idxs) "" else it }.joinToString(" ")

val numSamples = 10
var data = "errors, d1, d1err, d2, d2err, d3, d3err, d4, d4err"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ class SATValiantTest {
println(cfg.prettyPrint())

"_ _ _ _ _ _".also { println("$it is being synthesized...") }
.split(" ").genCandidates(cfg)
.split(' ').genCandidates(cfg)
.filter { (it.matches(cfg) to it.hasBalancedBrackets())
.also { (valiant, stack) ->
// Should never see either of these statements if we did our job correctly
Expand Down Expand Up @@ -585,7 +585,7 @@ class SATValiantTest {
.take(10).toList().also { assert(it.isNotEmpty()) }
.map {
println(it)
val (left, right) = it.split("=")
val (left, right) = it.split('=')
val (ltree, rtree) = arith.parse(left)!! to arith.parse(right)!!
val (leval, reval) = ltree.eval() to rtree.eval()
println("$leval = $reval")
Expand Down Expand Up @@ -838,7 +838,7 @@ class SATValiantTest {

// Deletes two random characters from each string
val corruptedStrings =
strings.map { val tokens = it.split(" ")
strings.map { val tokens = it.split(' ')
val toDelete = tokens.indices.shuffled().take(2)
tokens.filterIndexed { i, _ -> i !in toDelete }.joinToString(" ")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,6 @@ fun String.runVHDL(name: String = "hello") {

fun runCommand(command: String): Boolean =
try {
ProcessBuilder(*command.split(" ").toTypedArray())
ProcessBuilder(*command.split(' ').toTypedArray())
.redirectOutput(INHERIT).redirectError(INHERIT).start().waitFor(60, MINUTES)
} catch (e: Exception) { false }

0 comments on commit 6d21e7c

Please sign in to comment.