com.nicopolyptic.state.Automaton.scala Maven / Gradle / Ivy
The newest version!
/**
*
* _ ___ __ __ _
* / | / (_)________ ____ ____ / /_ ______ / /_(_)____
* / |/ / / ___/ __ \/ __ \/ __ \/ / / / / __ \/ __/ / ___/
* / /| / / /__/ /_/ / /_/ / /_/ / / /_/ / /_/ / /_/ / /__
* /_/ |_/_/\___/\____/ .___/\____/_/\__, / .___/\__/_/\___/
* /_/ /____/_/
*
**/
package com.nicopolyptic.state
import scala.annotation.tailrec
import scala.collection.immutable.BitSet
import scala.collection.mutable
private case class Transition[X](s: BitSet, x:X, target: BitSet)
protected case class Automaton[X](transitions: Map[BitSet, Map[X, BitSet]], initialState: BitSet, acceptingState: BitSet) {
def accepts[S](s : Seq[S])(implicit i : Interpretation[X,S]) : Boolean = accepts(initialState, s)
@tailrec
private def accepts[S](s : BitSet, trace : Seq[S])(implicit i : Interpretation[X,S]): Boolean = {
if (trace.isEmpty) {
return false
}
val xs = transitions(s).keys.filter(x => i.matches(x, trace(0)) || i.wildcard.equals(x)).toList
if (xs.isEmpty) {
return false
}
val x = xs.filterNot(i.wildcard.equals).headOption.getOrElse(xs.head)
val next = transitions(s)(x)
if (!next.intersect(acceptingState).isEmpty && trace.tail.isEmpty) {
return true
}
accepts(next, trace.tail)
}
}
protected object Automaton {
def create[X](e : Exp[X]) : Automaton[X] = {
var next = new mutable.HashMap[Int, mutable.Set[Int]] with mutable.MultiMap[Int, Int]
Exp.next(e).foreach({case (k,v) => next.addBinding(k,v)})
val marker = Exp.nextId
for (l <- Exp.last(e)) {
next.addBinding(l, marker)
}
val labels = (for (a <- Exp.leaves(e)) yield a.id -> a).toMap
val initialState = bitSet(Exp.first(e))
var states = mutable.Set(bitSet(initialState))
var done = mutable.Set[BitSet]()
val ts = mutable.Set[Transition[X]]()
while (!states.isEmpty) {
val b = states.take(1).toSeq(0)
states -= b
done += b
val ts1 = for ((x,as) <- (for (id <- b - marker) yield labels(id)).groupBy(a => a.x))
yield Transition(b, x, bitSet(as.flatMap(a => next(a.id))))
states ++= ts1.map(t => t.target).filterNot(done.contains).filterNot(marker.equals)
ts ++= ts1
}
val tMap = for (t <- ts.groupBy(t => t.s)) yield t._1 -> (for (t2 <- t._2) yield t2.x -> t2.target).toMap
Automaton(tMap, initialState, BitSet(marker))
}
private def bitSet[X](as : Iterable[Int]) = BitSet() ++ as
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy