Skip to content

Commit

Permalink
prototype automata propagator
Browse files Browse the repository at this point in the history
  • Loading branch information
breandan committed Apr 27, 2024
1 parent 6bf7d44 commit 296edd2
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 1 deletion.
2 changes: 2 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ kotlin {
// MPJ (required for Poon's SPN)
// implementation(files("$projectDir/libs/mpj-0.44.jar"))

implementation(files("$projectDir/jautomata-0.0.1-SNAPSHOT.jar"))

implementation("org.sosy-lab:common:0.3000-529-g6152d88")
implementation("org.sosy-lab:java-smt:4.1.1")

Expand Down
Binary file added jautomata-0.0.1-SNAPSHOT.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion latex/splash2024/splash.tex
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@

\section{Example}

Syntax errors are usually fixable with a small number of edits. If we assume the intended repair contains just a few edits, this imposes strongly locality constraints on the space of possible edits. For example, let us consider the following Python snippet, which contains a small syntax error:\\
Syntax errors are usually fixable with a small number of edits. If we assume the intended repair contains just a few edits, this imposes strong locality constraints on the space of possible edits. For example, let us consider the following Python snippet, which contains a small syntax error:\\

\texttt{def prepend(i, k, L=[]) n and [prepend(i - 1, k, [b] + L) for b in range(k)]}\\

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,16 @@ class PTree(val root: String = ".ε", val branches: List<Π2A<PTree>> = listOf()
else branches.maxOf { (l, r) -> maxOf(l.depth, r.depth) + 1 }
}

fun <T> propagator(
both: (T?, T?) -> T?,
either: (T?, T?) -> T?,
unit: (PTree) -> T?
): T? =
if (branches.isEmpty()) if("ε" in root) null else unit(this)
else branches.map { (l, r) ->
both(l.propagator(both, either, unit), r.propagator(both, either, unit))
}.reduce { acc, t -> either(acc, t) }

private val choice by lazy {
if (branches.isEmpty()) listOf(epsStr)
else shuffledBranches.flatMap { (l, r) ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ fun CFG.jvmIntersectLevFSA(fsa: FSA, parikhMap: ParikhMap = this.parikhMap): CFG
// .also { it.forEach { println("${it.LHS} -> ${it.RHS.joinToString(" ")}") } }
// .intersectLevFSAP(fsa)

fun CFG.makeLevPTree(toRepair: Σᐩ, levDist: Int = 3, parikhMap: ParikhMap = this.parikhMap): PTree =
jvmIntersectLevFSAP(makeLevFSA(toRepair, levDist), parikhMap).toPTree()

val BH_TIMEOUT = 9.minutes
val MINFREEMEM = 1000000000L
val MAX_NTS = 4_000_000 // Gives each nonterminal about ~35kb of memory on Xmx=150GB
Expand Down
58 changes: 58 additions & 0 deletions src/jvmTest/kotlin/ai/hypergraph/kaliningraph/automata/WFSATest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package ai.hypergraph.kaliningraph.automata

import ai.hypergraph.kaliningraph.parsing.*
import ai.hypergraph.kaliningraph.tokenizeByWhitespace
import io.kotest.matchers.types.shouldHaveSameHashCodeAs
import net.jhoogland.jautomata.*
import net.jhoogland.jautomata.Automaton
import net.jhoogland.jautomata.operations.*
import net.jhoogland.jautomata.semirings.RealSemiring
import kotlin.system.measureTimeMillis
import kotlin.test.Test
import kotlin.time.measureTimedValue


class WFSATest {
/*
./gradlew jvmTest --tests "ai.hypergraph.kaliningraph.automata.WFSATest.testWFSA"
*/
@Test
fun testWFSA() {
val a: Automaton<String, Double> =
EditableAutomaton<String, Double>(RealSemiring()).apply {
val s1: Int = addState(1.0, 0.0) // Create initial state (initial weight 1.0, final weight 0.0)
val s2: Int = addState(0.0, 1.0) // Create final state (initial weight 0.0, final weight 1.0)
addTransition(s1, s2, "b", 0.4) // Create transition from s1 to s2
addTransition(s2, s2, "a", 0.6) // Create transition from s2 to s2
} // probabilistic semiring uses RealSemiring

val aa = Concatenation(*Array(100) { a })

for (i in 0 until 10000 step 1000)
measureTimedValue { Automata.bestStrings(aa, i) }
.also { println("Took ${it.duration} to decode ${it.value.size} best strings") }
}

/*
./gradlew jvmTest --tests "ai.hypergraph.kaliningraph.automata.WFSATest.testLBHRepair"
*/
@Test
fun testLBHRepair() {
val toRepair = "NAME : NEWLINE NAME = STRING NEWLINE NAME = NAME . NAME ( STRING ) NEWLINE"
Grammars.seq2parsePythonCFG.makeLevPTree(toRepair, 2)
.propagator<Automaton<String, Double>>(
both = { a, b -> if (a == null) b else if (b == null) a else Concatenation(a, b) },
either = { a, b -> if (a == null) b else if (b == null) a else Union(a, b) },
unit = { a ->
if ("ε" in a.root) null
else EditableAutomaton<String, Double>(RealSemiring()).apply {
val s1 = addState(1.0, 0.0)
val s2 = addState(0.0, 1.0)
addTransition(s1, s2, a.root, 1.0)
}
}
).also { println("Total: ${Automata.transitions(it).size} arcs, ${Automata.states(it).size}") }
.let { Automata.bestStrings(it, 1000).map { it.label.joinToString(" ") } }
.forEach { println(levenshteinAlign(toRepair, it).paintANSIColors()) }
}
}

0 comments on commit 296edd2

Please sign in to comment.