From de5b097f7a61720317c9d14cdefd438924d1a058 Mon Sep 17 00:00:00 2001 From: breandan Date: Wed, 22 May 2024 17:49:46 -0400 Subject: [PATCH] debug bijection --- build.gradle.kts | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- latex/splash2024/splash.pdf | Bin 702782 -> 702799 bytes latex/splash2024/splash.tex | 6 +-- .../kaliningraph/parsing/SeqValiant.kt | 44 +++++++++++++++-- .../kaliningraph/automata/WFSATest.kt | 45 +++++++++++++++--- 6 files changed, 82 insertions(+), 17 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index dcf2c00b..22611d36 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,7 +10,7 @@ import kotlin.time.DurationUnit.MILLISECONDS plugins { signing `maven-publish` - kotlin("multiplatform") version "2.0.0-RC3" + kotlin("multiplatform") version "2.0.0" // kotlin("jupyter.api") version "0.11.0-225" id("com.github.ben-manes.versions") version "0.51.0" id("io.github.gradle-nexus.publish-plugin") version "2.0.0-rc-2" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 20db9ad5..c16cc264 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-rc-1-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/latex/splash2024/splash.pdf b/latex/splash2024/splash.pdf index 924ebae898d54b5ca6406d741d2594d5408dac08..57a58fe41a14c392d9af24b82e003b81eaec93a6 100644 GIT binary patch delta 23533 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 diff --git a/latex/splash2024/splash.tex b/latex/splash2024/splash.tex index 85220a9a..1ec1d13a 100644 --- a/latex/splash2024/splash.tex +++ b/latex/splash2024/splash.tex @@ -208,7 +208,7 @@ \node (start) [startstop, draw=none]; \node (pro1) [process, below of=start, yshift=-0.3cm] {$G_\cap \leftarrow G\cap\Delta(\err\sigma, d)$}; \node [above=0.07cm of pro1] {(\S~\ref{sec:lev_bh})}; - \node (pcfg) [io2, left of=pro1, xshift=-3cm] {[PHO]CFG}; + \node (pcfg) [io2, left of=pro1, xshift=-3cm] {[P]CFG}; \node [above=0.07cm of pcfg, xshift=1cm] {(\S~\ref{sec:prelim})}; \node (lnfa) [io, right of=pro1, xshift=3cm] {L-NFA}; \node [above=0.07cm of lnfa, xshift=1cm] {(\S~\ref{sec:lev_nfa})}; @@ -806,7 +806,7 @@ L(p) = 1 + p L(p) \phantom{addspace} P(a) = \Sigma + V + V L\big(V^2P(a)^2\big) \end{equation} - Depicted in Fig.~\ref{fig:ptree} is a partial $\mathbb{T}_2$, where red nodes are \texttt{root}s and blue nodes are \texttt{children}. The shape of type $\mathbb{T}_2$ is congruent with an acyclic CFG in Chomsky Normal Form, i.e., $\mathbb{T}_2\cong\mathcal{G}'$, so assuming the CFG recognizes a finite language, as the case for $G_\cap'$, we can translate it directly. If the language is infinite, we slice the CFL, $\mathcal{L}(G)\cap \Sigma^n$, and compute the fixpoint for each slice. + Depicted in Fig.~\ref{fig:ptree} is a partial $\mathbb{T}_2$, where red nodes are \texttt{root}s and blue nodes are \texttt{children}. The shape of type $\mathbb{T}_2$ is congruent with an acyclic CFG in Chomsky Normal Form, i.e., $\mathbb{T}_2\cong\mathcal{G}'$, so assuming the CFG recognizes a finite language, as is the case for $G_\cap'$, we can translate it directly. If the language is infinite, we slice the CFL, $\mathcal{L}(G)\cap \Sigma^n$, and compute the fixpoint for each slice. Given a porous string $\sigma: \underline\Sigma^n$ representing the slice, we can construct $\mathbb{T}_2$ from the bottom-up, and read off structures from the top-down. We construct the first upper diagonal $\hat\sigma_r = \Lambda(\sigma_r)$ as follows: @@ -1080,7 +1080,7 @@ \edge {x} {k,l} \end{tikzpicture}}\end{minipage}\begin{minipage}{5cm}\begin{align*} P(X\rightarrow KL \mid W\rightarrow XZ) &= P\big((\cdot x \cdot) \rightarrow (\cdot k \cdot)(\cdot l \cdot) \mid (\cdot w \cdot) \rightarrow (\cdot x \cdot)(\cdot z \cdot)\big) \\ &= P(K=k, L=l \mid W, X, Z)\\ &= \frac{C(K=k, L=l \mid W, X, Z)}{\sum_{k', l'}C(K=k', L=l' \mid W, X, Z)} \end{align*}\end{minipage}\end{table} - Since the parent can be a left- or right-sibling, we also consider a symmetric case: + Since the parent can be a left- or right-sibling, we should also consider the symmetric case: \begin{table}[h!] \begin{minipage}{3cm}\resizebox{.6\textwidth}{!}{\begin{tikzpicture} diff --git a/src/commonMain/kotlin/ai/hypergraph/kaliningraph/parsing/SeqValiant.kt b/src/commonMain/kotlin/ai/hypergraph/kaliningraph/parsing/SeqValiant.kt index 6720ec94..62d5eee2 100644 --- a/src/commonMain/kotlin/ai/hypergraph/kaliningraph/parsing/SeqValiant.kt +++ b/src/commonMain/kotlin/ai/hypergraph/kaliningraph/parsing/SeqValiant.kt @@ -44,6 +44,13 @@ class PTree(val root: String = ".ε", val branches: List<Π2A> = listOf() .reduce { acc, it -> acc + it } } + val ranges: List> by lazy { + if (branches.isEmpty()) listOf(BigInteger.ZERO to BigInteger.ONE) + else branches.map { (l, r) -> l.totalTrees + r.totalTrees } + .fold(listOf(BigInteger.ZERO)) { acc, it -> acc + (acc.last() + it) } + .windowed(2) { (a, b) -> a to b - 1 } + } + // e.g., if we want to prioritize shorter strings we can sort by total epsilons val numEpsilons: BigInteger by lazy { if (branches.isEmpty()) if (root == "ε") BigInteger.ONE else BigInteger.ZERO @@ -65,7 +72,7 @@ class PTree(val root: String = ".ε", val branches: List<Π2A> = listOf() either: (T?, T?) -> T?, unit: (PTree) -> T? ): T? = - if (branches.isEmpty()) if("ε" in root) null else unit(this) + 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) } @@ -88,25 +95,51 @@ class PTree(val root: String = ".ε", val branches: List<Π2A> = listOf() fun choose(): Sequence = choice.asSequence() + private fun newDecoder(i: BigInteger): String { + if (branches.isEmpty()) return epsStr +// println("Decoding $i") +// println(ranges.first().first) +// println(ranges.last().first) + val t = + if (i < ranges.first().first) 0 + else if (i > ranges.last().first) branches.size - 1 + else ranges.indexOfFirst { it.first <= i && i <= it.second } + val (l, r) = branches[t] + val range = l.totalTrees * r.totalTrees + val mod = i mod range +// val q = i - ranges[t].first +// val ratio = (l.totalTrees * 10000) / r.totalTrees +// val iLeft = (mod * ratio) / 10000 +// val iRight = i - numLeft +// val (iLeft, iRight) = q.divrem(r.totalTrees) + val iLeft = mod + val iRight = range - mod +// val (iLeft, iRight) = mod.divrem(r.totalTrees) + + val left = l.newDecoder(iLeft) + val right = r.newDecoder(iRight) + return if (left.isEmpty()) right else if (right.isEmpty()) left else "$left $right" + } + // Average time: 436.96ms, total time 43696.959ms (testRandomCFG) private fun decodeString(i: BigInteger): Pair { - if (branches.isEmpty()) return (epsStr) to i + if (branches.isEmpty()) return epsStr to i 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") + val concat = (if (l.isEmpty()) r else if (r.isEmpty()) l else "$l $r") return concat to quotient3 } // Average time: 328.99ms, total time 32899.708ms (testRandomCFG) private fun decodeStringFast(i: Long): Pair { - if (branches.isEmpty()) return (epsStr) to i + if (branches.isEmpty()) return epsStr to i val (quotient1, remainder) = i / branches.size.toLong() to (i % branches.size.toLong()) val (lb, rb) = shuffledBranches[remainder.toInt()] val (l, quotient2) = lb.decodeStringFast(quotient1) val (r, quotient3) = rb.decodeStringFast(quotient2) - val concat = (if(l.isEmpty()) r else if(r.isEmpty()) l else "$l $r") + val concat = (if (l.isEmpty()) r else if (r.isEmpty()) l else "$l $r") return concat to quotient3 } @@ -130,6 +163,7 @@ class PTree(val root: String = ".ε", val branches: List<Π2A> = listOf() sequence { var i = BigInteger.ZERO while (i < 9 * totalTrees) yield(decodeString(i++ * stride + offset).first) +// while (i < 9 * totalTrees) yield(newDecoder(i++ * stride + offset)) } fun sampleStrWithPCFG5(pcfgTable: Map): Sequence = diff --git a/src/jvmTest/kotlin/ai/hypergraph/kaliningraph/automata/WFSATest.kt b/src/jvmTest/kotlin/ai/hypergraph/kaliningraph/automata/WFSATest.kt index 18e1937e..17e7c26b 100644 --- a/src/jvmTest/kotlin/ai/hypergraph/kaliningraph/automata/WFSATest.kt +++ b/src/jvmTest/kotlin/ai/hypergraph/kaliningraph/automata/WFSATest.kt @@ -71,8 +71,10 @@ class WFSATest { val toRepair = "NAME : NEWLINE NAME = STRING NEWLINE NAME = NAME . NAME ( STRING ) NEWLINE" val radius = 1 val pt = Grammars.seq2parsePythonCFG.makeLevPTree(toRepair, radius, shortS2PParikhMap) - val repairs = pt.sampleStrWithoutReplacement().distinct().take(100).toSet() - println("Found ${repairs.size} repairs by enumerating PTree") + println(pt.totalTrees.toString()) + val maxResults = 10_000 + val repairs = pt.sampleStrWithoutReplacement() + .distinct().take(maxResults).toSet() measureTimedValue { pt.propagator>( both = { a, b -> if (a == null) b else if (b == null) a else Concatenation(a, b) }, @@ -85,12 +87,24 @@ class WFSATest { addTransition(s1, s2, a.root, 1.0) } } - )?.also { println("\n" + Operations.determinizeER(it).toDot().alsoCopy() + "\n") } - .also { println("Total: ${Automata.transitions(it).size} arcs, ${Automata.states(it).size}") } - .let { Automata.bestStrings(it, 1000).map { it.label.joinToString(" ") }.toSet() } + ) +// ?.also { println("\n" + Operations.determinizeER(it).toDot().alsoCopy() + "\n") } +// .also { println("Total: ${Automata.transitions(it).size} arcs, ${Automata.states(it).size}") } + .let { Automata.bestStrings(it, maxResults).map { it.label.joinToString(" ") }.toSet() } }.also { - println("Found ${it.value.size} repairs by decoding WFSA") - assertEquals(it.value, repairs) + println("Found ${it.value.size} unique repairs by decoding WFSA") + println("Found ${repairs.size} unique repairs by enumerating PTree") + +// // Print side by side comparison of repairs +// repairs.sorted().forEach { +// val a = it +// val b = if (it in repairs) it else "" +// val colorA = levenshteinAlign(toRepair, a).paintANSIColors() +// val colorB = if (b.isEmpty()) "" else levenshteinAlign(toRepair, b).paintANSIColors() +// println("$colorA\n$colorB\n") +// } + + assertEquals(it.value.size, repairs.size) it.value.forEach { println(levenshteinAlign(toRepair, it).paintANSIColors()) assertTrue(levenshtein(toRepair, it) <= radius) @@ -98,4 +112,21 @@ class WFSATest { } }.also { println("Decoding ${it.value.size} repairs took ${it.duration}") } } + +/* +./gradlew jvmTest --tests "ai.hypergraph.kaliningraph.automata.WFSATest.testBijection" +*/ + @Test + fun testBijection() { + val toRepair = "NAME : NEWLINE NAME = STRING NEWLINE NAME = NAME ( STRING ) NEWLINE" + val radius = 2 + val pt = Grammars.seq2parsePythonCFG.makeLevPTree(toRepair, radius, shortS2PParikhMap) + println(pt.totalTrees.toString()) + val maxResults = 10_000 + val repairs = pt.sampleStrWithoutReplacement().take(maxResults).toList() + println("Found ${repairs.size} total repairs by enumerating PTree") + val distinct = repairs.toSet().size + // Why so many duplicates? A true bijection should have no duplicates + println("Found $distinct unique repairs by enumerating PTree") + } } \ No newline at end of file