All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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