diff --git a/src/commonMain/kotlin/ai/hypergraph/kaliningraph/parsing/BarHillel.kt b/src/commonMain/kotlin/ai/hypergraph/kaliningraph/parsing/BarHillel.kt index 217bd929..903968d7 100644 --- a/src/commonMain/kotlin/ai/hypergraph/kaliningraph/parsing/BarHillel.kt +++ b/src/commonMain/kotlin/ai/hypergraph/kaliningraph/parsing/BarHillel.kt @@ -294,6 +294,15 @@ fun FSA.SPLP(a: STC, b: STC): IntRange { else rng..manhattanDistance(a.coords(), b.coords()) } +fun SPLPArith(a: STC, b: STC): IntRange { + val (xdiff, ydiff) = (b.coords().first - a.coords().first) to (b.coords().second - a.coords().second) + val lp = manhattanDistance(a.coords(), b.coords()) + return (if (xdiff < 0 || ydiff < 0) Int.MAX_VALUE..Int.MAX_VALUE + else if (xdiff == ydiff + 1) 1..lp + else if (xdiff > ydiff + 1) (xdiff - ydiff)..lp + else ((ydiff - xdiff) + 2).coerceAtMost(ydiff)..lp)//.also { if (it != SPLP(a, b)) println("INEQ!: $a,$b") } +} + fun IntRange.overlaps(other: IntRange) = (other.first in first..last) || (other.last in first..last) diff --git a/src/jvmMain/kotlin/ai/hypergraph/kaliningraph/parsing/JVMBarHillel.kt b/src/jvmMain/kotlin/ai/hypergraph/kaliningraph/parsing/JVMBarHillel.kt index 0d2e1372..3225cfb0 100644 --- a/src/jvmMain/kotlin/ai/hypergraph/kaliningraph/parsing/JVMBarHillel.kt +++ b/src/jvmMain/kotlin/ai/hypergraph/kaliningraph/parsing/JVMBarHillel.kt @@ -10,7 +10,6 @@ import kotlin.streams.* import kotlin.time.Duration.Companion.minutes import kotlin.time.TimeSource import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.atomic.* fun CFG.parallelEnumSeqMinimalWOR( prompt: List, @@ -226,9 +225,7 @@ fun CFG.jvmIntersectLevFSAP(fsa: FSA, parikhMap: ParikhMap = this.parikhMap): CF // Checks whether the length bounds for the nonterminal (i.e., the range of the number of terminals it can // parse) is compatible with the range of path lengths across all paths connecting two states in an FSA. // This is a coarse approximation, but is cheaper to compute, so it filters out most invalid triples. - && parikhMap.ntLengthBounds[it.π3].overlaps( - fsa.SPLP(it.π1, it.π2) - ) + && parikhMap.ntLengthBounds[it.π3].overlaps(SPLPArith(it.π1, it.π2)) // Checks the Parikh map for compatibility between the CFG nonterminals and state pairs in the FSA. // This is a finer grained filter, but more expensive to compute, so we use the coarse filter first && fsa.obeys(it.π1, it.π2, it.π3, parikhMap) @@ -241,7 +238,7 @@ fun CFG.jvmIntersectLevFSAP(fsa: FSA, parikhMap: ParikhMap = this.parikhMap): CF val states = fsa.stateLst val allsym = ntLst - val counter = AtomicInteger(0) + var counter = 0 val lpClock = TimeSource.Monotonic.markNow() val binaryProds = prods.parallelStream().flatMap { @@ -256,7 +253,7 @@ fun CFG.jvmIntersectLevFSAP(fsa: FSA, parikhMap: ParikhMap = this.parikhMap): CF // .filter { it.obeysLevenshteinParikhBounds(A to B to C, fsa, parikhMap) } .filter { it.checkCompatibility(trip, ct2) } .map { (a, b, c) -> - if (MAX_PRODS < counter.incrementAndGet()) throw Exception("∩-grammar has too many productions! (>$MAX_PRODS)") + if (MAX_PRODS < counter++) throw Exception("∩-grammar has too many productions! (>$MAX_PRODS)") val (p, q, r) = states[a] to states[b] to states[c] // "[$p~${allsym[A]}~$r]".also { nts.add(listOf(p, allsym[A], r)) } to listOf("[$p~${allsym[B]}~$q]", "[$q~${allsym[C]}~$r]") listOf(p, allsym[A], r).also { nts.add(it) } to listOf(listOf(p, allsym[B], q), listOf(q, allsym[C], r))