Skip to content

Instantly share code, notes, and snippets.

@fomkin
Last active May 16, 2017 09:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fomkin/0f14d58e093f0026203728cb275bd1fd to your computer and use it in GitHub Desktop.
Save fomkin/0f14d58e093f0026203728cb275bd1fd to your computer and use it in GitHub Desktop.
import shapeless._
import shapeless.nat._
import shapeless.ops.nat.GT._
import shapeless.ops.nat.GTEq._
import shapeless.ops.nat._
import shapeless.syntax.sized._
import scala.collection.mutable
/**
* Concurrent mutable Markov's Chain
*/
final class MarkovChain[Order <: Nat, T] private (implicit n: ToInt[Order]) {
import MarkovChain.SizedVectorOps
type Probs = Map[T, Int]
type State = Sized[Vector[T], Order]
def apply(state: State): Probs = this.synchronized {
dict(state)
}
def add[S <: Nat : ToInt](sentence: Sized[Vector[T], S])
(implicit ev: S > Order): this.type = this.synchronized {
sentence.sliding[Succ[Order]] foreach { xs =>
val value = xs.last
val state = xs.take[Order]
val probs = dict.getOrElse(state, Map.empty)
val newProb = probs.getOrElse(value, 0) + 1
dict.put(state, probs.updated(value, newProb))
}
this
}
private val dict = mutable.Map
.empty[State, Probs]
.withDefaultValue(Map.empty)
}
object MarkovChain {
def firstOrder[T] = new MarkovChain[_1, T]
def secondOrder[T] = new MarkovChain[_2, T]
def thirdOrder[T] = new MarkovChain[_3, T]
def nOrder[N <: Nat: ToInt, T] = new MarkovChain[N, T]
implicit final class SizedVectorOps[S <: Nat : ToInt, T](xs: Sized[Vector[T], S]) {
def sliding[M <: Nat : ToInt](implicit ev: S >= M): Iterator[Sized[Vector[T], M]] = {
xs.unsized.sliding(toInt[M]).map(_.ensureSized[M])
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment